diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b5f331216c7d0ea9e534bd35785d622d9420a6b..b6f5116f7bc1f3fd3ab209110ac08558a55e51d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,13 @@ # .gitlab-ci.yml -# + + + stages: + - merge-test - test - build - publish + - deploy image: parity/rust:nightly @@ -16,11 +20,7 @@ variables: -cache: - key: "${CI_JOB_NAME}" - paths: - - ./.cargo/ - +cache: {} .collect_artifacts: &collect_artifacts artifacts: @@ -32,85 +32,170 @@ cache: +.kubernetes_build: &kubernetes_build + tags: + - kubernetes-parity-build + environment: + name: parity-build + + + +#### stage: merge-test + +check:merge:conflict: + stage: merge-test + image: parity/tools:latest + cache: {} + <<: *kubernetes_build + only: + - /^[0-9]+$/ + variables: + GITHUB_API: "https://api.github.com" + GITLAB_API: "https://gitlab.parity.io/api/v4" + GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api" + script: + - ./scripts/gitlab/check_merge_conflict.sh + + + #### stage: test +check:runtime: + stage: test + image: parity/tools:latest + cache: {} + <<: *kubernetes_build + only: + - /^[0-9]+$/ + variables: + GITLAB_API: "https://gitlab.parity.io/api/v4" + GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api" + script: + - ./scripts/gitlab/check_runtime.sh + + + test:rust:stable: &test stage: test + cache: + key: "${CI_JOB_NAME}-test" + paths: + - ${CARGO_HOME} + - ./target variables: RUST_TOOLCHAIN: stable + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: -Cdebug-assertions=y TARGET: native + tags: + - linux-docker only: - - triggers - tags - master - schedules - web - - /^pr-[0-9]+$/ - /^[0-9]+$/ - tags: - - linux-docker before_script: + - test -d ${CARGO_HOME} -a -d ./target && + echo "build cache size:" && + du -h --max-depth=2 ${CARGO_HOME} ./target - ./scripts/build.sh script: - time cargo test --all --release --verbose --locked -.optional_test: &optional_test - <<: *test - allow_failure: true - only: - - master +.build_only: &build_only + only: + - master + - tags + - web + + #### stage: build build:rust:linux:release: &build stage: build + cache: + key: "${CI_JOB_NAME}-build" + paths: + - ${CARGO_HOME} + - ./target <<: *collect_artifacts - only: - - master - - tags - - web + <<: *build_only tags: - linux-docker before_script: - ./scripts/build.sh script: - - time cargo build --release --verbose; + - time cargo build --release --verbose - mkdir -p ./artifacts - mv ./target/release/substrate ./artifacts/. - echo -n "Substrate version = " - - ./artifacts/substrate --version | - sed -n -r 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | - tee ./artifacts/VERSION + - if [ "${CI_COMMIT_TAG}" ]; then + echo "${CI_COMMIT_TAG}" | tee ./artifacts/VERSION; + else + ./artifacts/substrate --version | + sed -n -r 's/^substrate ([0-9.]+.*-[0-9a-f]{7,13})-.*$/\1/p' | + tee ./artifacts/VERSION; + fi - sha256sum ./artifacts/substrate | tee ./artifacts/substrate.sha256 + - echo "\n# building node-template\n" + - ./scripts/node-template-release.sh ./artifacts/substrate-node-template.tar.gz + - cp -r scripts/docker/* ./artifacts + + + +build:rust:doc:release: &build + stage: build + allow_failure: true + artifacts: + name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}-doc" + when: on_success + expire_in: 7 days + paths: + - ./crate-docs + <<: *build_only + tags: + - linux-docker + script: + - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds + - time cargo +nightly doc --release --verbose + - cp -R ./target/doc ./crate-docs + - echo "" > ./crate-docs/index.html #### stage: publish -.publish: &publish +.publish_build: &publish_build stage: publish dependencies: - build:rust:linux:release cache: {} - only: - - master - - tags - - web + <<: *build_only + <<: *kubernetes_build + publish:docker:release: - <<: *publish - tags: - - shell + <<: *publish_build + image: docker:stable + services: + - docker:dind + # collect VERSION artifact here to pass it on to kubernetes + <<: *collect_artifacts variables: + DOCKER_HOST: tcp://localhost:2375 + DOCKER_DRIVER: overlay2 GIT_STRATEGY: none - DOCKERFILE: scripts/docker/Dockerfile + # DOCKERFILE: scripts/docker/Dockerfile CONTAINER_IMAGE: parity/substrate script: - VERSION="$(cat ./artifacts/VERSION)" @@ -118,15 +203,20 @@ publish:docker:release: || ( echo "no docker credentials provided"; exit 1 ) - docker login -u "$Docker_Hub_User_Parity" -p "$Docker_Hub_Pass_Parity" - docker info - - docker build --tag $CONTAINER_IMAGE:$VERSION --tag $CONTAINER_IMAGE:latest -f $DOCKERFILE ./artifacts/ + - cd ./artifacts + - docker build --tag $CONTAINER_IMAGE:$VERSION --tag $CONTAINER_IMAGE:latest . - docker push $CONTAINER_IMAGE:$VERSION - docker push $CONTAINER_IMAGE:latest after_script: - docker logout + # only VERSION information is needed for the deployment + - find ./artifacts/ -depth -not -name VERSION -not -name artifacts -delete + + publish:s3:release: - <<: *publish + <<: *publish_build image: parity/awscli:latest variables: GIT_STRATEGY: none @@ -134,10 +224,96 @@ publish:s3:release: PREFIX: "substrate/${ARCH}-${DOCKER_OS}" script: - aws s3 sync ./artifacts/ s3://${BUCKET}/${PREFIX}/$(cat ./artifacts/VERSION)/ + - echo "update objects in latest path" + - for file in ./artifacts/*; do + name="$(basename ${file})"; + aws s3api copy-object + --copy-source ${BUCKET}/${PREFIX}/$(cat ./artifacts/VERSION)/${name} + --bucket ${BUCKET} --key ${PREFIX}/latest/${name}; + done + after_script: + - aws s3 ls s3://${BUCKET}/${PREFIX}/latest/ + --recursive --human-readable --summarize + + + +publish:s3:doc: + stage: publish + allow_failure: true + dependencies: + - build:rust:doc:release + cache: {} + <<: *build_only + <<: *kubernetes_build + variables: + GIT_STRATEGY: none + BUCKET: "releases.parity.io" + PREFIX: "substrate-rustdoc" + script: + - test -r ./crate-docs/index.html || ( + echo "./crate-docs/index.html not present, build:rust:doc:release job not complete"; + exit 1 + ) + - aws s3 sync --delete --size-only --only-show-errors + ./crate-docs/ s3://${BUCKET}/${PREFIX}/ after_script: - aws s3 ls s3://${BUCKET}/${PREFIX}/ + --human-readable --summarize + + + + + + + +.deploy:template: &deploy + stage: deploy + when: manual + cache: {} + dependencies: + - publish:docker:release + retry: 1 + image: parity/kubectl-helm:$HELM_VERSION + <<: *build_only + # variables: + # DEPLOY_TAG: "latest" tags: - - linux-docker + - kubernetes-parity-build + before_script: + - test -z "${DEPLOY_TAG}" && + test -f ./artifacts/VERSION && + DEPLOY_TAG="$(cat ./artifacts/VERSION)" + - test "${DEPLOY_TAG}" || ( echo "Neither DEPLOY_TAG nor VERSION information available"; exit 1 ) + script: + - echo "Substrate version = ${DEPLOY_TAG}" + # or use helm to render the template + - helm template + --values ./scripts/kubernetes/values.yaml + --set image.tag=${DEPLOY_TAG} + --set validator.keys=${VALIDATOR_KEYS} + ./scripts/kubernetes | kubectl apply -f - --dry-run=false + - echo "# substrate namespace" + - kubectl -n substrate get all + - echo "# substrate's nodes' external ip addresses:" + - kubectl get nodes -l node=substrate + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range @.status.addresses[?(@.type=="ExternalIP")]}{.address}{"\n"}{end}' + - echo "# substrate' nodes" + - kubectl -n substrate get pods + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}' + + + +# have environment:url eventually point to the logs + +deploy:ew3: + <<: *deploy + environment: + name: parity-prod-ew3 + +deploy:ue1: + <<: *deploy + environment: + name: parity-prod-ue1 diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc index 94b3c44e1b3ed97025b8574ebf938b7151c3b9dc..7098869dcc4a0e157945042812fd72826f0bc94f 100644 --- a/CONTRIBUTING.adoc +++ b/CONTRIBUTING.adoc @@ -10,20 +10,27 @@ Individuals making significant and valuable contributions are given commit-acces There are a few basic ground-rules for contributors (including the maintainer(s) of the project): -. **No `--force` pushes** or modifying the Git history in any way. If you need to rebase, ensure you do it in your own repo. +. **No `--force` pushes** or modifying the master branch history in any way. If you need to rebase, ensure you do it in your own repo. . **Non-master branches**, prefixed with a short name moniker (e.g. `gav-my-feature`) must be used for ongoing work. . **All modifications** must be made in a **pull-request** to solicit feedback from other contributors. . A pull-request *must not be merged until CI* has finished successfully. -. Contributors should adhere to the https://github.com/paritytech/polkadot/wiki/Style-Guide[house coding style]. +. Contributors should adhere to the https://wiki.parity.io/Substrate-Style-Guide[house coding style]. + + +== Merge Process Merging pull requests once CI is successful: -. A pull request that does not alter any logic (e.g. comments, dependencies, docs) may be tagged https://github.com/paritytech/core/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3AA2-insubstantial[`insubstantial`] and merged by its author. -. A pull request with no large change to logic that is an urgent fix may be merged after a non-author contributor has reviewed it well. -. All other PRs should sit for 48 hours with the https://github.com/paritytech/core/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview[`pleasereview`] tag in order to garner feedback. +. A PR needs to be reviewed and approved by project maintainers unless: + - it does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged https://github.com/paritytech/substrate/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3AA2-insubstantial[`insubstantial`] and merged by its author once CI is complete. + - it is an urgent fix with no large change to logic, then it may be merged after a non-author contributor has approved the review once CI is complete. + +. Once a PR is ready for review please add the https://github.com/paritytech/substrate/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview[`pleasereview`] label. Generally PRs should sit with this label for 48 hours in order to garner feedback. It may be merged before if all relevant parties had a look at it. +. PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/B2-breaksapi[`breaksapi`], when it changes the SRML or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`breaksconsensus`] . No PR should be merged until all reviews' comments are addressed. -.Reviewing pull requests: +*Reviewing pull requests*: + When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in: . Buggy behaviour. @@ -33,10 +40,15 @@ When reviewing a pull request, the end-goal is to suggest useful changes to the . Feature reduction (i.e. it removes some aspect of functionality that a significant minority of users rely on). . Uselessness (i.e. it does not strictly add a feature or fix a known issue). -.Reviews may not be used as an effective veto for a PR because: +*Reviews may not be used as an effective veto for a PR because*: + . There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix. . It does not fit well with some other contributors' longer-term vision for the project. +== Helping out + +We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Furthermore we are organising issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task. + == Releases Declaring formal releases remains the prerogative of the project maintainer(s). diff --git a/Cargo.lock b/Cargo.lock index 597721c4d04acf21f66d1cc81e088e03ff010426..f5213844424da4fe8afe0faafe135c86099fe126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,32 +1,42 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "MacTypes-sys" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "aes-ctr" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aes-soft" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aesni" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -34,27 +44,22 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aio-limited" version = "0.1.0" -source = "git+https://github.com/paritytech/aio-limited.git#f01b01501c87c93d3005f9120cc35d0e576fa7a3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ansi_term" version = "0.11.0" @@ -71,7 +76,7 @@ dependencies = [ "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -81,7 +86,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -89,59 +94,66 @@ dependencies = [ [[package]] name = "asn1_der" -version = "0.5.10" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "etrace 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "assert_matches" -version = "1.3.0" +name = "asn1_der_derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "aster" -version = "0.41.0" +name = "assert_matches" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base-x" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -151,20 +163,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "base64" -version = "0.7.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -172,53 +183,49 @@ name = "bigint" version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bindgen" -version = "0.29.1" +version = "0.43.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.9.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#c2d8d196e30b018d1385be8357fdca61b978facf" [[package]] name = "blake2" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -226,25 +233,44 @@ name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-buffer" -version = "0.3.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "block-cipher-trait" -version = "0.5.3" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -257,33 +283,38 @@ name = "byte-tools" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" -version = "0.4.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cast" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -291,25 +322,16 @@ dependencies = [ [[package]] name = "cexpr" -version = "0.2.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cfg-if" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "chashmap" -version = "2.2.0" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "chrono" @@ -318,17 +340,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clang-sys" -version = "0.21.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -351,7 +373,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -367,7 +389,7 @@ name = "cmake" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -381,7 +403,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -389,54 +411,66 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "criterion" -version = "0.1.2" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-stats 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "criterion-plot" -version = "0.1.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "criterion-stats" -version = "0.1.3" +name = "crossbeam" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam" -version = "0.2.12" +name = "crossbeam-channel" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-deque" @@ -449,11 +483,11 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -461,8 +495,8 @@ name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -472,12 +506,12 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -488,20 +522,16 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam-utils" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -516,29 +546,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crypto-mac" -version = "0.5.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crypto-mac" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ctr" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -551,39 +598,29 @@ dependencies = [ ] [[package]] -name = "curve25519-dalek" -version = "0.20.0" +name = "cuckoofilter" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "data-encoding" -version = "2.1.1" +name = "curve25519-dalek" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "datastore" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" dependencies = [ - "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "difference" -version = "1.0.0" +name = "data-encoding" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -593,10 +630,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "digest" -version = "0.7.6" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -604,17 +649,25 @@ name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ed25519-dalek" -version = "0.8.1" +version = "1.0.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -632,22 +685,13 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.5.13" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -661,51 +705,35 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "eth-secp256k1" -version = "0.5.7" -source = "git+https://github.com/paritytech/rust-secp256k1#ccc06e7480148b723eb44ac56cf4d20eec380b6f" -dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "etrace" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "exit-future" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -719,20 +747,20 @@ name = "fdlimit" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "finality-grandpa" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -740,10 +768,10 @@ name = "fixed-hash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -766,17 +794,29 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fork-tree" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fs-swap" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -802,7 +842,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -812,20 +852,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "generic-array" -version = "0.9.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "getset" -version = "0.0.6" +name = "generic-array" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -841,38 +880,47 @@ dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "h2" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hash-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -885,7 +933,7 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -898,7 +946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -915,19 +963,39 @@ dependencies = [ [[package]] name = "hmac" -version = "0.6.3" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -939,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "humantime" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -955,8 +1023,8 @@ dependencies = [ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -965,27 +1033,27 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.17" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -996,11 +1064,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "indexmap" +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1019,29 +1104,13 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "isatty" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itertools" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "itertools" -version = "0.5.10" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1054,86 +1123,92 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "jsonrpc-http-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +name = "jsonrpc-derive" +version = "10.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "jsonrpc-macros" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +name = "jsonrpc-http-server" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-pubsub" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#0d78b8f145c18f08c1103f6b0b51991a89fb0a6f" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.9 (git+https://github.com/tomusdrw/ws-rs)", + "parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "keccak-hasher" +name = "keccak" version = "0.1.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "keccak-hasher" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1149,35 +1224,35 @@ dependencies = [ [[package]] name = "kvdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "kvdb-memorydb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "kvdb-rocksdb" version = "0.1.4" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rocksdb 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1185,11 +1260,6 @@ name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.2.0" @@ -1197,367 +1267,398 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.43" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libloading" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-dns 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-floodsub 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-kad 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-mplex 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ratelimit 0.1.1 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-relay 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-secio 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-tcp-transport 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-transport-timeout 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-uds 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-websocket 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-yamux 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ratelimit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libp2p-core-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libp2p-dns" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-floodsub" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-identify" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-kad" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mdns" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mplex" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-peerstore" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-noise" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ping" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-ratelimit" -version = "0.1.1" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-plaintext" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-relay" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-ratelimit" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-secio" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-tcp-transport" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "tk-listen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-transport-timeout" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-tcp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-uds" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-websocket" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-yamux" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.1.0 (git+https://github.com/paritytech/yamux)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "librocksdb-sys" -version = "5.11.3" +version = "5.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bindgen 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libsecp256k1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "linked-hash-map" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "linked_hash_set" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1574,31 +1675,21 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "make-cmd" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mashup" -version = "0.1.9" +name = "lru-cache" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "mashup-impl" -version = "0.1.9" +name = "make-cmd" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "matches" @@ -1607,20 +1698,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memchr" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1630,10 +1712,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1642,6 +1724,18 @@ name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "merlin" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.2.6" @@ -1659,12 +1753,12 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1673,10 +1767,10 @@ name = "mio-extras" version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1685,7 +1779,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1700,44 +1794,18 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multiaddr" -version = "0.3.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "multihash" -version = "0.8.1-pre" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "blake2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "multistream-select" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1745,7 +1813,7 @@ name = "names" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1754,15 +1822,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1770,8 +1838,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1781,9 +1849,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1791,46 +1859,48 @@ dependencies = [ name = "node-cli" version = "0.1.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "node-executor 0.1.0", "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", - "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-basic-authorship 0.1.0", "substrate-cli 0.3.0", "substrate-client 0.1.0", "substrate-consensus-aura 0.1.0", "substrate-finality-grandpa 0.1.0", + "substrate-inherents 0.1.0", "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-service 0.3.0", "substrate-service-test 0.3.0", + "substrate-telemetry 0.3.1", "substrate-transaction-pool 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-executor" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-contract 0.1.0", + "srml-fees 0.1.0", "srml-grandpa 0.1.0", + "srml-indices 0.1.0", "srml-session 0.1.0", "srml-staking 0.1.0", "srml-support 0.1.0", @@ -1842,19 +1912,19 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", - "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1865,13 +1935,13 @@ dependencies = [ name = "node-runtime" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -1882,9 +1952,13 @@ dependencies = [ "srml-council 0.1.0", "srml-democracy 0.1.0", "srml-executive 0.1.0", + "srml-fees 0.1.0", + "srml-finality-tracker 0.1.0", "srml-grandpa 0.1.0", + "srml-indices 0.1.0", "srml-session 0.1.0", "srml-staking 0.1.0", + "srml-sudo 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", @@ -1896,6 +1970,63 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "node-template" +version = "0.9.0" +dependencies = [ + "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "node-executor 0.1.0", + "node-template-runtime 0.9.0", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "substrate-basic-authorship 0.1.0", + "substrate-cli 0.3.0", + "substrate-client 0.1.0", + "substrate-consensus-aura 0.1.0", + "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", + "substrate-network 0.1.0", + "substrate-primitives 0.1.0", + "substrate-service 0.3.0", + "substrate-transaction-pool 0.1.0", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "node-template-runtime" +version = "0.9.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-aura 0.1.0", + "srml-balances 0.1.0", + "srml-consensus 0.1.0", + "srml-executive 0.1.0", + "srml-fees 0.1.0", + "srml-indices 0.1.0", + "srml-sudo 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "srml-timestamp 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "nodrop" version = "0.1.13" @@ -1903,15 +2034,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nohash-hasher" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nom" -version = "3.2.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1922,14 +2054,6 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-traits" version = "0.2.6" @@ -1937,45 +2061,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "0.2.13" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "num_cpus" -version = "1.8.0" +name = "ole32-sys" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ole32-sys" -version = "0.2.0" +name = "once_cell" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.1.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.15" +version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1985,23 +2109,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.39" +version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "owning_ref" -version = "0.2.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "owning_ref" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2010,68 +2137,90 @@ dependencies = [ [[package]] name = "parity-bytes" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" - -[[package]] -name = "parity-bytes" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" [[package]] name = "parity-codec" -version = "2.1.5" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-codec-derive" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-crypto" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parity-wasm" -version = "0.31.3" +name = "parity-multiaddr" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.3.8" +name = "parity-multihash" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.4.8" +name = "parity-wasm" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-ws" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2088,18 +2237,27 @@ name = "parking_lot" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2108,13 +2266,55 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -2132,20 +2332,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pretty_assertions" -version = "0.4.1" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "primitive-types" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "pretty_assertions" -version = "0.5.1" +name = "proc-macro-crate" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2156,6 +2366,16 @@ dependencies = [ "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack-impl" version = "0.4.1" @@ -2163,7 +2383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.3.8" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2171,7 +2391,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2179,39 +2399,19 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.1.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pwasm-utils" -version = "0.3.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quasi" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quasi_codegen" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quick-error" version = "0.1.4" @@ -2227,87 +2427,88 @@ name = "quote" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2315,15 +2516,38 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_isaac" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2331,24 +2555,25 @@ name = "rand_pcg" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rayon" -version = "0.8.2" +name = "rand_xoshiro" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2368,13 +2593,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.40" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2382,47 +2615,32 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "regex" -version = "0.2.11" +name = "ref_thread_local" +version = "0.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "regex" -version = "1.0.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2435,35 +2653,36 @@ dependencies = [ [[package]] name = "rhododendron" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ring" -version = "0.12.1" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocksdb" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "librocksdb-sys 5.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2472,20 +2691,15 @@ version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-hex" -version = "1.0.0" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2508,12 +2722,12 @@ dependencies = [ [[package]] name = "rw-stream-sink" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2531,13 +2745,16 @@ dependencies = [ [[package]] name = "safemem" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "safemem" -version = "0.3.0" +name = "same-file" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "schannel" @@ -2549,33 +2766,55 @@ dependencies = [ ] [[package]] -name = "scoped-tls" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "schnorrkel" +version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#d3289df76b8ae6dfb68e733204c5c009df5343a9" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "secp256k1" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "security-framework" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2593,72 +2832,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.80" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.80" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sha1" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "sha1" +name = "sha2" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "sha2" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "shell32-sys" -version = "0.1.2" +name = "sha3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "simplelog" -version = "0.4.4" +name = "shell32-sys" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2678,46 +2926,70 @@ dependencies = [ [[package]] name = "slog-json" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slog-scope" -version = "4.0.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "snow" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sr-api-macros" version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", "substrate-primitives 0.1.0", + "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2725,13 +2997,15 @@ name = "sr-io" version = "0.1.0" dependencies = [ "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2741,11 +3015,10 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -2756,12 +3029,12 @@ name = "sr-sandbox" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", - "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2775,10 +3048,10 @@ dependencies = [ name = "sr-version" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -2787,10 +3060,9 @@ dependencies = [ name = "srml-assets" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -2803,20 +3075,22 @@ dependencies = [ name = "srml-aura" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", + "srml-session 0.1.0", "srml-staking 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -2824,11 +3098,10 @@ dependencies = [ name = "srml-balances" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -2842,15 +3115,16 @@ dependencies = [ name = "srml-consensus" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -2859,31 +3133,35 @@ name = "srml-contract" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-sandbox 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", + "srml-consensus 0.1.0", + "srml-fees 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "srml-timestamp 0.1.0", "substrate-primitives 0.1.0", - "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-council" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -2898,11 +3176,11 @@ dependencies = [ name = "srml-democracy" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -2916,13 +3194,11 @@ dependencies = [ name = "srml-example" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", - "sr-std 0.1.0", "srml-balances 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", @@ -2933,16 +3209,53 @@ dependencies = [ name = "srml-executive" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", + "srml-fees 0.1.0", + "srml-indices 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-fees" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-finality-tracker" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -2950,14 +3263,14 @@ dependencies = [ name = "srml-grandpa" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-consensus 0.1.0", + "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", @@ -2965,14 +3278,32 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "srml-indices" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -2981,11 +3312,11 @@ dependencies = [ name = "srml-session" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -3000,11 +3331,10 @@ dependencies = [ name = "srml-staking" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -3018,63 +3348,97 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "srml-sudo" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-support-procedural 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-metadata 0.1.0", "srml-support-procedural 0.1.0", + "substrate-inherents 0.1.0", ] [[package]] name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-support-test" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "srml-support 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] name = "srml-system" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -3086,15 +3450,15 @@ dependencies = [ name = "srml-timestamp" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -3102,10 +3466,10 @@ dependencies = [ name = "srml-treasury" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -3119,18 +3483,13 @@ dependencies = [ name = "srml-upgrade-key" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", - "srml-support-procedural 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] @@ -3144,20 +3503,20 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "stdweb" -version = "0.1.3" +name = "static_slice" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "stdweb" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-runtime 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3165,44 +3524,44 @@ name = "stdweb-derive" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "stdweb-internal-macros" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base-x 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "stdweb-internal-runtime" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "stream-cipher" -version = "0.1.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3212,42 +3571,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "subkey" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "substrate-primitives 0.1.0", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate" -version = "0.9.0" +version = "0.10.0" dependencies = [ "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "node-cli 0.1.0", - "vergen 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-basic-authorship" +version = "0.1.0" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", + "substrate-telemetry 0.3.1", + "substrate-test-client 0.1.0", + "substrate-transaction-pool 0.1.0", +] + +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3257,28 +3649,29 @@ dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", - "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", "substrate-network 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-service 0.3.0", - "substrate-telemetry 0.3.0", - "sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-state-machine 0.1.0", + "substrate-telemetry 0.3.1", + "sysinfo 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3288,25 +3681,25 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", - "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", - "substrate-telemetry 0.3.0", + "substrate-telemetry 0.3.1", "substrate-test-client 0.1.0", "substrate-trie 0.4.0", ] @@ -3315,14 +3708,15 @@ dependencies = [ name = "substrate-client-db" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", - "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", - "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-executor 0.1.0", @@ -3338,54 +3732,74 @@ dependencies = [ name = "substrate-consensus-aura" version = "0.1.0" dependencies = [ - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", + "srml-aura 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-aura-slots 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-service 0.3.0", + "substrate-telemetry 0.3.1", "substrate-test-client 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "substrate-client 0.1.0", +] + +[[package]] +name = "substrate-consensus-aura-slots" +version = "0.1.0" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", - "sr-version 0.1.0", - "srml-support 0.1.0", "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-test-client 0.1.0", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3393,13 +3807,12 @@ name = "substrate-consensus-rhd" version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rhododendron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rhododendron 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", @@ -3408,11 +3821,10 @@ dependencies = [ "srml-system 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", - "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-transaction-pool 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3420,66 +3832,81 @@ name = "substrate-executor" version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-finality-grandpa" version = "0.1.0" dependencies = [ - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "finality-grandpa 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "finality-grandpa 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fork-tree 0.1.0", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", + "srml-finality-tracker 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", "substrate-finality-grandpa-primitives 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-service 0.3.0", + "substrate-telemetry 0.3.1", "substrate-test-client 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-finality-grandpa-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-client 0.1.0", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-inherents" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + [[package]] name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3490,13 +3917,13 @@ version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", - "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3505,16 +3932,19 @@ name = "substrate-network" version = "0.1.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fork-tree 0.1.0", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", @@ -3522,31 +3952,40 @@ dependencies = [ "substrate-network-libp2p 0.1.0", "substrate-primitives 0.1.0", "substrate-test-client 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-network-libp2p" version = "0.1.0" dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3555,26 +3994,31 @@ version = "0.1.0" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "substrate-serializer 0.1.0", - "twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3583,17 +4027,19 @@ version = "0.1.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", @@ -3601,20 +4047,22 @@ dependencies = [ "substrate-executor 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", + "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", + "substrate-test-runtime 0.1.0", "substrate-transaction-pool 0.1.0", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-rpc-servers" version = "0.1.0" dependencies = [ - "jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-http-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-rpc 0.1.0", ] @@ -3623,8 +4071,8 @@ dependencies = [ name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3632,41 +4080,41 @@ name = "substrate-service" version = "0.3.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-client-db 0.1.0", - "substrate-consensus-aura-primitives 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-rpc-servers 0.1.0", - "substrate-telemetry 0.3.0", + "substrate-telemetry 0.3.1", + "substrate-test-client 0.1.0", "substrate-transaction-pool 0.1.0", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-service-test" version = "0.3.0" dependencies = [ - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", @@ -3674,18 +4122,17 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-service 0.3.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-db" version = "0.1.0" dependencies = [ - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3693,29 +4140,33 @@ dependencies = [ name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" -version = "0.3.0" +version = "0.3.1" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-json 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3723,9 +4174,11 @@ dependencies = [ name = "substrate-test-client" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", + "substrate-client-db 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", "substrate-keyring 0.1.0", @@ -3738,21 +4191,25 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", + "srml-executive 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-test-client 0.1.0", ] [[package]] @@ -3763,9 +4220,10 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-test-runtime 0.1.0", ] @@ -3777,8 +4235,8 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-keyring 0.1.0", @@ -3791,56 +4249,36 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "criterion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.1.0 (git+https://github.com/paritytech/trie)", - "memory-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", - "trie-bench 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-standardmap 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-bench 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "subtle" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "subtle" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "syn" -version = "0.13.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.14.9" +name = "subtle" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "syn" -version = "0.15.22" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3849,61 +4287,19 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_errors" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_pos" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_syntax" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sysinfo" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3923,32 +4319,23 @@ name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "term" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "termcolor" version = "1.0.4" @@ -3962,8 +4349,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3975,21 +4362,6 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread-scoped" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "thread_local" version = "0.3.6" @@ -4000,14 +4372,28 @@ dependencies = [ [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.2" @@ -4016,36 +4402,47 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tinytemplate" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tk-listen" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.11" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4053,170 +4450,173 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-dns-unofficial" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tls" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4226,46 +4626,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "trie-bench" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "criterion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "keccak-hasher 0.1.0 (git+https://github.com/paritytech/trie)", - "memory-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-standardmap 0.9.0 (git+https://github.com/paritytech/trie)", + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-standardmap" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "criterion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "keccak-hasher 0.1.0 (git+https://github.com/paritytech/trie)", + "criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4275,20 +4675,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "twofish" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "twox-hash" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4303,16 +4703,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4342,8 +4743,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-segmentation" @@ -4355,11 +4759,6 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.1.0" @@ -4375,24 +4774,16 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unsigned-varint" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "untrusted" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -4422,13 +4813,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "vergen" -version = "2.1.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4443,25 +4833,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wabt" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wabt-sys" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "want" version = "0.0.6" @@ -4474,35 +4874,42 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "websocket" -version = "0.21.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "which" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -4529,7 +4936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4546,24 +4953,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws" -version = "0.7.9" -source = "git+https://github.com/tomusdrw/ws-rs#4baef2dc1abc8e216559af51cfc120bbcc777e21" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4571,16 +4961,16 @@ name = "ws" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4595,7 +4985,7 @@ dependencies = [ [[package]] name = "xdg" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -4605,61 +4995,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "yamux" -version = "0.1.0" -source = "git+https://github.com/paritytech/yamux#8f3d16e7645447645d3552a52159d56c8a01de27" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f65958ff3692041c36fc009261ccd63f24cd8e0dc1164266f068c2387e8b4e4f" -"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" -"checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" +"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" -"checksum aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)" = "" +"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "766afdc5c6d7c15de1abe4c9c15e360be3aa972c363ba5b606be3c4271235886" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" +"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" -"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" -"checksum base-x 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5cda5d0f5584d129112ad8bf4775b9fd2b9f1e30738c7b1a25314ba2244d6a51" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" -"checksum bindgen 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba610cba0c1727ed837316540068b51349b8268c073906067b7c3948598929bd" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d52d263eacd15d26cbcf215d254b410bd58212aaa2d3c453a04b2d3b3adcf41" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73b77e29dbd0115e43938be2d5128ecf81c0353e00acaa65339a1242586951d9" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -"checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" +"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" -"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0ce55bd354b095246fc34caf4e9e242f5297a7fd938b090cadfea6eee614aa62" -"checksum cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "011941fb53da1a8ac3e4132a1becc367c44fe13f630769f3143d8c66c91c6cb6" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47e651a8c1eb0cbbaa730f705e2531e75276c6f2bbe2eb12662cfd305213dff8" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e414af9726e1d11660801e73ccc7fb81803fb5f49e5903a25b348b2b3b480d2e" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -4667,341 +5060,346 @@ dependencies = [ "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum criterion 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f58b0200bf321214bdda8c797cf0071bcc638171c40ec198c3f652a4edaacde3" -"checksum criterion-plot 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "885431f7865f9d4956b466126674e5ea40a0f193d42157e56630c356c5501957" -"checksum criterion-stats 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c71521cb4c7b7eac76b540e75447fb0172c4234d6333729001b886aaa21d6da4" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1c6e5ee5b9652d4f851418c448af105642e1f99e9a2741a8ff45c0d2c911b1e0" +"checksum criterion-plot 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4107e4a5abb94267e0149922b8ff49dc70a87cc202820fdbfc0d3e1edbdc4b16" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" -"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" -"checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958" -"checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" -"checksum ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b669fcb8e20124db86dbd9b01e74ec0e9e420e65381311ce5249864fc7ff0c0" +"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" +"checksum ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "044f882973b245404e90c90e7e42e8ee8d7a64edfd7adf83d684fb97e8e2c1b6" "checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" -"checksum curve25519-dalek 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eacf6ff1b911e3170a8c400b402e10c86dc3cb166bd69034ebbc2b785fea4c2" -"checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e" -"checksum datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" +"checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956" +"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" +"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -"checksum ed25519-dalek 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cd66d8a16ef71c23cf5eeb2140d8d3cd293457c6c7fd6804b593397a933fcf1e" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" -"checksum etrace 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f17311e68ea07046ee809b8513f6c259518bc10173681d98c21f8c3926f56f40" -"checksum exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9aa7b56cef68c4182db7212dece19cc9f6e2916cf9412e57e6cea53ec02f316d" -"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" -"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum exit-future 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "87559b08e99a81a92bbb867d237543e43495857749f688e0773390a20d56c61c" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" -"checksum finality-grandpa 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a1dffe3c9d4c59d964f25cea31880e56c20414cdae7efe2269411238f850ad39" +"checksum finality-grandpa 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d415e902db2b87bd5a7df7a2b2de97a4566727a23b95ff39e1bfec25a66d4d1c" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "921d332c89b3b61a826de38c61ee5b6e02c56806cade1b0e5d81bd71f57a71bb" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getset 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54c7f36a235738bb25904d6a2b3dbb28f6f5736cd3918c4bf80d6bb236200782" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" -"checksum h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd33bafe2e6370e6c8eb0cf1b8c5f93390b90acde7e9b03723f166b28b648ed" -"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0e5c30fb65e661a0e39860e37100dfbe4d39aff865e9357a6a4ed0b5bbf303" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" -"checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" -"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" +"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" +"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c" -"checksum hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c49a75385d35ff5e9202755f09beb0b878a05c4c363fcc52b23eeb5dcb6782cc" +"checksum hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)" = "860faf61a9957c9cb0e23e69f1c8290e92f6eb660fcdd1f2d6777043a2ae1a46" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" -"checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f" -"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum keccak-hasher 0.1.0 (git+https://github.com/paritytech/trie)" = "" +"checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" +"checksum jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c14be84e86c75935be83a34c6765bf31f97ed6c9163bb0b83007190e9703940a" +"checksum jsonrpc-http-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99e1ce36c7cc9dcab398024d76849ab2cb917ee812653bce6f74fc9eb7c82d16" +"checksum jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56608ed54b1b2a69f4357cb8bdfbcbd99fe1179383c03a09bb428931bd35f592" +"checksum jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5521613b31ea22d36d9f95ad642058dccec846a94ed8690957652d479f620707" +"checksum jsonrpc-ws-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20b8333a5a6e6ccbcf5c90f90919de557cba4929efa164e9bd0e8e497eb20e46" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +"checksum keccak-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb9d3670023f4c04153d90b8a557a822d1b27ed702bb015a87cf7bffead5b611" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" +"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum libp2p 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-dns 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-floodsub 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-kad 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-mplex 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-relay 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-secio 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-uds 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-websocket 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-yamux 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum librocksdb-sys 5.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0fa7f4ca5ceff76237db63802cb073d84e64a327e38478e79a669093fb7fa5" +"checksum libp2p 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395d54c4c96fa175eabf4505e8a7bd616d916fa49fa27c60ceaa6d5d9b51bc" +"checksum libp2p-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c8dc95c7fda9de223bc195b637290918e8decb18e63fd3d03005f84b8ce380b" +"checksum libp2p-core-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e9ff3bb639d0be41e1aff9d0d28715e54474e4d15e43aa4865bdec44867d8d3" +"checksum libp2p-dns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d310aa56671539a2bce6124cf4326482278b0d0b841c3ba1514e44d8597096" +"checksum libp2p-floodsub 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8256d778f0dc087be409d8cbd081a11bc41ea27ddcd4862814e50e8cfa9c6df0" +"checksum libp2p-identify 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d128febfc8fe57b597e627f545bafea43ae009bf85cc9480b583996f244ab685" +"checksum libp2p-kad 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0691fcca7648369798c6466c61139d31dbb7e2afad311e44fcc4e220ce1e4d78" +"checksum libp2p-mdns 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63289f296e39752180d8a45e024cc38d1028a6db41deab3943ff2ccb9d1224cd" +"checksum libp2p-mplex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "791e375a6a230568f0d8f56f6236403de8e4bf4bd870c3c5f605fd1778da70b2" +"checksum libp2p-noise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70d28b0ca9eb9818d45e037b4a8a0915553c5c1f8d878d8d6170f60451ad37d2" +"checksum libp2p-ping 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53db5fafd4ca0a32f339371198196795b8e14d8ecb360d8d03ada03299c12a10" +"checksum libp2p-plaintext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4383404cba7e4483e0b7d78b3ac5e66f8b024233a5095df9da65d5a1e975d692" +"checksum libp2p-ratelimit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bad4fe925d50cc886608ab3b3a7a962b5064ecc49db8b66fd063a950d469c757" +"checksum libp2p-secio 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f9a7641a314d54ad7797f0445685818edb4d3c2f21690cea900f12ea73501b" +"checksum libp2p-tcp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4625bedbb083d676903a8ede4c5c42f9bf7bd5dee788f3cba29d8e01b785d253" +"checksum libp2p-uds 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5f5d900e381b02ebea2f0621555a2f25a7735772355291aeb70fd9e0da3692" +"checksum libp2p-websocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96b6dfdd776a248d7494aeaf22f149b4d5f6784146546bc34f7b094c7162e141" +"checksum libp2p-yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5a6197ae647c963f5a711c6fb00ba07b9a2812df26f6284870221f654fe9313" +"checksum librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9024327233e7fac7982440f73301c00046d438c5b1011e8f4e394226ce19007" +"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" -"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" +"checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" -"checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" -"checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum merlin 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9e97b439f6d38cbe2a4a4aa93f6770c5305f62761b78b1851406c09c87ee2a" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" +"checksum multistream-select 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ed84364f0e921a32204896952ee80c7befc14a7a39f2c56cd955d71e8dae6" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27593c72432b8cec9ae79e92792a73c38341064d525b6b612a9fccf8b7d17407" -"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" +"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" -"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" -"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc" +"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5168b4cf41f3835e4bc6ffb32f51bc9365dc50cb351904595b3931d917fd0c" -"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" -"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" -"checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" +"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum parity-crypto 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b9db194dfbcfe3b398d63d765437a5c7232d59906e203055f0e993f6458ff1" +"checksum parity-multiaddr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61ae6944d4435d41f4d0f12108c5cbb9207cbb14bc8f2b4984c6e930dc9c8e41" +"checksum parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8eab0287ccde7821e337a124dc5a4f1d6e4c25d10cc91e3f9361615dd95076" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9" -"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +"checksum parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fec5048fba72a2e01baeb0d08089db79aead4b57e2443df172fb1840075a233" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28ea5118e2f41bfbc974b28d88c07621befd1fa5d6ec23549be96302a1a59dd2" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "671a9cce836bd3635b40b2b0a72783481755ee988c493891f4e974b45264cc9d" -"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5" -"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" -"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" +"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82d117bc7565ce6be0150159251c9b1eeec7b129f5a2aa86e10acb5970de1cb" +"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" "checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de3f08319b5395bd19b70e73c4c465329495db02dafeb8ca711a20f1c2bd058c" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6ecfe9ebf36acd47a49d150990b047a5f7db0a7236ee2414b7ff5cc1097c7b" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" "checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" +"checksum ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rhododendron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a09bc21b21795c366c8bf0e87afb71175f5f736b3a5b279b6f4e81839d0a877b" -"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" -"checksum rocksdb 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a806011ca1d26f37729ed4dc78afd607cc86d37ee913718108b0b267e768d46f" +"checksum rhododendron 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9381ed76c1ec4e8994f1f7d2c6d7e33eed3ff7176e16fece09c2e993fc4a5a" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" -"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" +"checksum rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d548a40fe17c3a77d54b82457b79fcc9b8a288d509ca20fbf5aa1dac386d22d6" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" -"checksum security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab01dfbe5756785b5b4d46e0289e5a18071dfa9a7c2b24213ea00b9ef9b665bf" +"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" +"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" +"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" -"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" -"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" +"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" -"checksum simplelog 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "24b615b1a3cc51ffa565d9a1d0cfcc49fe7d64737ada84eca284cddb0292d125" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" -"checksum slog-json 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddd14b8df2df39378b3e933c79784350bf715b11444d99f903df0253bbe524e5" -"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" -"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" +"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum snow 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7251f8920e9043106cfe466c04ed3eb257b8315a7699259c4fd0af6dffb6aef6" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" -"checksum stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "22203527a18dc1c5c83bbd247fb005f5877d040783b6626571d6b7ed7a6f5e75" +"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" +"checksum stdweb 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "461e7f2e33670b1c33f1ea22bb2f86de6136fabd0c4d27d167ed425c231143ca" "checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" -"checksum stdweb-internal-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbc9155af9606d44c740197d7d6672b49c4ee93a176c7cecde8b49322677604" -"checksum stdweb-internal-runtime 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b74fe9de4c0d07e91987f4d798b95f27f3cb7769fbc222fa951fa386908297b5" -"checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" -"checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" +"checksum stdweb-internal-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "432465093692af7379dcd196ce4be398c906958d91b412fff9102a66238d6f26" +"checksum stdweb-internal-runtime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a2f4a2eb556337b2d1a302630bbddf989ae383c70393e89b48152b9896cbda" +"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" +"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "41c4a2479a078509940d82773d90ff824a8c89533ab3b59cd3ce8b0c0e369c02" -"checksum structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5352090cfae7a2c85e1a31146268b53396106c88ca5d6ccee2e3fae83b6e35c2" -"checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" +"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3" +"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" -"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" -"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" -"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" -"checksum sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c747a1fbe091faa7bf76c19f40099f9f12495384c811485d81cf3d60c0eae62" +"checksum sysinfo 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4da1ccc493b46042d6f5352910a7f18ed8fe81307dd7db3f2e2d8a7db6f6284" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" -"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +"checksum tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "37daa55a7240c4931c84559f03b3cad7d19535840d1c4a0cc4e9b2fb0dcf70ff" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" -"checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tk-listen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dec7ba6a80b7695fc2abb21af18bed445a362ffd80b64704771ce142d6d2151d" -"checksum tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895" +"checksum tinytemplate 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7655088894274afb52b807bd3c87072daa1fedd155068b8705cabfd628956115" +"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" +"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f90fcd90952f0a496d438a976afba8e5c205fb12123f813d8ab3aa1c8436638c" -"checksum tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb9bf62ca2c53bf2f2faec3e48a98b6d8c9577c27011cb0203a4beacdc8ab328" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4b26fd37f1125738b2170c80b551f69ff6fecb277e6e5ca885e53eec2b005018" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3929aee321c9220ed838ed6c3928be7f9b69986b0e3c22c972a66dbf8a298c68" -"checksum tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3a52f00c97fedb6d535d27f65cccb7181c8dd4c6edc3eda9ea93f6d45d05168e" -"checksum tokio-tls 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e53fdbf3156f588be1676022fe794232b24922d426e8c14f4e46891c1e31c440" -"checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" -"checksum tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df195376b43508f01570bacc73e13a1de0854dc59e79d1ec09913e8db6dd2a70" +"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" +"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-sync 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3742b64166c1ee9121f1921aea5a726098458926a6b732d906ef23b1f3ef6f4f" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-bench 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-root 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-standardmap 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum trie-bench 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77087d1bce467cf8371a5c0e10e4d925b065ec6cfad8b9cdff1fad4f218c6750" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" +"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" +"checksum trie-standardmap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4729504b8102acb1bef3f16e6b64d41aeb1ff0e329081451e8191df0f61ab2" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eef327f05b0d0ec1b9d7d119d8f4d9f602ceee37e0540aff8071e8e66c2e22e" -"checksum twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f85be565a110ed72ed7048cf56570db04ce0a592c98aa59b7dacde3e5718750" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" +"checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f8bfa9ff0cadcd210129ad9d2c5f145c13e9ced3d3e5d948a6213487d52444" -"checksum uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c1441164e5da61f00acd15f5a9e61939693c2c6e8b9fae36a220b82de7e212" -"checksum unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8abc4b7d8158bdfbbaaccc35331ed3c30c2673e99000d7ae665a2eb6576f4" -"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum vergen 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "93fb2d57fbc535fcd45548c99b141d2d960995daaf04b864c4d9fe1ea011c819" +"checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff1f0f87e467255240c1faf5cf13a04410723407840d7733e75967224e191a5" -"checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2" +"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" +"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" -"checksum wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a60b9508cff2b7c27ed41200dd668806280740fadc8c88440e9c88625e84f1a" -"checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" +"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" +"checksum websocket 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2c67346c042adbd4f5b2a49700e340befc5b772094fec8d36df6b825523d933" +"checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws 0.7.9 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" +"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.1.0 (git+https://github.com/paritytech/yamux)" = "" +"checksum yamux 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2269402a82beb59192319ad64a199850b6dcf3a14ef941206cdad3d7b9cfb598" diff --git a/Cargo.toml b/Cargo.toml index ffc5d408cdfe03664f6c2e049a2cb98cb39d7de3..286e93ecaed89f0a9eddb723e9f2f5b677dd3187 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,18 +4,19 @@ path = "node/src/main.rs" [package] name = "substrate" -version = "0.9.0" +version = "0.10.0" authors = ["Parity Technologies "] build = "build.rs" +edition = "2018" [dependencies] error-chain = "0.12" -node-cli = { path = "node/cli" } +cli = { package = "node-cli", path = "node/cli" } futures = "0.1" ctrlc = { version = "3.0", features = ["termination"] } [build-dependencies] -vergen = "2" +vergen = "3" [workspace] members = [ @@ -30,19 +31,33 @@ members = [ "core/finality-grandpa/primitives", "core/keyring", "core/network", + "core/panic-handler", "core/primitives", "core/rpc", "core/rpc-servers", + "core/serializer", + "core/service", + "core/service/test", + "core/sr-api-macros", "core/sr-io", + "core/sr-primitives", "core/sr-sandbox", "core/sr-std", "core/sr-version", + "core/state-machine", + "core/test-runtime", + "core/telemetry", + "core/trie", + "core/keystore", "core/transaction-pool", "core/transaction-pool/graph", + "core/inherents", + "core/util/fork-tree", "srml/support", "srml/support/procedural", "srml/support/procedural/tools", "srml/support/procedural/tools/derive", + "srml/support/test", "srml/assets", "srml/aura", "srml/balances", @@ -52,28 +67,23 @@ members = [ "srml/democracy", "srml/example", "srml/executive", + "srml/fees", + "srml/finality-tracker", "srml/grandpa", + "srml/indices", "srml/metadata", - "core/sr-primitives", "srml/session", "srml/staking", + "srml/sudo", "srml/system", "srml/timestamp", "srml/treasury", "srml/upgrade-key", - "core/serializer", - "core/service", - "core/service/test", - "core/sr-api-macros", - "core/state-machine", - "core/test-runtime", - "core/telemetry", - "core/trie", - "core/keystore", "node/cli", "node/executor", "node/primitives", "node/runtime", + "node-template", "subkey", ] exclude = [ diff --git a/Dockerfile b/Dockerfile index f7a36f2a5ba2845543d92a74698146bcdfaf5427..5c78740d5ea847f055021e3afbd332fda2647796 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ RUN apk add build-base \ cmake \ linux-headers \ openssl-dev \ + clang-dev \ cargo ARG PROFILE=release @@ -34,4 +35,4 @@ RUN rm -rf /usr/lib/python* && \ EXPOSE 30333 9933 9944 VOLUME ["/data"] -CMD ["/usr/local/bin/substrate"] +ENTRYPOINT ["/usr/local/bin/substrate"] diff --git a/README.adoc b/README.adoc index e35c6f2ab3ecefbc1edd9db49be4d4476786f076..492df92996a804ee189b09d261b133a22855de45 100644 --- a/README.adoc +++ b/README.adoc @@ -4,16 +4,18 @@ :toc: :sectnums: -== Intro +== Intro in one sentence -Next-generation framework for blockchain innovation. +Substrate is a next-generation framework for blockchain innovation. == Description -At its heart, Substrate is a combination of three technologies: WebAssembly, Libp2p and AfG Consensus. It is both a library for building new blockchains and a "skeleton key" of a blockchain client, able to synchronise to any Substrate-based chain. +At its heart, Substrate is a combination of three technologies: https://webassembly.org/[WebAssembly], https://libp2p.io/[Libp2p] and GRANDPA Consensus. About GRANDPA, see this https://hackmd.io/Jd0byWX0RiqFiXUVC78Bdw?view#GRANDPA[definition], https://medium.com/polkadot-network/grandpa-block-finality-in-polkadot-an-introduction-part-1-d08a24a021b5[introduction] and https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf[formal specification]. It is both a library for building new blockchains and a "skeleton key" of a blockchain client, able to synchronise to any Substrate-based chain. Substrate chains have three distinct features that make them "next-generation": a dynamic, self-defining state-transition function; light-client functionality from day one; and a progressive consensus algorithm with fast block production and adaptive, definite finality. The STF, encoded in WebAssembly, is known as the "runtime". This defines the `execute_block` function, and can specify everything from the staking algorithm, transaction semantics, logging mechanisms and procedures for replacing any aspect of itself or of the blockchain's state ("governance"). Because the runtime is entirely dynamic all of these can be switched out or upgraded at any time. A Substrate chain is very much a "living organism". +See also https://www.parity.io/what-is-substrate/. + == Usage Substrate is still an early stage project, and while it has already been used as the basis of major projects like Polkadot, using it is still a significant undertaking. In particular, you should have a good knowledge of blockchain concepts and basic cryptography. Terminology like header, block, client, hash, transaction and signature should be familiar. At present you will need a working knowledge of Rust to be able to do anything interesting (though eventually, we aim for this not to be the case). @@ -48,38 +50,35 @@ Other examples include the parachain-heads extrinsic in Polkadot and the "note-m === Runtime and API -Substrate chains all have a runtime. The runtime is a WebAssembly "blob" that includes a number of entry-points. Some entry-points are required as part of the underlying Substrate specification. Others are merely convention and required for the default implementation of the Substrate client to be able to author blocks. In short these two sets are: +Substrate chains all have a runtime. The runtime is a WebAssembly "blob" that includes a number of entry-points. Some entry-points are required as part of the underlying Substrate specification. Others are merely convention and required for the default implementation of the Substrate client to be able to author blocks. -The runtime is API entry points are expected to be in the runtime's `api` module. There is a specific ABI based upon the Substrate Simple Codec (`codec`), which is used to encode and decode the arguments for these functions and specify where and how they should be passed. A special macro is provided called `impl_stubs`, which prepares all functionality for marshalling arguments and basically just allows you to write the functions as you would normally (except for the fact that there must be example one argument - tuples are allowed to workaround). +If you want to develop a chain with Substrate, you will need to implement the `Core` trait. This `Core` trait generates an API with the minimum necessary functionality to interact with your runtime. A special macro is provided called `impl_runtime_apis!` that help you implement runtime API traits. All runtime API trait implementations need to be done in one call of the `impl_runtime_apis!` macro. All parameters and return values need to implement https://crates.io/crates/parity-codec[`parity-codec`] to be encodable and decodable. -Here's the Polkadot API implementation as of PoC-2: +Here's a snippet of the Polkadot API implementation as of PoC-3: ```rust -pub mod api { - impl_stubs!( - - // Standard: Required. - version => |()| super::Version::version(), - authorities => |()| super::Consensus::authorities(), - execute_block => |block| super::Executive::execute_block(block), - - // Conventional: Needed for Substrate client's reference block authoring logic to work. - initialise_block => |header| super::Executive::initialise_block(&header), - apply_extrinsic => |extrinsic| super::Executive::apply_extrinsic(extrinsic), - finalise_block => |()| super::Executive::finalise_block(), - inherent_extrinsics => |inherent| super::inherent_extrinsics(inherent), - - // Non-standard (Polkadot-specific). This just exposes some stuff that Polkadot client - // finds useful. - validator_count => |()| super::Session::validator_count(), - validators => |()| super::Session::validators() - ); +impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn authorities() -> Vec { + Consensus::authorities() + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialise_block(header: ::Header) { + Executive::initialise_block(&header) + } + } + // ---snip--- } ``` -As you can see, at the minimum there are only three API calls to implement. If you want to reuse as much of Substrate's reference block authoring client code, then you'll want to provide the next four entrypoints (though three of them you probably already implemented as part of `execute_block`). - -Of the first three, there is `execute_block`, which contains the actions to be taken to execute a block and pretty much defines the blockchain. Then there is `authorities` which tells the AfG consensus algorithm sitting in the Substrate client who the given authorities (known as "validators" in some contexts) are that can finalise the next block. Finally, there is `version`, which is a fairly sophisticated version identifier. This includes a key distinction between *specification version* and *authoring version*, with the former essentially versioning the logic of `execute_block` and the latter versioning only the logic of `inherent_extrinsics` and core aspects of extrinsic validity. === Inherent Extrinsics @@ -135,7 +134,7 @@ First let's get a template chainspec that you can edit. We'll use the "staging" [source, shell] ---- -substrate --chain=staging build-spec > ~/chainspec.json +substrate build-spec --chain=staging > ~/chainspec.json ---- Now, edit `~/chainspec.json` in your editor. There are a lot of individual fields for each module, and one very large one which contains the Webassembly code blob for this chain. The easiest field to edit is the block `period`. Change it to 10 (seconds): @@ -175,12 +174,15 @@ You can distribute `mychain.json` so that everyone can synchronise and (dependin === Hacking on Substrate -If you'd actually like hack on Substrate, you can just grab the source code and +If you'd actually like to hack on Substrate, you can just grab the source code and build it. Ensure you have Rust and the support software installed: [source, shell] ---- curl https://sh.rustup.rs -sSf | sh +# on Windows download and run rustup-init.exe +# from https://rustup.rs instead + rustup update nightly rustup target add wasm32-unknown-unknown --toolchain nightly rustup update stable @@ -197,6 +199,28 @@ sudo apt install cmake pkg-config libssl-dev git clang libclang-dev [source, shell] brew install cmake pkg-config openssl git llvm + - Windows (PowerShell): ++ +[source, shell] +---- +# Install LLVM +# Download and install the Pre Build Windows binaries +# of LLVM from http://releases.llvm.org/download.html + +# Install OpenSSL (through vcpkg) +mkdir \Tools +cd \Tools +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +.\bootstrap-vcpkg.bat +.\vcpkg.exe install openssl:x64-windows-static + +$env:OPENSSL_DIR = 'C:\Tools\vcpkg\installed\x64-windows-static' +$env:OPENSSL_STATIC = 'Yes' +[System.Environment]::SetEnvironmentVariable('OPENSSL_DIR', $env:OPENSSL_DIR, [System.EnvironmentVariableTarget]::User) +[System.Environment]::SetEnvironmentVariable('OPENSSL_STATIC', $env:OPENSSL_STATIC, [System.EnvironmentVariableTarget]::User) +---- + Then, grab the Substrate source code: [source, shell] @@ -213,28 +237,29 @@ Then build the code: cargo build # Builds all native code ---- -You can run the tests if you like: +You can run all the tests if you like: [source, shell] cargo test --all +Or just run the tests of a specific package (i.e. `cargo test -p srml-assets`) + You can start a development chain with: [source, shell] -cargo run -- --dev +cargo run \-- --dev +Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run \-- --dev`. -Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run -- --dev`. - -If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on [Telemetry](https://telemetry.polkadot.io/#/Local%20Testnet). You'll need two terminals windows open. +If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry] . You'll need two terminals windows open. We'll start Alice's substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The Bootnode ID of her node is `QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN`, which is generated from the `--node-key` value that we specify below: [source, shell] -cargo run -- \ +cargo run --release \-- \ --base-path /tmp/alice \ --chain=local \ - --key Alice \ + --key //Alice \ --name "ALICE" \ --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ --telemetry-url ws://telemetry.polkadot.io:1024 \ @@ -243,17 +268,50 @@ cargo run -- \ In the second terminal, we'll run the following to start Bob's substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's Bootnode ID on TCP port 30333: [source, shell] -cargo run -- \ +cargo run --release \-- \ --base-path /tmp/bob \ --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN \ --chain=local \ - --key Bob \ + --key //Bob \ --name "BOB" \ --port 30334 \ --telemetry-url ws://telemetry.polkadot.io:1024 \ --validator -Additional Substate CLI usage options are available and may be shown by running `cargo run -- --help`. +Additional Substate CLI usage options are available and may be shown by running `cargo run \-- --help`. + +=== Joining the Dried Danta Testnet + +Dried Danta is the new testnet for Substrate 1.0 gamma. Please note that 1.0 gamma is not compatible with the BBQ-Birch or Charred-Cherry testnets. Ensure you have the dependencies listed above before compiling. + +[source, shell] +---- +git clone https://github.com/paritytech/substrate.git +cd substrate +---- + +You can run the tests if you like: + +[source, shell] +cargo test --all + +Start your node: + +[source, shell] +cargo run --release \-- + +To see a list of command line options, enter: + +[source, shell] +cargo run --release \-- --help + +For example, you can choose a custom node name: + +[source, shell] +cargo run --release \-- --name my_custom_name + +If you are successful, you will see your node syncing at https://telemetry.polkadot.io/#/Dried%20Danta + == Documentation @@ -319,18 +377,18 @@ Example (generic): /// ```rust /// // insert example 1 code here /// ``` -/// +/// ``` * Important notes: ** Documentation comments must use annotations with a triple slash `///` -** Modules are documented using `//!` +** Modules are documented using `//!` ``` //! Summary (of module) //! //! Description (of module) ``` -* Special section header is indicated with a hash `#`. +* Special section header is indicated with a hash `#`. ** `Panics` section requires an explanation if the function triggers a panic ** `Errors` section is for describing conditions under which a function of method returns `Err(E)` if it returns a `Result` ** `Safety` section requires an explanation if the function is `unsafe` @@ -338,7 +396,7 @@ Example (generic): * Code block annotations for examples are included between triple graves, as shown above. Instead of including the programming language to use for syntax highlighting as the annotation after the triple graves, alternative annotations include the `ignore`, `text`, `should_panic`, or `no_run`. -* Summary sentence is a short high level sinngle sentence of its functionality +* Summary sentence is a short high level single sentence of its functionality * Description paragraph is for details additional to the summary sentence * Missing documentation annotations may be used to identify where to generate warnings with `#![warn(missing_docs)]` or errors `#![deny(missing_docs)]` @@ -350,7 +408,7 @@ The code block annotations in the `# Example` section may be used as https://doc * Important notes: ** Rustdoc will automatically add a `main()` wrapper around the code block to test it -** https://doc.rust-lang.org/1.9.0/book/documentation.html#documenting-macros[Documentating macros]. +** https://doc.rust-lang.org/1.9.0/book/documentation.html#documenting-macros[Documenting macros]. ** Documentation as tests examples are included when running `cargo test` == Contributing diff --git a/build.rs b/build.rs index ef920cc6d22f8a2cb673e979390c19a29f42d5bf..273700c525c883579880be28b231a5f14e43c6d7 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,18 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -extern crate vergen; +use vergen::{ConstantsFlags, generate_cargo_keys}; -use vergen::{ConstantsFlags, Vergen}; - -const ERROR_MSG: &'static str = "Failed to generate metadata files"; +const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { - let vergen = Vergen::new(ConstantsFlags::all()).expect(ERROR_MSG); - - for (k, v) in vergen.build_info() { - println!("cargo:rustc-env={}={}", k.name(), v); - } - + generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); println!("cargo:rerun-if-changed=.git/HEAD"); } diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..d173ac66ee2439da99f2257663c030bbe58c13e3 --- /dev/null +++ b/core/basic-authorship/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "substrate-basic-authorship" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4" +codec = { package = "parity-codec", version = "3.2" } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +client = { package = "substrate-client", path = "../../core/client" } +aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives" } +consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +inherents = { package = "substrate-inherents", path = "../inherents" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +substrate-telemetry = { path = "../telemetry" } + +[dev-dependencies] +test-client = { package = "substrate-test-client", path = "../../core/test-client" } diff --git a/core/service/src/consensus.rs b/core/basic-authorship/src/basic_authorship.rs similarity index 50% rename from core/service/src/consensus.rs rename to core/basic-authorship/src/basic_authorship.rs index 5f8d1898785bb8f46f7371fd36282a3154705067..579ac17fb1b78821829b617d4a6dd70fe1e89660 100644 --- a/core/service/src/consensus.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,27 +16,28 @@ //! A consensus proposer for "basic" chains which use the primitive inherent-data. -// FIXME: move this into substrate-consensus-common - https://github.com/paritytech/substrate/issues/1021 +// FIXME #1021 move this into substrate-consensus-common +// +use std::{self, time, sync::Arc}; -use std::sync::Arc; -use std::time; -use std; +use log::{info, debug}; -use client::{self, error, Client as SubstrateClient, CallExecutor}; -use client::{block_builder::api::BlockBuilder as BlockBuilderApi, runtime_api::Core}; -use codec::{Decode, Encode}; +use client::{ + self, error, Client as SubstrateClient, CallExecutor, + block_builder::api::BlockBuilder as BlockBuilderApi, runtime_api::Core, +}; +use codec::Decode; use consensus_common::{self, evaluation}; -use primitives::{H256, AuthorityId, ed25519, Blake2Hasher}; -use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi}; +use primitives::{H256, Blake2Hasher}; +use runtime_primitives::traits::{ + Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, AuthorityIdFor +}; +use runtime_primitives::ExecutionContext; use runtime_primitives::generic::BlockId; -use runtime_primitives::BasicInherentData; +use runtime_primitives::ApplyError; use transaction_pool::txpool::{self, Pool as TransactionPool}; -use aura_primitives::AuraConsensusData; - -type Timestamp = u64; - -// block size limit. -const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024; +use inherents::InherentData; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; /// Build new blocks. pub trait BlockBuilder { @@ -57,18 +58,20 @@ pub trait AuthoringApi: Send + Sync + ProvideRuntimeApi where fn build_block) -> ()>( &self, at: &BlockId, - inherent_data: BasicInherentData, + inherent_data: InherentData, build_ctx: F, ) -> Result; } impl<'a, B, E, Block, RA> BlockBuilder - for client::block_builder::BlockBuilder<'a, Block, BasicInherentData, SubstrateClient> + for client::block_builder::BlockBuilder<'a, Block, SubstrateClient> where B: client::backend::Backend + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, - RA: BlockBuilderApi, + RA: Send + Sync + 'static, + SubstrateClient : ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: BlockBuilderApi, { fn push_extrinsic(&mut self, extrinsic: ::Extrinsic) -> Result<(), error::Error> { client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into) @@ -79,7 +82,9 @@ impl AuthoringApi for SubstrateClient where B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + Clone + 'static, Block: BlockT, - RA: BlockBuilderApi, + RA: Send + Sync + 'static, + SubstrateClient : ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: BlockBuilderApi, { type Block = Block; type Error = client::error::Error; @@ -87,16 +92,16 @@ impl AuthoringApi for SubstrateClient where fn build_block) -> ()>( &self, at: &BlockId, - inherent_data: BasicInherentData, + inherent_data: InherentData, mut build_ctx: F, ) -> Result { let mut block_builder = self.new_block_at(at)?; let runtime_api = self.runtime_api(); - if runtime_api.has_api::>(at)? { - runtime_api.inherent_extrinsics(at, &inherent_data)? - .into_iter().try_for_each(|i| block_builder.push(i))?; - } + // We don't check the API versions any further here since the dispatch compatibility + // check should be enough. + runtime_api.inherent_extrinsics_with_context(at, ExecutionContext::BlockConstruction, inherent_data)? + .into_iter().try_for_each(|i| block_builder.push(i))?; build_ctx(&mut block_builder); @@ -112,12 +117,12 @@ pub struct ProposerFactory where A: txpool::ChainApi { pub transaction_pool: Arc>, } -impl consensus_common::Environment<::Block, ConsensusData> for ProposerFactory where +impl consensus_common::Environment<::Block> for ProposerFactory where C: AuthoringApi, - ::Api: BlockBuilderApi<::Block, BasicInherentData>, + ::Api: BlockBuilderApi<::Block>, A: txpool::ChainApi::Block>, client::error::Error: From<::Error>, - Proposer<::Block, C, A>: consensus_common::Proposer<::Block, ConsensusData>, + Proposer<::Block, C, A>: consensus_common::Proposer<::Block>, { type Proposer = Proposer<::Block, C, A>; type Error = error::Error; @@ -125,8 +130,7 @@ impl consensus_common::Environment<::Blo fn init( &self, parent_header: &<::Block as BlockT>::Header, - _: &[AuthorityId], - _: Arc, + _: &[AuthorityIdFor<::Block>], ) -> Result { let parent_hash = parent_header.hash(); @@ -140,16 +144,13 @@ impl consensus_common::Environment<::Blo parent_id: id, parent_number: *parent_header.number(), transaction_pool: self.transaction_pool.clone(), + now: Box::new(time::Instant::now), }; Ok(proposer) } } -struct ConsensusData { - timestamp: Option, -} - /// The proposer logic. pub struct Proposer { client: Arc, @@ -157,91 +158,105 @@ pub struct Proposer { parent_id: BlockId, parent_number: <::Header as HeaderT>::Number, transaction_pool: Arc>, + now: Box time::Instant>, } -impl consensus_common::Proposer<::Block, AuraConsensusData> for Proposer where +impl consensus_common::Proposer<::Block> for Proposer where Block: BlockT, C: AuthoringApi, - ::Api: BlockBuilderApi, + ::Api: BlockBuilderApi, A: txpool::ChainApi, client::error::Error: From<::Error> { type Create = Result<::Block, error::Error>; type Error = error::Error; - fn propose(&self, consensus_data: AuraConsensusData) + fn propose(&self, inherent_data: InherentData, max_duration: time::Duration) -> Result<::Block, error::Error> { - self.propose_with(ConsensusData { timestamp: Some(consensus_data.timestamp) }) - } -} - -impl consensus_common::Proposer<::Block, ()> for Proposer where - Block: BlockT, - C: AuthoringApi, - ::Api: BlockBuilderApi, - A: txpool::ChainApi, - client::error::Error: From<::Error> -{ - type Create = Result<::Block, error::Error>; - type Error = error::Error; - - fn propose(&self, _consensus_data: ()) -> Result<::Block, error::Error> { - self.propose_with(ConsensusData { timestamp: None }) + // leave some time for evaluation and block finalisation (33%) + let deadline = (self.now)() + max_duration - max_duration / 3; + self.propose_with(inherent_data, deadline) } } impl Proposer where Block: BlockT, C: AuthoringApi, - ::Api: BlockBuilderApi, + ::Api: BlockBuilderApi, A: txpool::ChainApi, client::error::Error: From<::Error>, { - fn propose_with(&self, consensus_data: ConsensusData) + fn propose_with(&self, inherent_data: InherentData, deadline: time::Instant) -> Result<::Block, error::Error> { use runtime_primitives::traits::BlakeTwo256; - let timestamp = consensus_data.timestamp.unwrap_or_else(current_timestamp); - let inherent_data = BasicInherentData::new(timestamp, 0); + /// If the block is full we will attempt to push at most + /// this number of transactions before quitting for real. + /// It allows us to increase block utilisation. + const MAX_SKIPPED_TRANSACTIONS: usize = 8; let block = self.client.build_block( &self.parent_id, inherent_data, |block_builder| { + let mut is_first = true; + let mut skipped = 0; let mut unqueue_invalid = Vec::new(); - let mut pending_size = 0; let pending_iterator = self.transaction_pool.ready(); for pending in pending_iterator { - // TODO [ToDr] Probably get rid of it, and validate in runtime. - let encoded_size = pending.data.encode().len(); - if pending_size + encoded_size >= MAX_TRANSACTIONS_SIZE { break } + if (self.now)() > deadline { + debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing."); + break; + } match block_builder.push_extrinsic(pending.data.clone()) { Ok(()) => { - pending_size += encoded_size; + debug!("[{:?}] Pushed to the block.", pending.hash); + } + Err(error::Error(error::ErrorKind::ApplyExtrinsicFailed(ApplyError::FullBlock), _)) => { + if is_first { + debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); + unqueue_invalid.push(pending.hash.clone()); + } else if skipped < MAX_SKIPPED_TRANSACTIONS { + skipped += 1; + debug!( + "Block seems full, but will try {} more transactions before quitting.", + MAX_SKIPPED_TRANSACTIONS - skipped + ); + } else { + debug!("Block is full, proceed with proposing."); + break; + } } Err(e) => { - trace!(target: "transaction-pool", "Invalid transaction: {}", e); + debug!("[{:?}] Invalid transaction: {}", pending.hash, e); unqueue_invalid.push(pending.hash.clone()); } } + + is_first = false; } self.transaction_pool.remove_invalid(&unqueue_invalid); })?; - info!("Proposing block [number: {}; hash: {}; parent_hash: {}; extrinsics: [{}]]", - block.header().number(), - <::Block as BlockT>::Hash::from(block.header().hash()), - block.header().parent_hash(), - block.extrinsics().iter() - .map(|xt| format!("{}", BlakeTwo256::hash_of(xt))) - .collect::>() - .join(", ") - ); + info!("Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics: [{}]]", + block.header().number(), + <::Block as BlockT>::Hash::from(block.header().hash()), + block.header().parent_hash(), + block.extrinsics() + .iter() + .map(|xt| format!("{}", BlakeTwo256::hash_of(xt))) + .collect::>() + .join(", ") + ); + telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing"; + "number" => ?block.header().number(), + "hash" => ?<::Block as BlockT>::Hash::from(block.header().hash()), + ); let substrate_block = Decode::decode(&mut block.encode().as_slice()) .expect("blocks are defined to serialize to substrate blocks correctly; qed"); @@ -256,8 +271,58 @@ impl Proposer where } } -fn current_timestamp() -> Timestamp { - time::SystemTime::now().duration_since(time::UNIX_EPOCH) - .expect("now always later than unix epoch; qed") - .as_secs() +#[cfg(test)] +mod tests { + use super::*; + + use codec::Encode; + use std::cell::RefCell; + use consensus_common::{Environment, Proposer}; + use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; + + fn extrinsic(nonce: u64) -> Extrinsic { + let tx = Transfer { + amount: Default::default(), + nonce, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }; + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); + Extrinsic::Transfer(tx, signature) + } + + #[test] + fn should_cease_building_block_when_deadline_is_reached() { + // given + let client = Arc::new(test_client::new()); + let chain_api = transaction_pool::ChainApi::new(client.clone()); + let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); + + txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]).unwrap(); + + let proposer_factory = ProposerFactory { + client: client.clone(), + transaction_pool: txpool.clone(), + }; + + let mut proposer = proposer_factory.init( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + &[] + ).unwrap(); + + // when + let cell = RefCell::new(time::Instant::now()); + proposer.now = Box::new(move || { + let new = *cell.borrow() + time::Duration::from_secs(2); + cell.replace(new) + }); + let deadline = time::Duration::from_secs(3); + let block = proposer.propose(Default::default(), deadline).unwrap(); + + // then + // block should have some extrinsics although we have some more in the pool. + assert_eq!(block.extrinsics().len(), 1); + assert_eq!(txpool.ready().count(), 2); + } + } diff --git a/node/cli/src/params.rs b/core/basic-authorship/src/lib.rs similarity index 52% rename from node/cli/src/params.rs rename to core/basic-authorship/src/lib.rs index f0928875874720a096d17ac4dbef0ac7e7861991..88a55c3bac4fa22bb21e42e9c66398a6e286b575 100644 --- a/node/cli/src/params.rs +++ b/core/basic-authorship/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,20 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use structopt::StructOpt; -use cli::CoreParams; +//! Basic implementation of block-authoring logic. -/// Extend params for Node -#[derive(Debug, StructOpt)] -pub struct Params { - /// Should run as a GRANDPA authority node - #[structopt(long = "grandpa-authority", help = "Run Node as a GRANDPA authority, implies --validator")] - grandpa_authority: bool, +#![warn(unused_extern_crates)] - /// Should run as a GRANDPA authority node only - #[structopt(long = "grandpa-authority-only", help = "Run Node as a GRANDPA authority only, don't as a usual validator, implies --grandpa-authority")] - grandpa_authority_only: bool, +mod basic_authorship; - #[structopt(flatten)] - core: CoreParams -} +pub use crate::basic_authorship::{ProposerFactory, BlockBuilder, AuthoringApi, Proposer}; diff --git a/core/cli/Cargo.toml b/core/cli/Cargo.toml index 88db4d87c0c5c967eb4c39a0045201a6e49e7be6..9ed26692c7b198d0bec7601119607dc1dbb8427c 100644 --- a/core/cli/Cargo.toml +++ b/core/cli/Cargo.toml @@ -3,17 +3,16 @@ name = "substrate-cli" version = "0.3.0" authors = ["Parity Technologies "] description = "Substrate CLI interface." +edition = "2018" [dependencies] clap = "~2.32" -backtrace = "0.3" -env_logger = "0.5" +env_logger = "0.6" error-chain = "0.12" log = "0.4" atty = "0.2" regex = "1" time = "0.1" -slog = "^2" ansi_term = "0.11" lazy_static = "1.0" app_dirs = "1.2" @@ -21,12 +20,15 @@ tokio = "0.1.7" futures = "0.1.17" fdlimit = "0.1" exit-future = "0.1" -sysinfo = "0.7" -substrate-client = { path = "../../core/client" } -substrate-network = { path = "../../core/network" } -sr-primitives = { path = "../../core/sr-primitives" } -substrate-primitives = { path = "../../core/primitives" } -substrate-service = { path = "../../core/service" } +serde_json = "1.0" +sysinfo = "0.8.0" +panic-handler = { package = "substrate-panic-handler", path = "../../core/panic-handler" } +client = { package = "substrate-client", path = "../../core/client" } +network = { package = "substrate-network", path = "../../core/network" } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +service = { package = "substrate-service", path = "../../core/service" } +state-machine = { package = "substrate-state-machine", path = "../../core/state-machine" } substrate-telemetry = { path = "../../core/telemetry" } names = "0.11.0" -structopt = "0.2.13" +structopt = "0.2" diff --git a/core/cli/src/error.rs b/core/cli/src/error.rs index f30481c84819e1b6a4e2ad2ee5868d576949f04b..e368cc6d9670a59adaf2975de4f69421948fbb14 100644 --- a/core/cli/src/error.rs +++ b/core/cli/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,13 @@ //! Initialization errors. +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/substrate/issues/1547 +#![allow(deprecated)] + use client; +use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind}; error_chain! { foreign_links { diff --git a/core/cli/src/informant.rs b/core/cli/src/informant.rs index 5912da81262cf9749bf4ef35752d431925cca405..260615b2c1cb626429c14e95cc51baceda08d4b1 100644 --- a/core/cli/src/informant.rs +++ b/core/cli/src/informant.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,40 +17,41 @@ //! Console informant. Prints sync progress and block events. Runs on the calling thread. use ansi_term::Colour; -use std::time::{Duration, Instant}; +use std::fmt; +use std::time; use futures::{Future, Stream}; use service::{Service, Components}; use tokio::runtime::TaskExecutor; -use tokio::timer::Interval; use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; use network::{SyncState, SyncProvider}; -use client::BlockchainEvents; -use runtime_primitives::traits::{Header, As}; +use client::{backend::Backend, BlockchainEvents}; +use substrate_telemetry::{telemetry, SUBSTRATE_INFO}; +use log::{info, warn}; -const TIMER_INTERVAL_MS: u64 = 5000; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{Header, As}; /// Spawn informant on the event loop pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExecutor) where C: Components, { - let interval = Interval::new(Instant::now(), Duration::from_millis(TIMER_INTERVAL_MS)); - let network = service.network(); let client = service.client(); let txpool = service.transaction_pool(); let mut last_number = None; + let mut last_update = time::Instant::now(); let mut sys = System::new(); let self_pid = get_current_pid(); - let display_notifications = interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { - let sync_status = network.status(); + let display_notifications = network.status().for_each(move |sync_status| { - if let Ok(best_block) = client.best_block_header() { - let hash = best_block.hash(); + if let Ok(info) = client.info() { + let best_number: u64 = info.chain.best_number.as_(); + let best_hash = info.chain.best_hash; let num_peers = sync_status.num_peers; - let best_number: u64 = best_block.number().as_(); - let speed = move || speed(best_number, last_number); + let speed = move || speed(best_number, last_number, last_update); + last_update = time::Instant::now(); let (status, target) = match (sync_status.sync.state, sync_status.sync.best_seen_block) { (SyncState::Idle, _) => ("Idle".into(), "".into()), (SyncState::Downloading, None) => (format!("Syncing{}", speed()), "".into()), @@ -58,14 +59,21 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe }; last_number = Some(best_number); let txpool_status = txpool.status(); + let finalized_number: u64 = info.chain.finalized_number.as_(); + let bandwidth_download = network.average_download_per_sec(); + let bandwidth_upload = network.average_upload_per_sec(); info!( target: "substrate", - "{}{} ({} peers), best: #{} ({})", + "{}{} ({} peers), best: #{} ({}), finalized #{} ({}), ⬇ {} ⬆ {}", Colour::White.bold().paint(&status), target, Colour::White.bold().paint(format!("{}", sync_status.num_peers)), Colour::White.paint(format!("{}", best_number)), - hash + best_hash, + Colour::White.paint(format!("{}", finalized_number)), + info.chain.finalized_hash, + TransferRateFormat(bandwidth_download), + TransferRateFormat(bandwidth_upload), ); // get cpu usage and memory usage of this process @@ -74,15 +82,23 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe (proc.cpu_usage(), proc.memory()) } else { (0.0, 0) }; + let network_state = serde_json::to_string(&network.network_state()).unwrap_or_default(); + telemetry!( + SUBSTRATE_INFO; "system.interval"; + "network_state" => network_state, "status" => format!("{}{}", status, target), "peers" => num_peers, "height" => best_number, - "best" => ?hash, + "best" => ?best_hash, "txcount" => txpool_status.ready, "cpu" => cpu_usage, - "memory" => memory + "memory" => memory, + "finalized_height" => finalized_number, + "finalized_hash" => ?info.chain.finalized_hash, + "bandwidth_download" => bandwidth_download, + "bandwidth_upload" => bandwidth_upload, ); } else { warn!("Error getting best block information"); @@ -92,7 +108,36 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe }); let client = service.client(); - let display_block_import = client.import_notification_stream().for_each(|n| { + let mut last = match client.info() { + Ok(info) => Some((info.chain.best_number, info.chain.best_hash)), + Err(e) => { warn!("Error getting best block information: {:?}", e); None } + }; + + let display_block_import = client.import_notification_stream().for_each(move |n| { + // detect and log reorganizations. + if let Some((ref last_num, ref last_hash)) = last { + if n.header.parent_hash() != last_hash { + let tree_route = ::client::blockchain::tree_route( + client.backend().blockchain(), + BlockId::Hash(last_hash.clone()), + BlockId::Hash(n.hash), + ); + + match tree_route { + Ok(ref t) if !t.retracted().is_empty() => info!( + "Reorg from #{},{} to #{},{}, common ancestor #{},{}", + last_num, last_hash, + n.header.number(), n.hash, + t.common_block().number, t.common_block().hash, + ), + Ok(_) => {}, + Err(e) => warn!("Error computing tree route: {}", e), + } + } + } + + last = Some((n.header.number().clone(), n.hash.clone())); + info!(target: "substrate", "Imported #{} ({})", n.header.number(), n.hash); Ok(()) }); @@ -100,7 +145,7 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe let txpool = service.transaction_pool(); let display_txpool_import = txpool.import_notification_stream().for_each(move |_| { let status = txpool.status(); - telemetry!("txpool.import"; "ready" => status.ready, "future" => status.future); + telemetry!(SUBSTRATE_INFO; "txpool.import"; "ready" => status.ready, "future" => status.future); Ok(()) }); @@ -108,9 +153,11 @@ pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExe handle.spawn(exit.until(informant_work).map(|_| ())); } -fn speed(best_number: u64, last_number: Option) -> String { +fn speed(best_number: u64, last_number: Option, last_update: time::Instant) -> String { + let since_last_millis = last_update.elapsed().as_secs() * 1000; + let since_last_subsec_millis = last_update.elapsed().subsec_millis() as u64; let speed = match last_number { - Some(num) => (best_number.saturating_sub(num) * 10_000 / TIMER_INTERVAL_MS) as f64, + Some(num) => (best_number.saturating_sub(num) * 10_000 / (since_last_millis + since_last_subsec_millis)) as f64, None => 0.0 }; @@ -120,3 +167,27 @@ fn speed(best_number: u64, last_number: Option) -> String { format!(" {:4.1} bps", speed / 10.0) } } + +/// Contains a number of bytes per second. Implements `fmt::Display` and shows this number of bytes +/// per second in a nice way. +struct TransferRateFormat(u64); +impl fmt::Display for TransferRateFormat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Special case 0. + if self.0 == 0 { + return write!(f, "0") + } + + // Under 0.1 kiB, display plain bytes. + if self.0 < 100 { + return write!(f, "{} B/s", self.0) + } + + // Under 1.0 MiB/sec, display the value in kiB/sec. + if self.0 < 1024 * 1024 { + return write!(f, "{:.1}kiB/s", self.0 as f64 / 1024.0) + } + + write!(f, "{:.1}MiB/s", self.0 as f64 / (1024.0 * 1024.0)) + } +} diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index dc3c96f9cd52dff8138aee4e96931b6f77a00685..189681338c35f2695ae41e543bcd1e8d3f83d9e7 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,71 +19,54 @@ #![warn(missing_docs)] #![warn(unused_extern_crates)] -extern crate app_dirs; -extern crate env_logger; -extern crate atty; -extern crate ansi_term; -extern crate regex; -extern crate time; -extern crate fdlimit; -extern crate futures; -extern crate tokio; -extern crate names; -extern crate backtrace; -extern crate sysinfo; - -extern crate substrate_client as client; -extern crate substrate_network as network; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_service as service; -extern crate substrate_primitives as primitives; #[macro_use] -extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` -#[macro_use] -extern crate substrate_telemetry; -extern crate exit_future; - -#[macro_use] -extern crate lazy_static; -extern crate clap; -#[macro_use] -extern crate error_chain; -#[macro_use] -extern crate log; -extern crate structopt; - +mod traits; mod params; pub mod error; pub mod informant; -mod panic_hook; +use client::ExecutionStrategies; use runtime_primitives::traits::As; use service::{ ServiceFactory, FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis, PruningMode, ChainSpec, }; use network::{ - Protocol, config::{NetworkConfiguration, NonReservedPeerMode}, - multiaddr, + Protocol, config::{NetworkConfiguration, NonReservedPeerMode, Secret}, + build_multiaddr, }; use primitives::H256; -use std::io::{Write, Read, stdin, stdout}; -use std::iter; -use std::fs; -use std::fs::File; -use std::net::{Ipv4Addr, SocketAddr}; -use std::path::{Path, PathBuf}; -use std::str::FromStr; +use std::{ + io::{Write, Read, stdin, stdout}, iter, fs::{self, File}, net::{Ipv4Addr, SocketAddr}, + path::{Path, PathBuf}, str::FromStr, +}; + use names::{Generator, Name}; use regex::Regex; -use structopt::StructOpt; -pub use params::{CoreParams, CoreCommands, ExecutionStrategy}; +use structopt::{StructOpt, clap::AppSettings}; +#[doc(hidden)] +pub use structopt::clap::App; +use params::{ + RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, + NetworkConfigurationParams, SharedParams, MergeParameters, TransactionPoolParams, +}; +pub use params::{NoCustom, CoreParams}; +pub use traits::{GetLogFilter, AugmentClap}; +use app_dirs::{AppInfo, AppDataType}; +use error_chain::bail; +use log::info; +use lazy_static::lazy_static; use futures::Future; +use substrate_telemetry::TelemetryEndpoints; + +const MAX_NODE_NAME_LENGTH: usize = 32; /// Executable version. Used to pass version information from the root crate. pub struct VersionInfo { + /// Implemtation name. + pub name: &'static str, /// Implementation version. pub version: &'static str, /// SCM Commit hash. @@ -94,14 +77,8 @@ pub struct VersionInfo { pub description: &'static str, /// Executable file author. pub author: &'static str, -} - -/// CLI Action -pub enum Action { - /// Substrate handled the command. No need to do anything. - ExecutedInternally, - /// Service mode requested. Caller should start the service. - RunService(E), + /// Support URL. + pub support_url: &'static str, } /// Something that can be converted into an exit signal. @@ -112,16 +89,30 @@ pub trait IntoExit { fn into_exit(self) -> Self::Exit; } -fn get_chain_key(matches: &clap::ArgMatches) -> String { - matches.value_of("chain").unwrap_or_else( - || if matches.is_present("dev") { "dev" } else { "" } - ).into() +fn get_chain_key(cli: &SharedParams) -> String { + match cli.chain { + Some(ref chain) => chain.clone(), + None => if cli.dev { "dev".into() } else { "".into() } + } +} + +fn generate_node_name() -> String { + let result = loop { + let node_name = Generator::with_naming(Name::Numbered).next().unwrap(); + let count = node_name.chars().count(); + + if count < MAX_NODE_NAME_LENGTH { + break node_name + } + }; + + result } -fn load_spec(matches: &clap::ArgMatches, factory: F) -> Result, String> +fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where G: RuntimeGenesis, F: FnOnce(&str) -> Result>, String>, { - let chain_key = get_chain_key(matches); + let chain_key = get_chain_key(cli); let spec = match factory(&chain_key)? { Some(spec) => spec, None => ChainSpec::from_json_file(PathBuf::from(chain_key))? @@ -129,10 +120,17 @@ fn load_spec(matches: &clap::ArgMatches, factory: F) -> Result PathBuf { - matches.value_of("base_path") - .map(|x| Path::new(x).to_owned()) - .unwrap_or_else(default_base_path) +fn base_path(cli: &SharedParams, version: &VersionInfo) -> PathBuf { + cli.base_path.clone() + .unwrap_or_else(|| + app_dirs::get_app_root( + AppDataType::UserData, + &AppInfo { + name: version.executable_name, + author: version.author + } + ).expect("app directories exist on all supported platforms; qed") + ) } fn create_input_err>(msg: T) -> error::Error { @@ -141,7 +139,6 @@ fn create_input_err>(msg: T) -> error::Error { /// Check whether a node name is considered as valid fn is_node_name_valid(_name: &str) -> Result<(), &str> { - const MAX_NODE_NAME_LENGTH: usize = 32; let name = _name.to_string(); if name.chars().count() >= MAX_NODE_NAME_LENGTH { return Err("Node name too long"); @@ -162,50 +159,167 @@ fn is_node_name_valid(_name: &str) -> Result<(), &str> { Ok(()) } -/// Parse command line arguments -pub fn parse_args_default<'a, I, T>(args: I, version: VersionInfo) -> clap::ArgMatches<'a> +/// Parse command line interface arguments and executes the desired command. +/// +/// # Return value +/// +/// A result that indicates if any error occurred. +/// If no error occurred and a custom subcommand was found, the subcommand is returned. +/// The user needs to handle this subcommand on its own. +/// +/// # Remarks +/// +/// `CC` is a custom subcommand. This needs to be an `enum`! If no custom subcommand is required, +/// `NoCustom` can be used as type here. +/// `RP` is are custom parameters for the run command. This needs to be a `struct`! The custom +/// parameters are visible to the user as if they were normal run command parameters. If no custom +/// parameters are required, `NoCustom` can be used as type here. +pub fn parse_and_execute<'a, F, CC, RP, S, RS, E, I, T>( + spec_factory: S, + version: &VersionInfo, + impl_name: &'static str, + args: I, + exit: E, + run_service: RS, +) -> error::Result> where + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, + CC: StructOpt + Clone + GetLogFilter, + RP: StructOpt + Clone + AugmentClap, + E: IntoExit, + RS: FnOnce(E, RP, FactoryFullConfiguration) -> Result<(), String>, I: IntoIterator, T: Into + Clone, { + panic_handler::set(version.support_url); + let full_version = service::config::full_version_from_strs( version.version, version.commit ); - match CoreParams::clap() + let matches = CoreParams::::clap() .name(version.executable_name) .author(version.author) .about(version.description) .version(&(full_version + "\n")[..]) - .get_matches_from_safe(args) { - Ok(m) => m, - Err(e) => e.exit(), + .setting(AppSettings::GlobalVersion) + .setting(AppSettings::ArgsNegateSubcommands) + .setting(AppSettings::SubcommandsNegateReqs) + .get_matches_from(args); + let cli_args = CoreParams::::from_clap(&matches); + + init_logger(cli_args.get_log_filter().as_ref().map(|v| v.as_ref()).unwrap_or("")); + fdlimit::raise_fd_limit(); + + match cli_args { + params::CoreParams::Run(params) => run_node::( + params, spec_factory, exit, run_service, impl_name, version, + ).map(|_| None), + params::CoreParams::BuildSpec(params) => + build_spec::(params, spec_factory, version).map(|_| None), + params::CoreParams::ExportBlocks(params) => + export_blocks::(params, spec_factory, exit, version).map(|_| None), + params::CoreParams::ImportBlocks(params) => + import_blocks::(params, spec_factory, exit, version).map(|_| None), + params::CoreParams::PurgeChain(params) => + purge_chain::(params, spec_factory, version).map(|_| None), + params::CoreParams::Revert(params) => + revert_chain::(params, spec_factory, version).map(|_| None), + params::CoreParams::Custom(params) => Ok(Some(params)), } } -/// Parse clap::Matches into config and chain specification -pub fn parse_matches<'a, F, S>( - spec_factory: S, - version: VersionInfo, - impl_name: &'static str, - matches: &clap::ArgMatches<'a> -) -> error::Result<(ChainSpec<::Genesis>, FactoryFullConfiguration)> +fn parse_node_key(key: Option) -> error::Result> { + match key.map(|k| H256::from_str(&k)) { + Some(Ok(secret)) => Ok(Some(secret.into())), + Some(Err(err)) => Err(create_input_err(format!("Error parsing node key: {}", err))), + None => Ok(None), + } +} + +/// Fill the given `PoolConfiguration` by looking at the cli parameters. +fn fill_transaction_pool_configuration( + options: &mut FactoryFullConfiguration, + params: TransactionPoolParams, +) -> error::Result<()> { + // ready queue + options.transaction_pool.ready.count = params.pool_limit; + options.transaction_pool.ready.total_bytes = params.pool_kbytes * 1024; + + // future queue + let factor = 10; + options.transaction_pool.future.count = params.pool_limit / factor; + options.transaction_pool.future.total_bytes = params.pool_kbytes * 1024 / factor; + + Ok(()) +} + +/// Fill the given `NetworkConfiguration` by looking at the cli parameters. +fn fill_network_configuration( + cli: NetworkConfigurationParams, + base_path: &Path, + chain_spec_id: &str, + config: &mut NetworkConfiguration, + client_id: String, +) -> error::Result<()> { + config.boot_nodes.extend(cli.bootnodes.into_iter()); + config.config_path = Some( + network_path(&base_path, chain_spec_id).to_string_lossy().into() + ); + config.net_config_path = config.config_path.clone(); + config.reserved_nodes.extend(cli.reserved_nodes.into_iter()); + if !config.reserved_nodes.is_empty() { + config.non_reserved_mode = NonReservedPeerMode::Deny; + } + + for addr in cli.listen_addr.iter() { + let addr = addr.parse().map_err(|_| "Invalid listen multiaddress")?; + config.listen_addresses.push(addr); + } + + if config.listen_addresses.is_empty() { + let port = match cli.port { + Some(port) => port, + None => 30333, + }; + + config.listen_addresses = vec![ + iter::once(Protocol::Ip4(Ipv4Addr::new(0, 0, 0, 0))) + .chain(iter::once(Protocol::Tcp(port))) + .collect() + ]; + } + + config.public_addresses = Vec::new(); + + config.client_version = client_id; + config.use_secret = parse_node_key(cli.node_key)?; + + config.in_peers = cli.in_peers; + config.out_peers = cli.out_peers; + + Ok(()) +} + +fn create_run_node_config( + cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo +) -> error::Result> where F: ServiceFactory, S: FnOnce(&str) -> Result>>, String>, - { - let spec = load_spec(&matches, spec_factory)?; + let spec = load_spec(&cli.shared_params, spec_factory)?; let mut config = service::Configuration::default_with_spec(spec.clone()); config.impl_name = impl_name; config.impl_commit = version.commit; config.impl_version = version.version; - config.name = match matches.value_of("name") { - None => Generator::with_naming(Name::Numbered).next().unwrap(), - Some(name) => name.into(), + config.name = match cli.name { + None => generate_node_name(), + Some(name) => name, }; match is_node_name_valid(&config.name) { Ok(_) => (), @@ -219,160 +333,101 @@ where ) } - let base_path = base_path(&matches); + let base_path = base_path(&cli.shared_params, version); - config.keystore_path = matches.value_of("keystore") - .map(|x| Path::new(x).to_owned()) + config.keystore_path = cli.keystore_path .unwrap_or_else(|| keystore_path(&base_path, config.chain_spec.id())) .to_string_lossy() .into(); - config.database_path = db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); - config.database_cache_size = match matches.value_of("database_cache_size") { - Some(s) => Some(s.parse().map_err(|_| "Invalid Database Cache size specified")?), - _=> None - }; - config.pruning = match matches.value_of("pruning") { - Some("archive") => PruningMode::ArchiveAll, + config.database_path = + db_path(&base_path, config.chain_spec.id()).to_string_lossy().into(); + config.database_cache_size = cli.database_cache_size; + config.pruning = match cli.pruning { + Some(ref s) if s == "archive" => PruningMode::ArchiveAll, None => PruningMode::default(), - Some(s) => PruningMode::keep_blocks(s.parse() - .map_err(|_| create_input_err("Invalid pruning mode specified"))?), + Some(s) => PruningMode::keep_blocks( + s.parse().map_err(|_| create_input_err("Invalid pruning mode specified"))? + ), }; let role = - if matches.is_present("light") { - config.block_execution_strategy = service::ExecutionStrategy::NativeWhenPossible; + if cli.light { service::Roles::LIGHT - } else if matches.is_present("validator") || matches.is_present("dev") { - config.block_execution_strategy = service::ExecutionStrategy::Both; + } else if cli.validator || cli.shared_params.dev { service::Roles::AUTHORITY } else { - config.block_execution_strategy = service::ExecutionStrategy::NativeWhenPossible; service::Roles::FULL }; - if let Some(s) = matches.value_of("execution") { - config.block_execution_strategy = match s { - "both" => service::ExecutionStrategy::Both, - "native" => service::ExecutionStrategy::NativeWhenPossible, - "wasm" => service::ExecutionStrategy::AlwaysWasm, - _ => bail!(create_input_err("Invalid execution mode specified")), - }; - } + config.execution_strategies = ExecutionStrategies { + syncing: cli.syncing_execution.into(), + importing: cli.importing_execution.into(), + block_construction: cli.block_construction_execution.into(), + other: cli.other_execution.into(), + }; config.roles = role; - { - config.network.boot_nodes.extend(matches - .values_of("bootnodes") - .map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect::>())); - config.network.config_path = Some(network_path(&base_path, config.chain_spec.id()).to_string_lossy().into()); - config.network.net_config_path = config.network.config_path.clone(); - config.network.reserved_nodes.extend(matches - .values_of("reserved_nodes") - .map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect::>())); - if !config.network.reserved_nodes.is_empty() { - config.network.non_reserved_mode = NonReservedPeerMode::Deny; - } - - config.network.listen_addresses = Vec::new(); - for addr in matches.values_of("listen_addr").unwrap_or_default() { - let addr = addr.parse().map_err(|_| "Invalid listen multiaddress")?; - config.network.listen_addresses.push(addr); - } - if config.network.listen_addresses.is_empty() { - let port = match matches.value_of("port") { - Some(port) => port.parse().map_err(|_| "Invalid p2p port value specified.")?, - None => 30333, - }; - config.network.listen_addresses = vec![ - iter::once(Protocol::Ip4(Ipv4Addr::new(0, 0, 0, 0))) - .chain(iter::once(Protocol::Tcp(port))) - .collect() - ]; - } - - config.network.public_addresses = Vec::new(); - - config.network.client_version = config.client_id(); - config.network.use_secret = match matches.value_of("node_key").map(H256::from_str) { - Some(Ok(secret)) => Some(secret.into()), - Some(Err(err)) => bail!(create_input_err(format!("Error parsing node key: {}", err))), - None => None, - }; + let client_id = config.client_id(); + fill_network_configuration( + cli.network_config, + &base_path, + spec.id(), + &mut config.network, + client_id, + )?; - let in_peers = match matches.value_of("in_peers") { - Some(in_peers) => in_peers.parse().map_err(|_| "Invalid in-peers value specified.")?, - None => 25, - }; - let out_peers = match matches.value_of("out_peers") { - Some(out_peers) => out_peers.parse().map_err(|_| "Invalid out-peers value specified.")?, - None => 25, - }; + fill_transaction_pool_configuration::( + &mut config, + cli.pool_config, + )?; - config.network.in_peers = in_peers; - config.network.out_peers = out_peers; + if let Some(key) = cli.key { + config.keys.push(key); } - config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); - if matches.is_present("dev") { - config.keys.push("Alice".into()); + if cli.shared_params.dev { + config.keys.push("//Alice".into()); } - let rpc_interface: &str = if matches.is_present("rpc_external") { "0.0.0.0" } else { "127.0.0.1" }; - let ws_interface: &str = if matches.is_present("ws_external") { "0.0.0.0" } else { "127.0.0.1" }; + let rpc_interface: &str = if cli.rpc_external { "0.0.0.0" } else { "127.0.0.1" }; + let ws_interface: &str = if cli.ws_external { "0.0.0.0" } else { "127.0.0.1" }; - config.rpc_http = Some(parse_address(&format!("{}:{}", rpc_interface, 9933), "rpc_port", &matches)?); - config.rpc_ws = Some(parse_address(&format!("{}:{}", ws_interface, 9944), "ws_port", &matches)?); + config.rpc_http = Some( + parse_address(&format!("{}:{}", rpc_interface, 9933), cli.rpc_port)? + ); + config.rpc_ws = Some( + parse_address(&format!("{}:{}", ws_interface, 9944), cli.ws_port)? + ); // Override telemetry - if matches.is_present("no_telemetry") { - config.telemetry_url = None; - } else if let Some(url) = matches.value_of("telemetry_url") { - config.telemetry_url = Some(url.to_owned()); + if cli.no_telemetry { + config.telemetry_endpoints = None; + } else if !cli.telemetry_endpoints.is_empty() { + config.telemetry_endpoints = Some(TelemetryEndpoints::new(cli.telemetry_endpoints)); } - Ok((spec, config)) + Ok(config) } -fn get_db_path_for_subcommand( - main_cmd: &clap::ArgMatches, - sub_cmd: &clap::ArgMatches -) -> error::Result { - if main_cmd.is_present("chain") && sub_cmd.is_present("chain") { - bail!(create_input_err("`--chain` option is present two times")); - } - - fn check_contradicting_chain_dev_flags( - m0: &clap::ArgMatches, - m1: &clap::ArgMatches - ) -> error::Result<()> { - if m0.is_present("dev") && m1.is_present("chain") { - bail!(create_input_err("`--dev` and `--chain` given on different levels")); - } - - Ok(()) - } - - check_contradicting_chain_dev_flags(main_cmd, sub_cmd)?; - check_contradicting_chain_dev_flags(sub_cmd, main_cmd)?; - - let spec_id = if sub_cmd.is_present("chain") || sub_cmd.is_present("dev") { - get_chain_key(sub_cmd) - } else { - get_chain_key(main_cmd) - }; - - if main_cmd.is_present("base_path") && sub_cmd.is_present("base_path") { - bail!(create_input_err("`--base_path` option is present two times")); - } - - let base_path = if sub_cmd.is_present("base_path") { - base_path(sub_cmd) - } else { - base_path(main_cmd) - }; +fn run_node( + cli: MergeParameters, + spec_factory: S, + exit: E, + run_service: RS, + impl_name: &'static str, + version: &VersionInfo, +) -> error::Result<()> +where + RP: StructOpt + Clone, + F: ServiceFactory, + E: IntoExit, + S: FnOnce(&str) -> Result>>, String>, + RS: FnOnce(E, RP, FactoryFullConfiguration) -> Result<(), String>, + { + let config = create_run_node_config::(cli.left, spec_factory, impl_name, version)?; - Ok(db_path(&base_path, &spec_id)) + run_service(exit, cli.right, config).map_err(Into::into) } // @@ -383,71 +438,25 @@ fn get_db_path_for_subcommand( // 9803-9874 Unassigned // 9926-9949 Unassigned -/// execute default commands or return service configuration -pub fn execute_default<'a, F, E>( - spec: ChainSpec>, - exit: E, - matches: &clap::ArgMatches<'a>, - config: &FactoryFullConfiguration -) -> error::Result> -where - E: IntoExit, - F: ServiceFactory, -{ - panic_hook::set(); - - let log_pattern = matches.value_of("log").unwrap_or(""); - init_logger(log_pattern); - fdlimit::raise_fd_limit(); - - if let Some(matches) = matches.subcommand_matches("build-spec") { - build_spec::(matches, spec, config)?; - return Ok(Action::ExecutedInternally); - } else if let Some(sub_matches) = matches.subcommand_matches("export-blocks") { - export_blocks::( - get_db_path_for_subcommand(matches, sub_matches)?, - matches, - spec, - exit.into_exit() - )?; - return Ok(Action::ExecutedInternally); - } else if let Some(sub_matches) = matches.subcommand_matches("import-blocks") { - import_blocks::( - get_db_path_for_subcommand(matches, sub_matches)?, - matches, - spec, - exit.into_exit() - )?; - return Ok(Action::ExecutedInternally); - } else if let Some(sub_matches) = matches.subcommand_matches("revert") { - revert_chain::( - get_db_path_for_subcommand(matches, sub_matches)?, - matches, - spec - )?; - return Ok(Action::ExecutedInternally); - } else if let Some(sub_matches) = matches.subcommand_matches("purge-chain") { - purge_chain::(get_db_path_for_subcommand(matches, sub_matches)?)?; - return Ok(Action::ExecutedInternally); - } - - Ok(Action::RunService(exit)) -} - fn with_default_boot_node( - spec: &ChainSpec>, - config: &NetworkConfiguration + mut spec: ChainSpec>, + cli: &BuildSpecCmd, + version: &VersionInfo, ) -> error::Result>> where F: ServiceFactory { - let mut spec = spec.clone(); if spec.boot_nodes().is_empty() { + let network_path = + Some(network_path(&base_path(&cli.shared_params, version), spec.id()).to_string_lossy().into()); + let network_key = parse_node_key(cli.node_key.clone())?; + let network_keys = - network::obtain_private_key(config) + network::obtain_private_key(&network_key, &network_path) .map_err(|err| format!("Error obtaining network key: {}", err))?; + let peer_id = network_keys.to_peer_id(); - let addr = multiaddr![ + let addr = build_multiaddr![ Ip4([127, 0, 0, 1]), Tcp(30333u16), P2p(peer_id) @@ -457,142 +466,147 @@ where Ok(spec) } -fn build_spec( - matches: &clap::ArgMatches, - spec: ChainSpec>, - config: &FactoryFullConfiguration +fn build_spec( + cli: BuildSpecCmd, + spec_factory: S, + version: &VersionInfo, ) -> error::Result<()> where - F: ServiceFactory + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, { info!("Building chain spec"); - let raw = matches.is_present("raw"); - let spec = with_default_boot_node::(&spec, &config.network)?; - let json = service::chain_ops::build_spec::>(spec, raw)?; + let spec = load_spec(&cli.shared_params, spec_factory)?; + let spec = with_default_boot_node::(spec, &cli, version)?; + let json = service::chain_ops::build_spec::>(spec, cli.raw)?; + print!("{}", json); + Ok(()) } -fn export_blocks( - db_path: PathBuf, - matches: &clap::ArgMatches, - spec: ChainSpec>, - exit: E +fn create_config_with_db_path( + spec_factory: S, cli: &SharedParams, version: &VersionInfo, +) -> error::Result> +where + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, +{ + let spec = load_spec(cli, spec_factory)?; + let base_path = base_path(cli, version); + + let mut config = service::Configuration::default_with_spec(spec.clone()); + config.database_path = db_path(&base_path, spec.id()).to_string_lossy().into(); + + Ok(config) +} + +fn export_blocks( + cli: ExportBlocksCmd, + spec_factory: S, + exit: E, + version: &VersionInfo, ) -> error::Result<()> - where F: ServiceFactory, E: Future + Send + 'static, +where + F: ServiceFactory, + E: IntoExit, + S: FnOnce(&str) -> Result>>, String>, { - let mut config = service::Configuration::default_with_spec(spec); - config.database_path = db_path.to_string_lossy().into(); - info!("DB path: {}", config.database_path); - let from: u64 = match matches.value_of("from") { - Some(v) => v.parse().map_err(|_| "Invalid --from argument")?, - None => 1, - }; + let config = create_config_with_db_path::(spec_factory, &cli.shared_params, version)?; - let to: Option = match matches.value_of("to") { - Some(v) => Some(v.parse().map_err(|_| "Invalid --to argument")?), - None => None, - }; - let json = matches.is_present("json"); + info!("DB path: {}", config.database_path); + let from = cli.from.unwrap_or(1); + let to = cli.to; + let json = cli.json; - let file: Box = match matches.value_of("output") { + let file: Box = match cli.output { Some(filename) => Box::new(File::create(filename)?), None => Box::new(stdout()), }; - Ok(service::chain_ops::export_blocks::(config, exit, file, As::sa(from), to.map(As::sa), json)?) + service::chain_ops::export_blocks::( + config, exit.into_exit(), file, As::sa(from), to.map(As::sa), json + ).map_err(Into::into) } -fn import_blocks( - db_path: PathBuf, - matches: &clap::ArgMatches, - spec: ChainSpec>, - exit: E +fn import_blocks( + cli: ImportBlocksCmd, + spec_factory: S, + exit: E, + version: &VersionInfo, ) -> error::Result<()> - where F: ServiceFactory, E: Future + Send + 'static, +where + F: ServiceFactory, + E: IntoExit, + S: FnOnce(&str) -> Result>>, String>, { - let mut config = service::Configuration::default_with_spec(spec); - config.database_path = db_path.to_string_lossy().into(); - - if let Some(s) = matches.value_of("execution") { - config.block_execution_strategy = match s { - "both" => service::ExecutionStrategy::Both, - "native" => service::ExecutionStrategy::NativeWhenPossible, - "wasm" => service::ExecutionStrategy::AlwaysWasm, - _ => return Err(error::ErrorKind::Input("Invalid block execution mode specified".to_owned()).into()), - }; - } - - if let Some(s) = matches.value_of("api-execution") { - config.api_execution_strategy = match s { - "both" => service::ExecutionStrategy::Both, - "native" => service::ExecutionStrategy::NativeWhenPossible, - "wasm" => service::ExecutionStrategy::AlwaysWasm, - _ => return Err(error::ErrorKind::Input("Invalid API execution mode specified".to_owned()).into()), - }; - } + let config = create_config_with_db_path::(spec_factory, &cli.shared_params, version)?; - let file: Box = match matches.value_of("input") { + let file: Box = match cli.input { Some(filename) => Box::new(File::open(filename)?), None => Box::new(stdin()), }; - Ok(service::chain_ops::import_blocks::(config, exit, file)?) + service::chain_ops::import_blocks::(config, exit.into_exit(), file).map_err(Into::into) } -fn revert_chain( - db_path: PathBuf, - matches: &clap::ArgMatches, - spec: ChainSpec> +fn revert_chain( + cli: RevertCmd, + spec_factory: S, + version: &VersionInfo, ) -> error::Result<()> - where F: ServiceFactory, +where + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, { - let mut config = service::Configuration::default_with_spec(spec); - config.database_path = db_path.to_string_lossy().into(); - - let blocks = match matches.value_of("num") { - Some(v) => v.parse().map_err(|_| "Invalid block count specified")?, - None => 256, - }; - + let config = create_config_with_db_path::(spec_factory, &cli.shared_params, version)?; + let blocks = cli.num; Ok(service::chain_ops::revert_chain::(config, As::sa(blocks))?) } -fn purge_chain( - db_path: PathBuf, +fn purge_chain( + cli: PurgeChainCmd, + spec_factory: S, + version: &VersionInfo, ) -> error::Result<()> - where F: ServiceFactory, +where + F: ServiceFactory, + S: FnOnce(&str) -> Result>>, String>, { - print!("Are you sure to remove {:?}? (y/n)", &db_path); - stdout().flush().expect("failed to flush stdout"); - - let mut input = String::new(); - stdin().read_line(&mut input)?; - let input = input.trim(); - - match input.chars().nth(0) { - Some('y') | Some('Y') => { - fs::remove_dir_all(&db_path)?; - println!("{:?} removed.", &db_path); - }, - _ => println!("Aborted"), + let config = create_config_with_db_path::(spec_factory, &cli.shared_params, version)?; + let db_path = config.database_path; + + if cli.yes == false { + print!("Are you sure to remove {:?}? (y/n)", &db_path); + stdout().flush().expect("failed to flush stdout"); + + let mut input = String::new(); + stdin().read_line(&mut input)?; + let input = input.trim(); + + match input.chars().nth(0) { + Some('y') | Some('Y') => {}, + _ => { + println!("Aborted"); + return Ok(()); + }, + } } + fs::remove_dir_all(&db_path)?; + println!("{:?} removed.", &db_path); + Ok(()) } fn parse_address( - default: &str, - port_param: &str, - matches: &clap::ArgMatches + address: &str, + port: Option, ) -> Result { - let mut address: SocketAddr = default.parse().ok().ok_or_else( - || format!("Invalid address specified for --{}.", port_param) + let mut address: SocketAddr = address.parse().map_err( + |_| format!("Invalid address: {}", address) )?; - if let Some(port) = matches.value_of(port_param) { - let port: u16 = port.parse().ok().ok_or_else( - || format!("Invalid port for --{} specified.", port_param) - )?; + if let Some(port) = port { address.set_port(port); } @@ -623,20 +637,6 @@ fn network_path(base_path: &Path, chain_id: &str) -> PathBuf { path } -fn default_base_path() -> PathBuf { - use app_dirs::{AppInfo, AppDataType}; - - let app_info = AppInfo { - name: "Substrate", - author: "Parity Technologies", - }; - - app_dirs::get_app_root( - AppDataType::UserData, - &app_info, - ).expect("app directories exist on all supported platforms; qed") -} - fn init_logger(pattern: &str) { use ansi_term::Colour; @@ -656,13 +656,27 @@ fn init_logger(pattern: &str) { let enable_color = isatty; builder.format(move |buf, record| { - let timestamp = time::strftime("%Y-%m-%d %H:%M:%S", &time::now()).expect("Error formatting log timestamp"); + let now = time::now(); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S", &now) + .expect("Error formatting log timestamp"); let mut output = if log::max_level() <= log::LevelFilter::Info { format!("{} {}", Colour::Black.bold().paint(timestamp), record.args()) } else { - let name = ::std::thread::current().name().map_or_else(Default::default, |x| format!("{}", Colour::Blue.bold().paint(x))); - format!("{} {} {} {} {}", Colour::Black.bold().paint(timestamp), name, record.level(), record.target(), record.args()) + let name = ::std::thread::current() + .name() + .map_or_else(Default::default, |x| format!("{}", Colour::Blue.bold().paint(x))); + let millis = (now.tm_nsec as f32 / 1000000.0).round() as usize; + let timestamp = format!("{}.{:03}", timestamp, millis); + format!( + "{} {} {} {} {}", + Colour::Black.bold().paint(timestamp), + name, + record.level(), + record.target(), + record.args() + ) }; if !enable_color { diff --git a/core/cli/src/params.rs b/core/cli/src/params.rs index 59d1d68233a877920a0a59165aca5e04c74735a8..bffd71b8c76f934f30586b453e1e0355881b3c87 100644 --- a/core/cli/src/params.rs +++ b/core/cli/src/params.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,234 +14,477 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use crate::traits::{AugmentClap, GetLogFilter}; + use std::path::PathBuf; -use structopt::StructOpt; +use structopt::{StructOpt, clap::{arg_enum, _clap_count_exprs, App, AppSettings, SubCommand}}; +use client; + +/// Auxialary macro to implement `GetLogFilter` for all types that have the `shared_params` field. +macro_rules! impl_get_log_filter { + ( $type:ident ) => { + impl $crate::GetLogFilter for $type { + fn get_log_filter(&self) -> Option { + self.shared_params.get_log_filter() + } + } + } +} + +arg_enum! { + /// How to execute blocks + #[derive(Debug, Clone)] + pub enum ExecutionStrategy { + Native, + Wasm, + Both, + NativeElseWasm, + } +} + +impl Into for ExecutionStrategy { + fn into(self) -> client::ExecutionStrategy { + match self { + ExecutionStrategy::Native => client::ExecutionStrategy::NativeWhenPossible, + ExecutionStrategy::Wasm => client::ExecutionStrategy::AlwaysWasm, + ExecutionStrategy::Both => client::ExecutionStrategy::Both, + ExecutionStrategy::NativeElseWasm => client::ExecutionStrategy::NativeElseWasm, + } + } +} + +/// Shared parameters used by all `CoreParams`. +#[derive(Debug, StructOpt, Clone)] +pub struct SharedParams { + /// Specify the chain specification (one of dev, local or staging) + #[structopt(long = "chain", value_name = "CHAIN_SPEC")] + pub chain: Option, + + /// Specify the development chain + #[structopt(long = "dev")] + pub dev: bool, + + /// Specify custom base path. + #[structopt(long = "base-path", short = "d", value_name = "PATH", parse(from_os_str))] + pub base_path: Option, -/// CLI Parameters provided by default -#[derive(Debug, StructOpt)] -#[structopt(name = "Substrate")] -pub struct CoreParams { ///Sets a custom logging filter #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] - log: Option, + pub log: Option, +} + +impl GetLogFilter for SharedParams { + fn get_log_filter(&self) -> Option { + self.log.clone() + } +} + +/// Parameters used to create the network configuration. +#[derive(Debug, StructOpt, Clone)] +pub struct NetworkConfigurationParams { + /// Specify a list of bootnodes + #[structopt(long = "bootnodes", value_name = "URL")] + pub bootnodes: Vec, + + /// Specify a list of reserved node addresses + #[structopt(long = "reserved-nodes", value_name = "URL")] + pub reserved_nodes: Vec, + + /// Listen on this multiaddress + #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] + pub listen_addr: Vec, + /// Specify p2p protocol TCP port. Only used if --listen-addr is not specified. + #[structopt(long = "port", value_name = "PORT")] + pub port: Option, + + /// Specify node secret key (64-character hex string) + #[structopt(long = "node-key", value_name = "KEY")] + pub node_key: Option, + + /// Specify the number of outgoing connections we're trying to maintain + #[structopt(long = "out-peers", value_name = "OUT_PEERS", default_value = "25")] + pub out_peers: u32, + + /// Specify the maximum number of incoming connections we're accepting + #[structopt(long = "in-peers", value_name = "IN_PEERS", default_value = "25")] + pub in_peers: u32, +} + +/// Parameters used to create the pool configuration. +#[derive(Debug, StructOpt, Clone)] +pub struct TransactionPoolParams { + /// Maximum number of transactions in the transaction pool. + #[structopt(long = "pool-limit", value_name = "COUNT", default_value = "512")] + pub pool_limit: usize, + /// Maximum number of kilobytes of all transactions stored in the pool. + #[structopt(long = "pool-kbytes", value_name = "COUNT", default_value="10240")] + pub pool_kbytes: usize, +} + +/// The `run` command used to run a node. +#[derive(Debug, StructOpt, Clone)] +pub struct RunCmd { /// Specify custom keystore path #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] - keystore_path: Option, + pub keystore_path: Option, /// Specify additional key seed #[structopt(long = "key", value_name = "STRING")] - key: Option, - - /// Specify node secret key (64-character hex string) - #[structopt(long = "node-key", value_name = "KEY")] - node_key: Option, + pub key: Option, /// Enable validator mode #[structopt(long = "validator")] - validator: bool, + pub validator: bool, /// Run in light client mode #[structopt(long = "light")] - light: bool, + pub light: bool, /// Limit the memory the database cache can use #[structopt(long = "db-cache", value_name = "MiB")] - database_cache_size: Option, - - /// Listen on this multiaddress - #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] - listen_addr: Vec, - - /// Specify p2p protocol TCP port. Only used if --listen-addr is not specified. - #[structopt(long = "port", value_name = "PORT")] - port: Option, + pub database_cache_size: Option, /// Listen to all RPC interfaces (default is local) #[structopt(long = "rpc-external")] - rpc_external: bool, + pub rpc_external: bool, /// Listen to all Websocket interfaces (default is local) #[structopt(long = "ws-external")] - ws_external: bool, + pub ws_external: bool, /// Specify HTTP RPC server TCP port #[structopt(long = "rpc-port", value_name = "PORT")] - rpc_port: Option, + pub rpc_port: Option, /// Specify WebSockets RPC server TCP port #[structopt(long = "ws-port", value_name = "PORT")] - ws_port: Option, - - /// Specify a list of bootnodes - #[structopt(long = "bootnodes", value_name = "URL")] - bootnodes: Vec, - - /// Specify a list of reserved node addresses - #[structopt(long = "reserved-nodes", value_name = "URL")] - reserved_nodes: Vec, - - /// Specify the number of outgoing connections we're trying to maintain - #[structopt(long = "out-peers", value_name = "OUT_PEERS")] - out_peers: Option, - - /// Specify the maximum number of incoming connections we're accepting - #[structopt(long = "in-peers", value_name = "IN_PEERS")] - in_peers: Option, + pub ws_port: Option, /// Specify the pruning mode, a number of blocks to keep or 'archive'. Default is 256. #[structopt(long = "pruning", value_name = "PRUNING_MODE")] - pruning: Option, + pub pruning: Option, /// The human-readable name for this node, as reported to the telemetry server, if enabled #[structopt(long = "name", value_name = "NAME")] - name: Option, - - /// Should connect to the Substrate telemetry server (telemetry is off by default on local chains) - #[structopt(short = "t", long = "telemetry")] - telemetry: bool, + pub name: Option, /// Should not connect to the Substrate telemetry server (telemetry is on by default on global chains) #[structopt(long = "no-telemetry")] - no_telemetry: bool, + pub no_telemetry: bool, + + /// The URL of the telemetry server to connect to. This flag can be passed multiple times + /// as a mean to specify multiple telemetry endpoints. Verbosity levels range from 0-9, with + /// 0 denoting the least verbosity. If no verbosity level is specified the default is 0. + #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = "parse_telemetry_endpoints"))] + pub telemetry_endpoints: Vec<(String, u8)>, + + /// The means of execution used when calling into the runtime while syncing blocks. + #[structopt( + long = "syncing-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""NativeElseWasm""# + ) + )] + pub syncing_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while importing blocks. + #[structopt( + long = "importing-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""NativeElseWasm""# + ) + )] + pub importing_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while constructing blocks. + #[structopt( + long = "block-construction-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""Wasm""# + ) + )] + pub block_construction_execution: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. + #[structopt( + long = "other-execution", + value_name = "STRATEGY", + raw( + possible_values = "&ExecutionStrategy::variants()", + case_insensitive = "true", + default_value = r#""Wasm""# + ) + )] + pub other_execution: ExecutionStrategy, + + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub network_config: NetworkConfigurationParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub pool_config: TransactionPoolParams, +} - /// The URL of the telemetry server. Implies --telemetry - #[structopt(long = "telemetry-url", value_name = "TELEMETRY_URL")] - telemetry_url: Option, +/// Default to verbosity level 0, if none is provided. +fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), Box> { + let pos = s.find(' '); + match pos { + None => { + Ok((s.to_owned(), 0)) + }, + Some(pos_) => { + let verbosity = s[pos_ + 1..].parse()?; + let url = s[..pos_].parse()?; + Ok((url, verbosity)) + } + } +} + +impl_augment_clap!(RunCmd); +impl_get_log_filter!(RunCmd); - /// The means of execution used when calling into the runtime. Can be either wasm, native or both. - #[structopt(long = "execution", value_name = "STRATEGY")] - execution: Option, +/// The `build-spec` command used to build a specification. +#[derive(Debug, StructOpt, Clone)] +pub struct BuildSpecCmd { + /// Force raw genesis storage output. + #[structopt(long = "raw")] + pub raw: bool, #[allow(missing_docs)] #[structopt(flatten)] - shared_flags: SharedFlags, + pub shared_params: SharedParams, - #[structopt(subcommand)] - cmds: Option, + /// Specify node secret key (64-character hex string) + #[structopt(long = "node-key", value_name = "KEY")] + pub node_key: Option, } -/// How to execute blocks -#[derive(Debug, StructOpt)] -pub enum ExecutionStrategy { - /// Execute native only - Native, - /// Execute wasm only - Wasm, - /// Execute natively when possible, wasm otherwise - Both, +impl_get_log_filter!(BuildSpecCmd); + +/// The `export-blocks` command used to export blocks. +#[derive(Debug, StructOpt, Clone)] +pub struct ExportBlocksCmd { + /// Output file name or stdout if unspecified. + #[structopt(parse(from_os_str))] + pub output: Option, + + /// Specify starting block number. 1 by default. + #[structopt(long = "from", value_name = "BLOCK")] + pub from: Option, + + /// Specify last block number. Best block by default. + #[structopt(long = "to", value_name = "BLOCK")] + pub to: Option, + + /// Use JSON output rather than binary. + #[structopt(long = "json")] + pub json: bool, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, } -impl Default for ExecutionStrategy { - fn default() -> Self { - ExecutionStrategy::Both - } +impl_get_log_filter!(ExportBlocksCmd); + +/// The `import-blocks` command used to import blocks. +#[derive(Debug, StructOpt, Clone)] +pub struct ImportBlocksCmd { + /// Input file or stdin if unspecified. + #[structopt(parse(from_os_str))] + pub input: Option, + + /// The default number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. + #[structopt(long = "default-heap-pages", value_name = "COUNT")] + pub default_heap_pages: Option, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, } -impl std::str::FromStr for ExecutionStrategy { - type Err = String; - fn from_str(input: &str) -> Result { - match input { - "native" => Ok(ExecutionStrategy::Native), - "wasm" | "webassembly" => Ok(ExecutionStrategy::Wasm), - "both" => Ok(ExecutionStrategy::Both), - _ => Err("Please specify either 'native', 'wasm' or 'both".to_owned()) +impl_get_log_filter!(ImportBlocksCmd); - } - } +/// The `revert` command used revert the chain to a previos state. +#[derive(Debug, StructOpt, Clone)] +pub struct RevertCmd { + /// Number of blocks to revert. + #[structopt(default_value = "256")] + pub num: u64, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, } -/// Flags used by `CoreParams` and almost all `CoreCommands`. -#[derive(Debug, StructOpt)] -pub struct SharedFlags { - /// Specify the chain specification (one of dev, local or staging) - #[structopt(long = "chain", value_name = "CHAIN_SPEC")] - chain: Option, +impl_get_log_filter!(RevertCmd); - /// Specify the development chain - #[structopt(long = "dev")] - dev: bool, +/// The `purge-chain` command used to remove the whole chain. +#[derive(Debug, StructOpt, Clone)] +pub struct PurgeChainCmd { + /// Skip interactive prompt by answering yes automatically. + #[structopt(short = "y")] + pub yes: bool, - /// Specify custom base path. - #[structopt(long = "base-path", short = "d", value_name = "PATH")] - base_path: Option, -} - -/// Subcommands provided by Default -#[derive(Debug, StructOpt)] -pub enum CoreCommands { - /// Build a spec.json file, outputing to stdout - #[structopt(name = "build-spec")] - BuildSpec { - /// Force raw genesis storage output. - #[structopt(long = "raw")] - raw: bool, - }, - - /// Export blocks to a file - #[structopt(name = "export-blocks")] - ExportBlocks { - /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] - output: Option, - - /// Specify starting block number. 1 by default. - #[structopt(long = "from", value_name = "BLOCK")] - from: Option, - - /// Specify last block number. Best block by default. - #[structopt(long = "to", value_name = "BLOCK")] - to: Option, - - /// Use JSON output rather than binary. - #[structopt(long = "json")] - json: bool, - - #[allow(missing_docs)] - #[structopt(flatten)] - shared_flags: SharedFlags, - }, + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, +} + +impl_get_log_filter!(PurgeChainCmd); + +/// All core commands that are provided by default. +/// +/// The core commands are split into multiple subcommands and `Run` is the default subcommand. From +/// the CLI user perspective, it is not visible that `Run` is a subcommand. So, all parameters of +/// `Run` are exported as main executable parameters. +#[derive(Debug, Clone)] +pub enum CoreParams { + /// Run a node. + Run(MergeParameters), + + /// Build a spec.json file, outputing to stdout. + BuildSpec(BuildSpecCmd), + + /// Export blocks to a file. + ExportBlocks(ExportBlocksCmd), /// Import blocks from file. - #[structopt(name = "import-blocks")] - ImportBlocks { - /// Input file or stdin if unspecified. - #[structopt(parse(from_os_str))] - input: Option, - - /// The means of execution used when executing blocks. Can be either wasm, native or both. - #[structopt(long = "execution", value_name = "STRATEGY")] - execution: ExecutionStrategy, - - /// The means of execution used when calling into the runtime. Can be either wasm, native or both. - #[structopt(long = "api-execution", value_name = "STRATEGY")] - api_execution: ExecutionStrategy, - - /// The maximum number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. - #[structopt(long = "max-heap-pages", value_name = "COUNT")] - max_heap_pages: Option, - - #[allow(missing_docs)] - #[structopt(flatten)] - shared_flags: SharedFlags, - }, - - ///Revert chain to the previous state - #[structopt(name = "revert")] - Revert { - /// Number of blocks to revert. Default is 256. - num: Option, - - #[allow(missing_docs)] - #[structopt(flatten)] - shared_flags: SharedFlags, - }, + ImportBlocks(ImportBlocksCmd), + + /// Revert chain to the previous state. + Revert(RevertCmd), /// Remove the whole chain data. - #[structopt(name = "purge-chain")] - PurgeChain { - #[allow(missing_docs)] - #[structopt(flatten)] - shared_flags: SharedFlags, - }, + PurgeChain(PurgeChainCmd), + + /// Further custom subcommands. + Custom(CC), +} + +impl StructOpt for CoreParams where + CC: StructOpt + GetLogFilter, + RP: StructOpt + AugmentClap +{ + fn clap<'a, 'b>() -> App<'a, 'b> { + RP::augment_clap( + RunCmd::augment_clap( + CC::clap().unset_setting(AppSettings::SubcommandRequiredElseHelp) + ) + ).subcommand( + BuildSpecCmd::augment_clap(SubCommand::with_name("build-spec")) + .about("Build a spec.json file, outputing to stdout.") + ) + .subcommand( + ExportBlocksCmd::augment_clap(SubCommand::with_name("export-blocks")) + .about("Export blocks to a file.") + ) + .subcommand( + ImportBlocksCmd::augment_clap(SubCommand::with_name("import-blocks")) + .about("Import blocks from file.") + ) + .subcommand( + RevertCmd::augment_clap(SubCommand::with_name("revert")) + .about("Revert chain to the previous state.") + ) + .subcommand( + PurgeChainCmd::augment_clap(SubCommand::with_name("purge-chain")) + .about("Remove the whole chain data.") + ) + } + + fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { + match matches.subcommand() { + ("build-spec", Some(matches)) => + CoreParams::BuildSpec(BuildSpecCmd::from_clap(matches)), + ("export-blocks", Some(matches)) => + CoreParams::ExportBlocks(ExportBlocksCmd::from_clap(matches)), + ("import-blocks", Some(matches)) => + CoreParams::ImportBlocks(ImportBlocksCmd::from_clap(matches)), + ("revert", Some(matches)) => CoreParams::Revert(RevertCmd::from_clap(matches)), + ("purge-chain", Some(matches)) => + CoreParams::PurgeChain(PurgeChainCmd::from_clap(matches)), + (_, None) => CoreParams::Run(MergeParameters::from_clap(matches)), + _ => CoreParams::Custom(CC::from_clap(matches)), + } + } +} + +impl GetLogFilter for CoreParams where CC: GetLogFilter { + fn get_log_filter(&self) -> Option { + match self { + CoreParams::Run(c) => c.left.get_log_filter(), + CoreParams::BuildSpec(c) => c.get_log_filter(), + CoreParams::ExportBlocks(c) => c.get_log_filter(), + CoreParams::ImportBlocks(c) => c.get_log_filter(), + CoreParams::PurgeChain(c) => c.get_log_filter(), + CoreParams::Revert(c) => c.get_log_filter(), + CoreParams::Custom(c) => c.get_log_filter(), + } + } +} + +/// A special commandline parameter that expands to nothing. +/// Should be used as custom subcommand/run arguments if no custom values are required. +#[derive(Clone, Debug)] +pub struct NoCustom {} + +impl StructOpt for NoCustom { + fn clap<'a, 'b>() -> App<'a, 'b> { + App::new("NoCustom") + } + + fn from_clap(_: &::structopt::clap::ArgMatches) -> Self { + NoCustom {} + } +} + +impl AugmentClap for NoCustom { + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + app + } +} + +impl GetLogFilter for NoCustom { + fn get_log_filter(&self) -> Option { + None + } +} + +/// Merge all CLI parameters of `L` and `R` into the same level. +#[derive(Clone, Debug)] +pub struct MergeParameters { + /// The left side parameters. + pub left: L, + /// The right side parameters. + pub right: R, +} + +impl StructOpt for MergeParameters where L: StructOpt + AugmentClap, R: StructOpt { + fn clap<'a, 'b>() -> App<'a, 'b> { + L::augment_clap(R::clap()) + } + + fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { + MergeParameters { + left: L::from_clap(matches), + right: R::from_clap(matches), + } + } } diff --git a/core/cli/src/traits.rs b/core/cli/src/traits.rs new file mode 100644 index 0000000000000000000000000000000000000000..ddb389e454ece4aafacc64e7a40e02a171255e68 --- /dev/null +++ b/core/cli/src/traits.rs @@ -0,0 +1,44 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use structopt::{StructOpt, clap::App}; + +/// Something that can augment a clapp app with further parameters. +/// `derive(StructOpt)` is implementing this function by default, so a macro `impl_augment_clap!` +/// is provided to simplify the implementation of this trait. +pub trait AugmentClap: StructOpt { + /// Augment the given clap `App` with further parameters. + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b>; +} + +/// Macro for implementing the `AugmentClap` trait. +/// This requires that the given type uses `derive(StructOpt)`! +#[macro_export] +macro_rules! impl_augment_clap { + ( $type:ident ) => { + impl $crate::AugmentClap for $type { + fn augment_clap<'a, 'b>(app: $crate::App<'a, 'b>) -> $crate::App<'a, 'b> { + $type::augment_clap(app) + } + } + } +} + +/// Returns the log filter given by the user as commandline argument. +pub trait GetLogFilter { + /// Returns the set log filter. + fn get_log_filter(&self) -> Option; +} diff --git a/core/client/Cargo.toml b/core/client/Cargo.toml index 1da261cb4bc698e6a56683ce5e528bf142c1eac1..f797d93f1fe9ce6fedb29ae7a267b274c1601bef 100644 --- a/core/client/Cargo.toml +++ b/core/client/Cargo.toml @@ -2,57 +2,57 @@ name = "substrate-client" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] error-chain = { version = "0.12", optional = true } fnv = { version = "1.0", optional = true } log = { version = "0.4", optional = true } -parking_lot = { version = "0.4", optional = true } -hex-literal = { version = "0.1", optional = true } +parking_lot = { version = "0.7.1", optional = true } +hex = { package = "hex-literal", version = "0.1", optional = true } futures = { version = "0.1.17", optional = true } -slog = { version = "^2", optional = true } heapsize = { version = "0.4", optional = true } -substrate-consensus-common = { path = "../consensus/common", optional = true } -substrate-executor = { path = "../executor", optional = true } -substrate-state-machine = { path = "../state-machine", optional = true } -substrate-keyring = { path = "../keyring", optional = true } -substrate-trie = { path = "../trie", optional = true } +consensus = { package = "substrate-consensus-common", path = "../consensus/common", optional = true } +executor = { package = "substrate-executor", path = "../executor", optional = true } +state-machine = { package = "substrate-state-machine", path = "../state-machine", optional = true } +keyring = { package = "substrate-keyring", path = "../keyring", optional = true } +trie = { package = "substrate-trie", path = "../trie", optional = true } substrate-telemetry = { path = "../telemetry", optional = true } -hash-db = { git = "https://github.com/paritytech/trie", optional = true } -kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } - -parity-codec = { version = "2.1", default-features = false } -substrate-primitives = { path = "../primitives", default-features = false } -sr-primitives = { path = "../sr-primitives", default-features = false } -sr-version = { path = "../sr-version", default-features = false } -sr-std = { path = "../sr-std", default-features = false } +hash-db = { version = "0.11", optional = true } +kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } +runtime-primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } +runtime-version = { package = "sr-version", path = "../sr-version", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +inherents = { package = "substrate-inherents", path = "../inherents", default-features = false } sr-api-macros = { path = "../sr-api-macros" } [dev-dependencies] -substrate-test-client = { path = "../test-client" } -kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } +test-client = { package = "substrate-test-client", path = "../test-client" } +kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } [features] default = ["std"] std = [ "parity-codec/std", - "substrate-consensus-common", - "substrate-primitives/std", + "consensus", + "primitives/std", + "inherents/std", "parking_lot", "error-chain", "fnv", "log", - "hex-literal", + "hex", "futures", - "slog", "heapsize", - "substrate-executor", - "sr-primitives/std", - "sr-version/std", - "sr-std/std", - "substrate-state-machine", - "substrate-keyring", - "substrate-trie", + "executor", + "runtime-primitives/std", + "runtime-version/std", + "rstd/std", + "state-machine", + "keyring", + "trie", "substrate-telemetry", "hash-db", "kvdb" diff --git a/core/client/db/Cargo.toml b/core/client/db/Cargo.toml index 9536fe803af0cd3d960222afd0afbd6eeaca3f99..97de2cd7cdc8be20053d263645828971bbc59202 100644 --- a/core/client/db/Cargo.toml +++ b/core/client/db/Cargo.toml @@ -2,24 +2,32 @@ name = "substrate-client-db" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -parking_lot = "0.4" +parking_lot = "0.7.1" log = "0.4" -kvdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } -kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } -hash-db = { git = "https://github.com/paritytech/trie" } -substrate-primitives = { path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } -substrate-client = { path = "../../client" } -substrate-state-machine = { path = "../../state-machine" } -parity-codec = "2.1" -parity-codec-derive = "2.1" -substrate-executor = { path = "../../executor" } -substrate-state-db = { path = "../../state-db" } -substrate-trie = { path = "../../trie" } +kvdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } +# FIXME replace with release as soon as our rocksdb changes are released upstream https://github.com/paritytech/parity-common/issues/88 +kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } +kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d", optional = true } +lru-cache = "0.1.1" +hash-db = { version = "0.11" } +primitives = { package = "substrate-primitives", path = "../../primitives" } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } +client = { package = "substrate-client", path = "../../client" } +state-machine = { package = "substrate-state-machine", path = "../../state-machine" } +parity-codec = { version = "3.2", features = ["derive"] } +executor = { package = "substrate-executor", path = "../../executor" } +state_db = { package = "substrate-state-db", path = "../../state-db" } +trie = { package = "substrate-trie", path = "../../trie" } [dev-dependencies] -kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="616b40150ded71f57f650067fcbc5c99d7c343e6" } +kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } substrate-keyring = { path = "../../keyring" } -substrate-test-client = { path = "../../test-client" } +test-client = { package = "substrate-test-client", path = "../../test-client" } +env_logger = { version = "0.6" } + +[features] +default = [] +test-helpers = ["kvdb-memorydb"] diff --git a/core/client/db/src/cache/list_cache.rs b/core/client/db/src/cache/list_cache.rs index 6d95349ee351fa97bcb5ebe5af1961b4b68cd495..1e641534f969c0d63eefe387e98c9ded8bb3c81a 100644 --- a/core/client/db/src/cache/list_cache.rs +++ b/core/client/db/src/cache/list_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -41,12 +41,14 @@ use std::collections::BTreeSet; +use log::warn; + use client::error::{ErrorKind as ClientErrorKind, Result as ClientResult}; use runtime_primitives::traits::{Block as BlockT, NumberFor, As, Zero}; -use cache::{CacheItemT, ComplexBlockId}; -use cache::list_entry::{Entry, StorageEntry}; -use cache::list_storage::{Storage, StorageTransaction, Metadata}; +use crate::cache::{CacheItemT, ComplexBlockId}; +use crate::cache::list_entry::{Entry, StorageEntry}; +use crate::cache::list_storage::{Storage, StorageTransaction, Metadata}; /// List-based cache. pub struct ListCache> { @@ -583,15 +585,16 @@ fn read_forks>( #[cfg(test)] pub mod tests { + use test_client::runtime::H256; use runtime_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; use runtime_primitives::traits::Header as HeaderT; - use cache::list_storage::tests::{DummyStorage, FaultyStorage, DummyTransaction}; + use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage, DummyTransaction}; use super::*; type Block = RawBlock>; pub fn test_id(number: u64) -> ComplexBlockId { - ComplexBlockId::new(From::from(number), number) + ComplexBlockId::new(H256::from_low_u64_be(number), number) } fn correct_id(number: u64) -> ComplexBlockId { @@ -619,7 +622,7 @@ pub mod tests { Header { parent_hash: fork_header(fork_nonce, fork_from, number - 1).hash(), number, - state_root: (1 + fork_nonce).into(), + state_root: H256::from_low_u64_be(1 + fork_nonce), extrinsics_root: Default::default(), digest: Default::default(), } @@ -638,7 +641,7 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, 50.into()) + .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: None }), 1024, test_id(100) @@ -648,7 +651,7 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, 50.into()) + .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), 1024, test_id(100) @@ -658,7 +661,7 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(100, 100.into()) + .with_id(100, H256::from_low_u64_be(100)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), 1024, test_id(100) @@ -669,18 +672,18 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, 50.into()) + .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), 1024, test_id(100) - ).value_at_block(&ComplexBlockId::new(2.into(), 100)).unwrap(), None); + ).value_at_block(&ComplexBlockId::new(H256::from_low_u64_be(2), 100)).unwrap(), None); // when block is later than last finalized block AND there are no forks AND finalized value is None // ---> [100] --- 200 assert_eq!(ListCache::<_, u64, _>::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, 50.into()) + .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: None }), 1024, test_id(100) ).value_at_block(&test_id(200)).unwrap(), None); @@ -689,7 +692,7 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, 50.into()) + .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }), 1024, test_id(100) ).value_at_block(&test_id(200)).unwrap(), Some(100)); @@ -1211,14 +1214,14 @@ pub mod tests { #[test] fn fork_destroy_works() { // when we reached finalized entry without iterations - let storage = DummyStorage::new().with_id(100, 100.into()); + let storage = DummyStorage::new().with_id(100, H256::from_low_u64_be(100)); let mut tx = DummyTransaction::new(); Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } .destroy(&storage, &mut tx, Some(200)).unwrap(); assert!(tx.removed_entries().is_empty()); // when we reach finalized entry with iterations let storage = DummyStorage::new() - .with_id(10, 10.into()) + .with_id(10, H256::from_low_u64_be(10)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(20)), value: Some(50) }) .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: Some(20) }) @@ -1232,7 +1235,7 @@ pub mod tests { vec![test_id(100).hash, test_id(50).hash, test_id(20).hash].into_iter().collect()); // when we reach beginning of fork before finalized block let storage = DummyStorage::new() - .with_id(10, 10.into()) + .with_id(10, H256::from_low_u64_be(10)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: Some(50) }); let mut tx = DummyTransaction::new(); @@ -1301,10 +1304,10 @@ pub mod tests { assert_eq!(chain::is_finalized_block::<_, u64, _>(&DummyStorage::new(), &test_id(1), 100).unwrap(), false); // when there's different hash for this block number in the database assert_eq!(chain::is_finalized_block::<_, u64, _>(&DummyStorage::new() - .with_id(1, From::from(2)), &test_id(1), 100).unwrap(), false); + .with_id(1, H256::from_low_u64_be(2)), &test_id(1), 100).unwrap(), false); // when there's the same hash for this block number in the database assert_eq!(chain::is_finalized_block::<_, u64, _>(&DummyStorage::new() - .with_id(1, From::from(1)), &test_id(1), 100).unwrap(), true); + .with_id(1, H256::from_low_u64_be(1)), &test_id(1), 100).unwrap(), true); } #[test] @@ -1354,9 +1357,9 @@ pub mod tests { #[test] fn ancient_entries_are_pruned() { let cache = ListCache::new(DummyStorage::new() - .with_id(10, 10.into()) - .with_id(20, 20.into()) - .with_id(30, 30.into()) + .with_id(10, H256::from_low_u64_be(10)) + .with_id(20, H256::from_low_u64_be(20)) + .with_id(30, H256::from_low_u64_be(30)) .with_entry(test_id(10), StorageEntry { prev_valid_from: None, value: Some(10) }) .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: Some(20) }) .with_entry(test_id(30), StorageEntry { prev_valid_from: Some(test_id(20)), value: Some(30) }), diff --git a/core/client/db/src/cache/list_entry.rs b/core/client/db/src/cache/list_entry.rs index 53d250bd068b81e39c0426e3a82e689d0aca50de..237ae9a268026744b87f6d85b7c6301cb82ee204 100644 --- a/core/client/db/src/cache/list_entry.rs +++ b/core/client/db/src/cache/list_entry.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,9 +18,10 @@ use client::error::Result as ClientResult; use runtime_primitives::traits::{Block as BlockT, NumberFor}; +use parity_codec::{Encode, Decode}; -use cache::{CacheItemT, ComplexBlockId}; -use cache::list_storage::{Storage}; +use crate::cache::{CacheItemT, ComplexBlockId}; +use crate::cache::list_storage::{Storage}; /// Single list-based cache entry. #[derive(Debug)] @@ -112,8 +113,8 @@ impl StorageEntry { #[cfg(test)] mod tests { - use cache::list_cache::tests::test_id; - use cache::list_storage::tests::{DummyStorage, FaultyStorage}; + use crate::cache::list_cache::tests::test_id; + use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage}; use super::*; #[test] diff --git a/core/client/db/src/cache/list_storage.rs b/core/client/db/src/cache/list_storage.rs index ec6883d26296b98a95485c4053841656dcfcfaed..659a30507e136576a844624fa167eb1cfb08ddb9 100644 --- a/core/client/db/src/cache/list_storage.rs +++ b/core/client/db/src/cache/list_storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,14 +21,14 @@ use std::sync::Arc; use kvdb::{KeyValueDB, DBTransaction}; use client::error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; -use codec::{Encode, Decode}; +use parity_codec::{Encode, Decode}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use utils::{self, db_err, meta_keys}; +use crate::utils::{self, db_err, meta_keys}; -use cache::{CacheItemT, ComplexBlockId}; -use cache::list_cache::{CommitOperation, Fork}; -use cache::list_entry::{Entry, StorageEntry}; +use crate::cache::{CacheItemT, ComplexBlockId}; +use crate::cache::list_cache::{CommitOperation, Fork}; +use crate::cache::list_entry::{Entry, StorageEntry}; /// Single list-cache metadata. #[derive(Debug)] diff --git a/core/client/db/src/cache/mod.rs b/core/client/db/src/cache/mod.rs index db2a1762db5754851c874bc1da05618b0799c98d..3d669e392d01c86fc4c6666aec40728c950862ef 100644 --- a/core/client/db/src/cache/mod.rs +++ b/core/client/db/src/cache/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,11 +23,10 @@ use kvdb::{KeyValueDB, DBTransaction}; use client::blockchain::Cache as BlockchainCache; use client::error::Result as ClientResult; -use codec::{Encode, Decode}; -use primitives::AuthorityId; +use parity_codec::{Encode, Decode}; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As}; -use utils::{self, COLUMN_META}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As, AuthorityIdFor}; +use crate::utils::{self, COLUMN_META}; use self::list_cache::ListCache; @@ -65,7 +64,7 @@ impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} /// Database-backed blockchain data cache. pub struct DbCache { - authorities_at: ListCache, self::list_storage::DbStorage>, + authorities_at: ListCache>, self::list_storage::DbStorage>, } impl DbCache { @@ -112,14 +111,14 @@ impl DbCache { /// Cache operations that are to be committed after database transaction is committed. pub struct DbCacheTransactionOps { - authorities_at_op: Option>>, + authorities_at_op: Option>>>, } /// Database-backed blockchain data cache transaction valid for single block import. pub struct DbCacheTransaction<'a, Block: BlockT> { cache: &'a mut DbCache, tx: &'a mut DBTransaction, - authorities_at_op: Option>>, + authorities_at_op: Option>>>, } impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { @@ -135,7 +134,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { mut self, parent: ComplexBlockId, block: ComplexBlockId, - authorities_at: Option>, + authorities_at: Option>>, is_final: bool, ) -> ClientResult { assert!(self.authorities_at_op.is_none()); @@ -179,7 +178,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { pub struct DbCacheSync(pub RwLock>); impl BlockchainCache for DbCacheSync { - fn authorities_at(&self, at: BlockId) -> Option> { + fn authorities_at(&self, at: BlockId) -> Option>> { let cache = self.0.read(); let storage = cache.authorities_at.storage(); let db = storage.db(); diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs index 72ee2c772e441054c61e4d94da67cc8eb8c0ced4..d276992f08cdf9b070842b80814e9b4d48fc33ca 100644 --- a/core/client/db/src/lib.rs +++ b/core/client/db/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,34 +24,10 @@ //! //! Finality implies canonicality but not vice-versa. -extern crate substrate_client as client; -extern crate kvdb_rocksdb; -extern crate kvdb; -extern crate hash_db; -extern crate parking_lot; -extern crate substrate_state_machine as state_machine; -extern crate substrate_primitives as primitives; -extern crate sr_primitives as runtime_primitives; -extern crate parity_codec as codec; -extern crate substrate_executor as executor; -extern crate substrate_state_db as state_db; -extern crate substrate_trie as trie; - -#[macro_use] -extern crate log; - -#[macro_use] -extern crate parity_codec_derive; - -#[cfg(test)] -extern crate substrate_test_client as test_client; - -#[cfg(test)] -extern crate kvdb_memorydb; - pub mod light; mod cache; +mod storage_cache; mod utils; use std::sync::Arc; @@ -59,26 +35,35 @@ use std::path::PathBuf; use std::io; use client::backend::NewBlockState; -use codec::{Decode, Encode}; +use client::blockchain::HeaderBackend; +use client::ExecutionStrategies; +use parity_codec::{Decode, Encode}; use hash_db::Hasher; use kvdb::{KeyValueDB, DBTransaction}; use trie::MemoryDB; use parking_lot::RwLock; -use primitives::{H256, AuthorityId, Blake2Hasher, ChangesTrieConfiguration, convert_hash}; +use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash}; use primitives::storage::well_known_keys; -use runtime_primitives::{generic::BlockId, Justification, StorageMap, ChildrenStorageMap}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, Digest, DigestItem}; +use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, Digest, DigestItem, AuthorityIdFor}; use runtime_primitives::BuildStorage; use state_machine::backend::Backend as StateBackend; use executor::RuntimeInfo; -use state_machine::{CodeExecutor, DBValue, ExecutionStrategy}; -use utils::{Meta, db_err, meta_keys, open_database, read_db, block_id_to_lookup_key, read_meta}; -use client::LeafSet; +use state_machine::{CodeExecutor, DBValue}; +use crate::utils::{Meta, db_err, meta_keys, open_database, read_db, block_id_to_lookup_key, read_meta}; +use client::leaves::{LeafSet, FinalizationDisplaced}; +use client::children; use state_db::StateDb; +use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; +use log::{trace, debug, warn}; pub use state_db::PruningMode; -const CANONICALIZATION_DELAY: u64 = 256; +#[cfg(feature = "test-helpers")] +use client::in_mem::Backend as InMemoryBackend; + +const CANONICALIZATION_DELAY: u64 = 4096; const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u64 = 32768; +const STATE_CACHE_SIZE_BYTES: usize = 16 * 1024 * 1024; /// DB-backed patricia trie state, transaction type is an overlay of changes to commit. pub type DbState = state_machine::TrieBackend>, Blake2Hasher>; @@ -98,8 +83,7 @@ pub fn new_client( settings: DatabaseSettings, executor: E, genesis_storage: S, - block_execution_strategy: ExecutionStrategy, - api_execution_strategy: ExecutionStrategy, + execution_strategies: ExecutionStrategies, ) -> Result, client::LocalCallExecutor, E>, Block, RA>, client::error::Error> where Block: BlockT, @@ -108,11 +92,11 @@ pub fn new_client( { let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); let executor = client::LocalCallExecutor::new(backend.clone(), executor); - Ok(client::Client::new(backend, executor, genesis_storage, block_execution_strategy, api_execution_strategy)?) + Ok(client::Client::new(backend, executor, genesis_storage, execution_strategies)?) } mod columns { - pub const META: Option = ::utils::COLUMN_META; + pub const META: Option = crate::utils::COLUMN_META; pub const STATE: Option = Some(1); pub const STATE_META: Option = Some(2); /// maps hashes to lookup keys and numbers to canon hashes. @@ -187,7 +171,7 @@ impl BlockchainDb { impl client::blockchain::HeaderBackend for BlockchainDb { fn header(&self, id: BlockId) -> Result, client::error::Error> { - ::utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) + utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) } fn info(&self) -> Result, client::error::Error> { @@ -266,15 +250,22 @@ impl client::blockchain::Backend for BlockchainDb { fn leaves(&self) -> Result, client::error::Error> { Ok(self.leaves.read().hashes()) } + + fn children(&self, parent_hash: Block::Hash) -> Result, client::error::Error> { + children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash) + } } /// Database transaction pub struct BlockImportOperation { - old_state: DbState, - updates: MemoryDB, + old_state: CachingState, + db_updates: MemoryDB, + storage_updates: Vec<(Vec, Option>)>, changes_trie_updates: MemoryDB, pending_block: Option>, aux_ops: Vec<(Vec, Option>)>, + finalized_blocks: Vec<(BlockId, Option)>, + set_head: Option>, } impl BlockImportOperation { @@ -292,7 +283,7 @@ impl client::backend::BlockImportOperation for BlockImportOperation where Block: BlockT, { - type State = DbState; + type State = CachingState; fn state(&self) -> Result, client::error::Error> { Ok(Some(&self.old_state)) @@ -315,17 +306,16 @@ where Block: BlockT, Ok(()) } - fn update_authorities(&mut self, _authorities: Vec) { + fn update_authorities(&mut self, _authorities: Vec>) { // currently authorities are not cached on full nodes } - fn update_storage(&mut self, update: MemoryDB) -> Result<(), client::error::Error> { - self.updates = update; + fn update_db_storage(&mut self, update: MemoryDB) -> Result<(), client::error::Error> { + self.db_updates = update; Ok(()) } - fn reset_storage(&mut self, mut top: StorageMap, children: ChildrenStorageMap) -> Result { - // TODO: wipe out existing trie. + fn reset_storage(&mut self, mut top: StorageOverlay, children: ChildrenStorageOverlay) -> Result { if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { return Err(client::error::ErrorKind::GenesisInvalid.into()); @@ -349,7 +339,7 @@ where Block: BlockT, let (root, update) = self.old_state.storage_root(top.into_iter().map(|(k, v)| (k, Some(v)))); transaction.consolidate(update); - self.updates = transaction; + self.db_updates = transaction; Ok(root) } @@ -358,10 +348,26 @@ where Block: BlockT, Ok(()) } - fn set_aux(&mut self, ops: I) -> Result<(), client::error::Error> + fn insert_aux(&mut self, ops: I) -> Result<(), client::error::Error> where I: IntoIterator, Option>)> { - self.aux_ops = ops.into_iter().collect(); + self.aux_ops.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage(&mut self, update: Vec<(Vec, Option>)>) -> Result<(), client::error::Error> { + self.storage_updates = update; + Ok(()) + } + + fn mark_finalized(&mut self, block: BlockId, justification: Option) -> Result<(), client::error::Error> { + self.finalized_blocks.push((block, justification)); + Ok(()) + } + + fn mark_head(&mut self, block: BlockId) -> Result<(), client::error::Error> { + assert!(self.set_head.is_none(), "Only one set head per operation is allowed"); + self.set_head = Some(block); Ok(()) } } @@ -392,7 +398,7 @@ struct DbGenesisStorage(pub H256); impl DbGenesisStorage { pub fn new() -> Self { let mut root = H256::default(); - let mut mdb = MemoryDB::::default(); // TODO: use new() to make it more correct + let mut mdb = MemoryDB::::default(); state_machine::TrieDBMut::::new(&mut mdb, &mut root); DbGenesisStorage(root) } @@ -446,10 +452,29 @@ impl DbChangesTrieStorage { } } +impl client::backend::PrunableStateChangesTrieStorage for DbChangesTrieStorage { + fn oldest_changes_trie_block( + &self, + config: &ChangesTrieConfiguration, + best_finalized_block: u64 + ) -> u64 { + match self.min_blocks_to_keep { + Some(min_blocks_to_keep) => state_machine::oldest_non_pruned_changes_trie( + config, + min_blocks_to_keep, + best_finalized_block, + ), + None => 1, + } + } +} + impl state_machine::ChangesTrieRootsStorage for DbChangesTrieStorage { fn root(&self, anchor: &state_machine::ChangesTrieAnchorBlockId, block: u64) -> Result, String> { - // check API requirement - assert!(block <= anchor.number, "API requirement"); + // check API requirement: we can't get NEXT block(s) based on anchor + if block > anchor.number { + return Err(format!("Can't get changes trie root at {} using anchor at {}", block, anchor.number)); + } // we need to get hash of the block to resolve changes trie root let block_id = if block <= self.meta.read().finalized_number.as_() { @@ -459,7 +484,7 @@ impl state_machine::ChangesTrieRootsStorage for DbC // the block is not finalized let mut current_num = anchor.number; let mut current_hash: Block::Hash = convert_hash(&anchor.hash); - let maybe_anchor_header: Block::Header = ::utils::require_header::( + let maybe_anchor_header: Block::Header = utils::require_header::( &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Number(As::sa(current_num)) ).map_err(|e| e.to_string())?; if maybe_anchor_header.hash() == current_hash { @@ -470,7 +495,7 @@ impl state_machine::ChangesTrieRootsStorage for DbC // => we should find the required block hash by traversing // back from the anchor to the block with given number while current_num != block { - let current_header: Block::Header = ::utils::require_header::( + let current_header: Block::Header = utils::require_header::( &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Hash(current_hash) ).map_err(|e| e.to_string())?; @@ -482,7 +507,7 @@ impl state_machine::ChangesTrieRootsStorage for DbC } }; - Ok(::utils::require_header::(&*self.db, columns::KEY_LOOKUP, columns::HEADER, block_id) + Ok(utils::require_header::(&*self.db, columns::KEY_LOOKUP, columns::HEADER, block_id) .map_err(|e| e.to_string())? .digest().log(DigestItem::as_changes_trie_root) .map(|root| H256::from_slice(root.as_ref()))) @@ -503,9 +528,10 @@ pub struct Backend { changes_tries_storage: DbChangesTrieStorage, blockchain: BlockchainDb, canonicalization_delay: u64, + shared_cache: SharedCache, } -impl Backend { +impl> Backend { /// Create a new instance of database backend. /// /// The pruning window is how old a block must be before the state is pruned. @@ -515,8 +541,8 @@ impl Backend { Backend::from_kvdb(db as Arc<_>, config.pruning, canonicalization_delay) } - #[cfg(test)] - fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { use utils::NUM_COLUMNS; let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); @@ -550,9 +576,166 @@ impl Backend { changes_tries_storage, blockchain, canonicalization_delay, + shared_cache: new_shared_cache(STATE_CACHE_SIZE_BYTES), }) } + /// Returns in-memory blockchain that contains the same set of blocks that the self. + #[cfg(feature = "test-helpers")] + pub fn as_in_memory(&self) -> InMemoryBackend { + use client::backend::{Backend as ClientBackend, BlockImportOperation}; + use client::blockchain::Backend as BlockchainBackend; + + let inmem = InMemoryBackend::::new(); + + // get all headers hashes && sort them by number (could be duplicate) + let mut headers: Vec<(NumberFor, Block::Hash, Block::Header)> = Vec::new(); + for (_, header) in self.blockchain.db.iter(columns::HEADER) { + let header = Block::Header::decode(&mut &header[..]).unwrap(); + let hash = header.hash(); + let number = *header.number(); + let pos = headers.binary_search_by(|item| item.0.cmp(&number)); + match pos { + Ok(pos) => headers.insert(pos, (number, hash, header)), + Err(pos) => headers.insert(pos, (number, hash, header)), + } + } + + // insert all other headers + bodies + justifications + let info = self.blockchain.info().unwrap(); + for (number, hash, header) in headers { + let id = BlockId::Hash(hash); + let justification = self.blockchain.justification(id).unwrap(); + let body = self.blockchain.body(id).unwrap(); + let state = self.state_at(id).unwrap().pairs(); + + let new_block_state = if number.is_zero() { + NewBlockState::Final + } else if hash == info.best_hash { + NewBlockState::Best + } else { + NewBlockState::Normal + }; + let mut op = inmem.begin_operation().unwrap(); + op.set_block_data(header, body, justification, new_block_state).unwrap(); + op.update_db_storage(state.into_iter().map(|(k, v)| (None, k, Some(v))).collect()).unwrap(); + inmem.commit_operation(op).unwrap(); + } + + // and now finalize the best block we have + inmem.finalize_block(BlockId::Hash(info.finalized_hash), None).unwrap(); + + inmem + } + + /// Handle setting head within a transaction. `route_to` should be the last + /// block that existed in the database. `best_to` should be the best block + /// to be set. + /// + /// In the case where the new best block is a block to be imported, `route_to` + /// should be the parent of `best_to`. In the case where we set an existing block + /// to be best, `route_to` should equal to `best_to`. + fn set_head_with_transaction(&self, transaction: &mut DBTransaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash)) -> Result<(Vec, Vec), client::error::Error> { + let mut enacted = Vec::default(); + let mut retracted = Vec::default(); + + let meta = self.blockchain.meta.read(); + + // cannot find tree route with empty DB. + if meta.best_hash != Default::default() { + let tree_route = ::client::blockchain::tree_route( + &self.blockchain, + BlockId::Hash(meta.best_hash), + BlockId::Hash(route_to), + )?; + + // uncanonicalize: check safety violations and ensure the numbers no longer + // point to these block hashes in the key mapping. + for r in tree_route.retracted() { + if r.hash == meta.finalized_hash { + warn!( + "Potential safety failure: reverting finalized block {:?}", + (&r.number, &r.hash) + ); + + return Err(::client::error::ErrorKind::NotInFinalizedChain.into()); + } + + retracted.push(r.hash.clone()); + utils::remove_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + r.number + ); + } + + // canonicalize: set the number lookup to map to this block's hash. + for e in tree_route.enacted() { + enacted.push(e.hash.clone()); + utils::insert_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + e.number, + e.hash + ); + } + } + + let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1); + transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); + utils::insert_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + best_to.0, + best_to.1, + ); + + Ok((enacted, retracted)) + } + + fn ensure_sequential_finalization( + &self, + header: &Block::Header, + last_finalized: Option, + ) -> Result<(), client::error::Error> { + let last_finalized = last_finalized.unwrap_or_else(|| self.blockchain.meta.read().finalized_hash); + if *header.parent_hash() != last_finalized { + return Err(::client::error::ErrorKind::NonSequentialFinalization( + format!("Last finalized {:?} not parent of {:?}", last_finalized, header.hash()), + ).into()); + } + Ok(()) + } + + fn finalize_block_with_transaction( + &self, + transaction: &mut DBTransaction, + hash: &Block::Hash, + header: &Block::Header, + last_finalized: Option, + justification: Option, + finalization_displaced: &mut Option>>, + ) -> Result<(Block::Hash, ::Number, bool, bool), client::error::Error> { + // TODO: ensure best chain contains this block. + let number = *header.number(); + self.ensure_sequential_finalization(header, last_finalized)?; + self.note_finalized( + transaction, + header, + *hash, + finalization_displaced, + )?; + + if let Some(justification) = justification { + transaction.put( + columns::JUSTIFICATION, + &utils::number_and_hash_to_lookup_key(number, hash), + &justification.encode(), + ); + } + Ok((*hash, number, false, true)) + } + // performs forced canonicaliziation with a delay after importning a non-finalized block. fn force_delayed_canonicalize( &self, @@ -566,7 +749,7 @@ impl Backend { if number_u64 > self.canonicalization_delay { let new_canonical = number_u64 - self.canonicalization_delay; - if new_canonical <= self.storage.state_db.best_canonical() { + if new_canonical <= self.storage.state_db.best_canonical().unwrap_or(0) { return Ok(()) } @@ -579,13 +762,183 @@ impl Backend { }; trace!(target: "db", "Canonicalize block #{} ({:?})", new_canonical, hash); - let commit = self.storage.state_db.canonicalize_block(&hash); + let commit = self.storage.state_db.canonicalize_block(&hash) + .map_err(|e: state_db::Error| client::error::Error::from(format!("State database error: {:?}", e)))?; apply_state_commit(transaction, commit); }; Ok(()) } + fn try_commit_operation(&self, mut operation: BlockImportOperation) + -> Result<(), client::error::Error> + { + let mut transaction = DBTransaction::new(); + let mut finalization_displaced_leaves = None; + + operation.apply_aux(&mut transaction); + + let mut meta_updates = Vec::new(); + let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; + + if !operation.finalized_blocks.is_empty() { + for (block, justification) in operation.finalized_blocks { + let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; + let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; + + meta_updates.push(self.finalize_block_with_transaction( + &mut transaction, + &block_hash, + &block_header, + Some(last_finalized_hash), + justification, + &mut finalization_displaced_leaves, + )?); + last_finalized_hash = block_hash; + } + } + + let imported = if let Some(pending_block) = operation.pending_block { + let hash = pending_block.header.hash(); + let parent_hash = *pending_block.header.parent_hash(); + let number = pending_block.header.number().clone(); + + // blocks are keyed by number + hash. + let lookup_key = utils::number_and_hash_to_lookup_key(number, hash); + + let (enacted, retracted) = if pending_block.leaf_state.is_best() { + self.set_head_with_transaction(&mut transaction, parent_hash, (number, hash))? + } else { + (Default::default(), Default::default()) + }; + + utils::insert_hash_to_key_mapping( + &mut transaction, + columns::KEY_LOOKUP, + number, + hash, + ); + + transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); + if let Some(body) = pending_block.body { + transaction.put(columns::BODY, &lookup_key, &body.encode()); + } + if let Some(justification) = pending_block.justification { + transaction.put(columns::JUSTIFICATION, &lookup_key, &justification.encode()); + } + + if number.is_zero() { + transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); + transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); + } + + let mut changeset: state_db::ChangeSet = state_db::ChangeSet::default(); + for (key, (val, rc)) in operation.db_updates.drain() { + if rc > 0 { + changeset.inserted.push((key, val.to_vec())); + } else if rc < 0 { + changeset.deleted.push(key); + } + } + let number_u64 = number.as_(); + let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset) + .map_err(|e: state_db::Error| client::error::Error::from(format!("State database error: {:?}", e)))?; + apply_state_commit(&mut transaction, commit); + + // Check if need to finalize. Genesis is always finalized instantly. + let finalized = number_u64 == 0 || pending_block.leaf_state.is_final(); + + let header = &pending_block.header; + let is_best = pending_block.leaf_state.is_best(); + let changes_trie_updates = operation.changes_trie_updates; + + self.changes_tries_storage.commit(&mut transaction, changes_trie_updates); + + if finalized { + // TODO: ensure best chain contains this block. + self.ensure_sequential_finalization(header, Some(last_finalized_hash))?; + self.note_finalized( + &mut transaction, + header, + hash, + &mut finalization_displaced_leaves, + )?; + } else { + // canonicalize blocks which are old enough, regardless of finality. + self.force_delayed_canonicalize(&mut transaction, hash, *header.number())? + } + + debug!(target: "db", "DB Commit {:?} ({}), best = {}", hash, number, is_best); + + let displaced_leaf = { + let mut leaves = self.blockchain.leaves.write(); + let displaced_leaf = leaves.import(hash, number, parent_hash); + leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX); + + displaced_leaf + }; + + let mut children = children::read_children(&*self.storage.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash)?; + children.push(hash); + children::write_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash, children); + + meta_updates.push((hash, number, pending_block.leaf_state.is_best(), finalized)); + + Some((number, hash, enacted, retracted, displaced_leaf, is_best)) + } else { + None + }; + + if let Some(set_head) = operation.set_head { + if let Some(header) = ::client::blockchain::HeaderBackend::header(&self.blockchain, set_head)? { + let number = header.number(); + let hash = header.hash(); + + self.set_head_with_transaction( + &mut transaction, + hash.clone(), + (number.clone(), hash.clone()) + )?; + } else { + return Err(client::error::ErrorKind::UnknownBlock(format!("Cannot set head {:?}", set_head)).into()) + } + } + + let write_result = self.storage.db.write(transaction).map_err(db_err); + + if let Some((number, hash, enacted, retracted, displaced_leaf, is_best)) = imported { + if let Err(e) = write_result { + let mut leaves = self.blockchain.leaves.write(); + let mut undo = leaves.undo(); + if let Some(displaced_leaf) = displaced_leaf { + undo.undo_import(displaced_leaf); + } + + if let Some(finalization_displaced) = finalization_displaced_leaves { + undo.undo_finalization(finalization_displaced); + } + + return Err(e) + } + + operation.old_state.sync_cache( + &enacted, + &retracted, + operation.storage_updates, + Some(hash), + Some(number), + || is_best, + ); + } + + for (hash, number, is_best, is_finalized) in meta_updates { + self.blockchain.update_meta(hash, number, is_best, is_finalized); + } + + Ok(()) + } + + // write stuff to a transaction after a new block is finalized. // this canonicalizes finalized blocks. Fails if called with a block which // was not a child of the last finalized block. @@ -594,25 +947,20 @@ impl Backend { transaction: &mut DBTransaction, f_header: &Block::Header, f_hash: Block::Hash, + displaced: &mut Option>> ) -> Result<(), client::error::Error> where Block: BlockT, { - let meta = self.blockchain.meta.read(); let f_num = f_header.number().clone(); - if f_num.as_() > self.storage.state_db.best_canonical() { + if self.storage.state_db.best_canonical().map(|c| f_num.as_() > c).unwrap_or(true) { let parent_hash = f_header.parent_hash().clone(); - if meta.finalized_hash != parent_hash { - return Err(::client::error::ErrorKind::NonSequentialFinalization( - format!("Last finalized {:?} not parent of {:?}", - meta.finalized_hash, f_hash), - ).into()) - } - let lookup_key = ::utils::number_and_hash_to_lookup_key(f_num, f_hash.clone()); + let lookup_key = utils::number_and_hash_to_lookup_key(f_num, f_hash.clone()); transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); - let commit = self.storage.state_db.canonicalize_block(&f_hash); + let commit = self.storage.state_db.canonicalize_block(&f_hash) + .map_err(|e: state_db::Error| client::error::Error::from(format!("State database error: {:?}", e)))?; apply_state_commit(transaction, commit); // read config from genesis, since it is readonly atm @@ -623,6 +971,12 @@ impl Backend { self.changes_tries_storage.prune(changes_trie_config, transaction, f_hash, f_num); } + let new_displaced = self.blockchain.leaves.write().finalize_height(f_num); + match displaced { + x @ &mut None => *x = Some(new_displaced), + &mut Some(ref mut displaced) => displaced.merge(new_displaced), + } + Ok(()) } } @@ -669,182 +1023,74 @@ impl client::backend::AuxStore for Backend where Block: BlockT client::backend::Backend for Backend where Block: BlockT { type BlockImportOperation = BlockImportOperation; type Blockchain = BlockchainDb; - type State = DbState; + type State = CachingState; type ChangesTrieStorage = DbChangesTrieStorage; - fn begin_operation(&self, block: BlockId) -> Result { - let state = self.state_at(block)?; + fn begin_operation(&self) -> Result { + let old_state = self.state_at(BlockId::Hash(Default::default()))?; Ok(BlockImportOperation { pending_block: None, - old_state: state, - updates: MemoryDB::default(), + old_state, + db_updates: MemoryDB::default(), + storage_updates: Default::default(), changes_trie_updates: MemoryDB::default(), aux_ops: Vec::new(), + finalized_blocks: Vec::new(), + set_head: None, }) } - fn commit_operation(&self, mut operation: Self::BlockImportOperation) + fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> Result<(), client::error::Error> { + operation.old_state = self.state_at(block)?; + Ok(()) + } + + fn commit_operation(&self, operation: Self::BlockImportOperation) -> Result<(), client::error::Error> { - let mut transaction = DBTransaction::new(); - operation.apply_aux(&mut transaction); - - if let Some(pending_block) = operation.pending_block { - let hash = pending_block.header.hash(); - let parent_hash = *pending_block.header.parent_hash(); - let number = pending_block.header.number().clone(); - - // blocks are keyed by number + hash. - let lookup_key = ::utils::number_and_hash_to_lookup_key(number, hash); - - if pending_block.leaf_state.is_best() { - let meta = self.blockchain.meta.read(); - - // cannot find tree route with empty DB. - if meta.best_hash != Default::default() { - let tree_route = ::client::blockchain::tree_route( - &self.blockchain, - BlockId::Hash(meta.best_hash), - BlockId::Hash(parent_hash), - )?; - - // uncanonicalize: check safety violations and ensure the numbers no longer - // point to these block hashes in the key mapping. - for retracted in tree_route.retracted() { - if retracted.hash == meta.finalized_hash { - warn!("Potential safety failure: reverting finalized block {:?}", - (&retracted.number, &retracted.hash)); - - return Err(::client::error::ErrorKind::NotInFinalizedChain.into()); - } - - ::utils::remove_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - retracted.number - ); - } - - // canonicalize: set the number lookup to map to this block's hash. - for enacted in tree_route.enacted() { - ::utils::insert_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - enacted.number, - enacted.hash - ); - } - } - - transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); - ::utils::insert_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - number, - hash, - ); - } - - ::utils::insert_hash_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - number, - hash, - ); - - transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); - if let Some(body) = pending_block.body { - transaction.put(columns::BODY, &lookup_key, &body.encode()); - } - if let Some(justification) = pending_block.justification { - transaction.put(columns::JUSTIFICATION, &lookup_key, &justification.encode()); - } - - if number.is_zero() { - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); - transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); - } - - let mut changeset: state_db::ChangeSet = state_db::ChangeSet::default(); - for (key, (val, rc)) in operation.updates.drain() { - if rc > 0 { - changeset.inserted.push((key, val.to_vec())); - } else if rc < 0 { - changeset.deleted.push(key); - } - } - let number_u64 = number.as_(); - let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset) - .map_err(|e: state_db::Error| client::error::Error::from(format!("State database error: {:?}", e)))?; - apply_state_commit(&mut transaction, commit); - self.changes_tries_storage.commit(&mut transaction, operation.changes_trie_updates); - - let finalized = match pending_block.leaf_state { - NewBlockState::Final => true, - _ => false, - }; - - if finalized { - // TODO: ensure best chain contains this block. - self.note_finalized(&mut transaction, &pending_block.header, hash)?; - } else { - // canonicalize blocks which are old enough, regardless of finality. - self.force_delayed_canonicalize(&mut transaction, hash, *pending_block.header.number())? - } - - debug!(target: "db", "DB Commit {:?} ({}), best = {}", hash, number, - pending_block.leaf_state.is_best()); - - { - let mut leaves = self.blockchain.leaves.write(); - let displaced_leaf = leaves.import(hash, number, parent_hash); - leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX); - - let write_result = self.storage.db.write(transaction).map_err(db_err); - if let Err(e) = write_result { - // revert leaves set update, if there was one. - if let Some(displaced_leaf) = displaced_leaf { - leaves.undo(displaced_leaf); - } - return Err(e); - } - drop(leaves); + match self.try_commit_operation(operation) { + Ok(_) => { + self.storage.state_db.apply_pending(); + Ok(()) + }, + e @ Err(_) => { + self.storage.state_db.revert_pending(); + e } - - self.blockchain.update_meta( - hash.clone(), - number.clone(), - pending_block.leaf_state.is_best(), - finalized, - ); } - Ok(()) } fn finalize_block(&self, block: BlockId, justification: Option) -> Result<(), client::error::Error> { - use runtime_primitives::traits::Header; - - if let Some(header) = ::client::blockchain::HeaderBackend::header(&self.blockchain, block)? { - let mut transaction = DBTransaction::new(); - // TODO: ensure best chain contains this block. - let hash = header.hash(); - self.note_finalized(&mut transaction, &header, hash.clone())?; - if let Some(justification) = justification { - let number = header.number().clone(); - transaction.put( - columns::JUSTIFICATION, - &::utils::number_and_hash_to_lookup_key(number, hash.clone()), - &justification.encode(), - ); - } + let mut transaction = DBTransaction::new(); + let hash = self.blockchain.expect_block_hash_from_id(&block)?; + let header = self.blockchain.expect_header(block)?; + let mut displaced = None; + let commit = |displaced| { + let (hash, number, is_best, is_finalized) = self.finalize_block_with_transaction( + &mut transaction, + &hash, + &header, + None, + justification, + displaced, + )?; self.storage.db.write(transaction).map_err(db_err)?; - self.blockchain.update_meta(hash, header.number().clone(), false, true); + self.blockchain.update_meta(hash, number, is_best, is_finalized); Ok(()) - } else { - Err(client::error::ErrorKind::UnknownBlock(format!("Cannot finalize block {:?}", block)).into()) + }; + match commit(&mut displaced) { + Ok(()) => self.storage.state_db.apply_pending(), + e @ Err(_) => { + self.storage.state_db.revert_pending(); + if let Some(displaced) = displaced { + self.blockchain.leaves.write().undo().undo_finalization(displaced); + } + return e; + } } + Ok(()) } fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { @@ -853,7 +1099,12 @@ impl client::backend::Backend for Backend whe fn revert(&self, n: NumberFor) -> Result, client::error::Error> { use client::blockchain::HeaderBackend; + let mut best = self.blockchain.info()?.best_number; + let finalized = self.blockchain.info()?.finalized_number; + let revertible = best - finalized; + let n = if revertible < n { revertible } else { n }; + for c in 0 .. n.as_() { if best == As::sa(0) { return Ok(As::sa(c)) @@ -862,18 +1113,21 @@ impl client::backend::Backend for Backend whe match self.storage.state_db.revert_one() { Some(commit) => { apply_state_commit(&mut transaction, commit); - let _removed = best.clone(); - best -= As::sa(1); - let header = self.blockchain.header(BlockId::Number(best))?.ok_or_else( + let removed = self.blockchain.header(BlockId::Number(best))?.ok_or_else( || client::error::ErrorKind::UnknownBlock( - format!("Error reverting to {}. Block header not found.", best)))?; + format!("Error reverting to {}. Block hash not found.", best)))?; - let lookup_key = ::utils::number_and_hash_to_lookup_key(header.number().clone(), header.hash().clone()); - transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); - transaction.delete(columns::KEY_LOOKUP, header.hash().as_ref()); + best -= As::sa(1); // prev block + let hash = self.blockchain.hash(best)?.ok_or_else( + || client::error::ErrorKind::UnknownBlock( + format!("Error reverting to {}. Block hash not found.", best)))?; + let key = utils::number_and_hash_to_lookup_key(best.clone(), &hash); + transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); + transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref()); + children::remove_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, hash); self.storage.db.write(transaction).map_err(db_err)?; - self.blockchain.update_meta(header.hash().clone(), best.clone(), true, false); - self.blockchain.leaves.write().revert(header.hash().clone(), header.number().clone(), header.parent_hash().clone()); + self.blockchain.update_meta(hash, best, true, false); + self.blockchain.leaves.write().revert(removed.hash().clone(), removed.number().clone(), removed.parent_hash().clone()); } None => return Ok(As::sa(c)) } @@ -893,20 +1147,35 @@ impl client::backend::Backend for Backend whe BlockId::Hash(h) if h == Default::default() => { let genesis_storage = DbGenesisStorage::new(); let root = genesis_storage.0.clone(); - return Ok(DbState::new(Arc::new(genesis_storage), root)); + let state = DbState::new(Arc::new(genesis_storage), root); + return Ok(CachingState::new(state, self.shared_cache.clone(), None)); }, _ => {} } match self.blockchain.header(block) { - Ok(Some(ref hdr)) if !self.storage.state_db.is_pruned(hdr.number().as_()) => { - let root = H256::from_slice(hdr.state_root().as_ref()); - Ok(DbState::new(self.storage.clone(), root)) + Ok(Some(ref hdr)) => { + let hash = hdr.hash(); + if !self.storage.state_db.is_pruned(&hash, hdr.number().as_()) { + let root = H256::from_slice(hdr.state_root().as_ref()); + let state = DbState::new(self.storage.clone(), root); + Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash))) + } else { + Err(client::error::ErrorKind::UnknownBlock(format!("State already discarded for {:?}", block)).into()) + } }, + Ok(None) => Err(client::error::ErrorKind::UnknownBlock(format!("Unknown state for block {:?}", block)).into()), Err(e) => Err(e), - _ => Err(client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into()), } } + + fn destroy_state(&self, mut state: Self::State) -> Result<(), client::error::Error> { + if let Some(hash) = state.parent_hash.clone() { + let is_best = || self.blockchain.meta.read().best_hash == hash; + state.sync_cache(&[], &[], vec![], None, None, is_best); + } + Ok(()) + } } impl client::backend::LocalBackend for Backend @@ -916,10 +1185,12 @@ where Block: BlockT {} mod tests { use hash_db::HashDB; use super::*; + use crate::columns; use client::backend::Backend as BTrait; + use client::blockchain::Backend as BLBTrait; use client::backend::BlockImportOperation as Op; - use client::blockchain::HeaderBackend as BlockchainHeaderBackend; use runtime_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; + use runtime_primitives::traits::{Hash, BlakeTwo256}; use state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage}; use test_client; @@ -927,7 +1198,7 @@ mod tests { fn prepare_changes(changes: Vec<(Vec, Vec)>) -> (H256, MemoryDB) { let mut changes_root = H256::default(); - let mut changes_trie_update = MemoryDB::::default(); // TODO: change to new() to make more correct + let mut changes_trie_update = MemoryDB::::default(); { let mut trie = TrieDBMut::::new( &mut changes_trie_update, @@ -960,7 +1231,7 @@ mod tests { let header = Header { number, parent_hash, - state_root: Default::default(), + state_root: BlakeTwo256::trie_root::<_, &[u8], &[u8]>(Vec::new()), digest, extrinsics_root, }; @@ -971,7 +1242,8 @@ mod tests { } else { BlockId::Number(number - 1) }; - let mut op = backend.begin_operation(block_id).unwrap(); + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, block_id).unwrap(); op.set_block_data(header, None, None, NewBlockState::Best).unwrap(); op.update_changes_trie(changes_trie_update).unwrap(); backend.commit_operation(op).unwrap(); @@ -993,7 +1265,8 @@ mod tests { BlockId::Number(i - 1) }; - let mut op = db.begin_operation(id).unwrap(); + let mut op = db.begin_operation().unwrap(); + db.begin_state_operation(&mut op, id).unwrap(); let header = Header { number: i, parent_hash: if i == 0 { @@ -1031,7 +1304,8 @@ mod tests { fn set_state_data() { let db = Backend::::new_test(2, 0); let hash = { - let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap(); + let mut op = db.begin_operation().unwrap(); + db.begin_state_operation(&mut op, BlockId::Hash(Default::default())).unwrap(); let mut header = Header { number: 0, parent_hash: Default::default(), @@ -1072,7 +1346,8 @@ mod tests { }; { - let mut op = db.begin_operation(BlockId::Number(0)).unwrap(); + let mut op = db.begin_operation().unwrap(); + db.begin_state_operation(&mut op, BlockId::Number(0)).unwrap(); let mut header = Header { number: 1, parent_hash: hash, @@ -1087,7 +1362,7 @@ mod tests { ]; let (root, overlay) = op.old_state.storage_root(storage.iter().cloned()); - op.update_storage(overlay).unwrap(); + op.update_db_storage(overlay).unwrap(); header.state_root = root.into(); op.set_block_data( @@ -1109,11 +1384,13 @@ mod tests { #[test] fn delete_only_when_negative_rc() { + let _ = ::env_logger::try_init(); let key; - let backend = Backend::::new_test(0, 0); + let backend = Backend::::new_test(1, 0); let hash = { - let mut op = backend.begin_operation(BlockId::Hash(Default::default())).unwrap(); + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Hash(Default::default())).unwrap(); let mut header = Header { number: 0, parent_hash: Default::default(), @@ -1133,7 +1410,7 @@ mod tests { op.reset_storage(storage.iter().cloned().collect(), Default::default()).unwrap(); - key = op.updates.insert(b"hello"); + key = op.db_updates.insert(b"hello"); op.set_block_data( header, Some(vec![]), @@ -1143,12 +1420,13 @@ mod tests { backend.commit_operation(op).unwrap(); - assert_eq!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().unwrap(), &b"hello"[..]); + assert_eq!(backend.storage.db.get(columns::STATE, key.as_bytes()).unwrap().unwrap(), &b"hello"[..]); hash }; let hash = { - let mut op = backend.begin_operation(BlockId::Number(0)).unwrap(); + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Number(0)).unwrap(); let mut header = Header { number: 1, parent_hash: hash, @@ -1166,8 +1444,8 @@ mod tests { ).0.into(); let hash = header.hash(); - op.updates.insert(b"hello"); - op.updates.remove(&key); + op.db_updates.insert(b"hello"); + op.db_updates.remove(&key); op.set_block_data( header, Some(vec![]), @@ -1177,12 +1455,13 @@ mod tests { backend.commit_operation(op).unwrap(); - assert_eq!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().unwrap(), &b"hello"[..]); + assert_eq!(backend.storage.db.get(columns::STATE, key.as_bytes()).unwrap().unwrap(), &b"hello"[..]); hash }; - { - let mut op = backend.begin_operation(BlockId::Number(1)).unwrap(); + let hash = { + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Number(1)).unwrap(); let mut header = Header { number: 2, parent_hash: hash, @@ -1198,8 +1477,9 @@ mod tests { .cloned() .map(|(x, y)| (x, Some(y))) ).0.into(); + let hash = header.hash(); - op.updates.remove(&key); + op.db_updates.remove(&key); op.set_block_data( header, Some(vec![]), @@ -1209,12 +1489,45 @@ mod tests { backend.commit_operation(op).unwrap(); - assert!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().is_none()); + assert!(backend.storage.db.get(columns::STATE, key.as_bytes()).unwrap().is_some()); + hash + }; + + { + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Number(2)).unwrap(); + let mut header = Header { + number: 3, + parent_hash: hash, + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }; + + let storage: Vec<(_, _)> = vec![]; + + header.state_root = op.old_state.storage_root(storage + .iter() + .cloned() + .map(|(x, y)| (x, Some(y))) + ).0.into(); + + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + backend.commit_operation(op).unwrap(); + + assert!(backend.storage.db.get(columns::STATE, key.as_bytes()).unwrap().is_none()); } backend.finalize_block(BlockId::Number(1), None).unwrap(); backend.finalize_block(BlockId::Number(2), None).unwrap(); - assert!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().is_none()); + backend.finalize_block(BlockId::Number(3), None).unwrap(); + assert!(backend.storage.db.get(columns::STATE, key.as_bytes()).unwrap().is_none()); } #[test] @@ -1225,7 +1538,10 @@ mod tests { let check_changes = |backend: &Backend, block: u64, changes: Vec<(Vec, Vec)>| { let (changes_root, mut changes_trie_update) = prepare_changes(changes); - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: Default::default(), number: block }; + let anchor = state_machine::ChangesTrieAnchorBlockId { + hash: backend.blockchain().header(BlockId::Number(block)).unwrap().unwrap().hash(), + number: block + }; assert_eq!(backend.changes_tries_storage.root(&anchor, block), Ok(Some(changes_root))); for (key, (val, _)) in changes_trie_update.drain() { @@ -1309,7 +1625,6 @@ mod tests { #[test] fn changes_tries_with_digest_are_pruned_on_finalization() { let mut backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.meta.write().finalized_number = 1000; backend.changes_tries_storage.min_blocks_to_keep = Some(8); let config = ChangesTrieConfiguration { digest_interval: 2, @@ -1329,10 +1644,12 @@ mod tests { let block9 = insert_header(&backend, 9, block8, vec![(b"key_at_9".to_vec(), b"val_at_9".to_vec())], Default::default()); let block10 = insert_header(&backend, 10, block9, vec![(b"key_at_10".to_vec(), b"val_at_10".to_vec())], Default::default()); let block11 = insert_header(&backend, 11, block10, vec![(b"key_at_11".to_vec(), b"val_at_11".to_vec())], Default::default()); - let _ = insert_header(&backend, 12, block11, vec![(b"key_at_12".to_vec(), b"val_at_12".to_vec())], Default::default()); + let block12 = insert_header(&backend, 12, block11, vec![(b"key_at_12".to_vec(), b"val_at_12".to_vec())], Default::default()); + let block13 = insert_header(&backend, 13, block12, vec![(b"key_at_13".to_vec(), b"val_at_13".to_vec())], Default::default()); + backend.changes_tries_storage.meta.write().finalized_number = 13; // check that roots of all tries are in the columns::CHANGES_TRIE - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: Default::default(), number: 100 }; + let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block13, number: 13 }; fn read_changes_trie_root(backend: &Backend, num: u64) -> H256 { backend.blockchain().header(BlockId::Number(num)).unwrap().unwrap().digest().logs().iter() .find(|i| i.as_changes_trie_root().is_some()).unwrap().as_changes_trie_root().unwrap().clone() @@ -1494,18 +1811,68 @@ mod tests { } } + #[test] + fn tree_route_child() { + let backend = Backend::::new_test(1000, 100); + + let block0 = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); + let block1 = insert_header(&backend, 1, block0, Vec::new(), Default::default()); + + { + let tree_route = ::client::blockchain::tree_route( + backend.blockchain(), + BlockId::Hash(block0), + BlockId::Hash(block1), + ).unwrap(); + + assert_eq!(tree_route.common_block().hash, block0); + assert!(tree_route.retracted().is_empty()); + assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![block1]); + } + } + #[test] fn test_leaves_with_complex_block_tree() { let backend: Arc> = Arc::new(Backend::new_test(20, 20)); test_client::trait_tests::test_leaves_for_backend(backend); } + #[test] + fn test_children_with_complex_block_tree() { + let backend: Arc> = Arc::new(Backend::new_test(20, 20)); + test_client::trait_tests::test_children_for_backend(backend); + } + #[test] fn test_blockchain_query_by_number_gets_canonical() { let backend: Arc> = Arc::new(Backend::new_test(20, 20)); test_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend); } + #[test] + fn test_leaves_pruned_on_finality() { + let backend: Backend = Backend::new_test(10, 10); + let block0 = insert_header(&backend, 0, Default::default(), Default::default(), Default::default()); + + let block1_a = insert_header(&backend, 1, block0, Default::default(), Default::default()); + let block1_b = insert_header(&backend, 1, block0, Default::default(), [1; 32].into()); + let block1_c = insert_header(&backend, 1, block0, Default::default(), [2; 32].into()); + + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block1_a, block1_b, block1_c]); + + let block2_a = insert_header(&backend, 2, block1_a, Default::default(), Default::default()); + let block2_b = insert_header(&backend, 2, block1_b, Default::default(), Default::default()); + let block2_c = insert_header(&backend, 2, block1_b, Default::default(), [1; 32].into()); + + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block2_a, block2_b, block2_c, block1_c]); + + backend.finalize_block(BlockId::hash(block1_a), None).unwrap(); + backend.finalize_block(BlockId::hash(block2_a), None).unwrap(); + + // leaves at same height stay. Leaves at lower heights pruned. + assert_eq!(backend.blockchain().leaves().unwrap(), vec![block2_a, block2_b, block2_c]); + } + #[test] fn test_aux() { let backend: Backend = Backend::new_test(0, 0); @@ -1520,34 +1887,48 @@ mod tests { fn test_finalize_block_with_justification() { use client::blockchain::{Backend as BlockChainBackend}; - let backend = Backend::::new_test(0, 0); - - { - let mut op = backend.begin_operation(BlockId::Hash(Default::default())).unwrap(); - let header = Header { - number: 0, - parent_hash: Default::default(), - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }; - - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); + let backend = Backend::::new_test(10, 10); - backend.commit_operation(op).unwrap(); - } + let block0 = insert_header(&backend, 0, Default::default(), Default::default(), Default::default()); + let _ = insert_header(&backend, 1, block0, Default::default(), Default::default()); let justification = Some(vec![1, 2, 3]); - backend.finalize_block(BlockId::Number(0), justification.clone()).unwrap(); + backend.finalize_block(BlockId::Number(1), justification.clone()).unwrap(); assert_eq!( - backend.blockchain().justification(BlockId::Number(0)).unwrap(), + backend.blockchain().justification(BlockId::Number(1)).unwrap(), justification, ); } + + #[test] + fn test_finalize_multiple_blocks_in_single_op() { + let backend = Backend::::new_test(10, 10); + + let block0 = insert_header(&backend, 0, Default::default(), Default::default(), Default::default()); + let block1 = insert_header(&backend, 1, block0, Default::default(), Default::default()); + let block2 = insert_header(&backend, 2, block1, Default::default(), Default::default()); + { + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Hash(block0)).unwrap(); + op.mark_finalized(BlockId::Hash(block1), None).unwrap(); + op.mark_finalized(BlockId::Hash(block2), None).unwrap(); + backend.commit_operation(op).unwrap(); + } + } + + #[test] + fn test_finalize_non_sequential() { + let backend = Backend::::new_test(10, 10); + + let block0 = insert_header(&backend, 0, Default::default(), Default::default(), Default::default()); + let block1 = insert_header(&backend, 1, block0, Default::default(), Default::default()); + let block2 = insert_header(&backend, 2, block1, Default::default(), Default::default()); + { + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, BlockId::Hash(block0)).unwrap(); + op.mark_finalized(BlockId::Hash(block2), None).unwrap(); + backend.commit_operation(op).unwrap_err(); + } + } } diff --git a/core/client/db/src/light.rs b/core/client/db/src/light.rs index 729519020c34e07ae5ef7a66cce5043f7933b8f7..d99ef503b2f81047d341140233b51d17160d0bdb 100644 --- a/core/client/db/src/light.rs +++ b/core/client/db/src/light.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,21 +24,23 @@ use kvdb::{KeyValueDB, DBTransaction}; use client::backend::{AuxStore, NewBlockState}; use client::blockchain::{BlockStatus, Cache as BlockchainCache, HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; -use client::{cht, LeafSet}; +use client::cht; +use client::leaves::{LeafSet, FinalizationDisplaced}; use client::error::{ErrorKind as ClientErrorKind, Result as ClientResult}; use client::light::blockchain::Storage as LightBlockchainStorage; -use codec::{Decode, Encode}; -use primitives::{AuthorityId, Blake2Hasher}; +use parity_codec::{Decode, Encode}; +use primitives::Blake2Hasher; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, - Zero, One, As, NumberFor, Digest, DigestItem}; -use cache::{DbCacheSync, DbCache, ComplexBlockId}; -use utils::{meta_keys, Meta, db_err, open_database, + Zero, One, As, NumberFor, Digest, DigestItem, AuthorityIdFor}; +use crate::cache::{DbCacheSync, DbCache, ComplexBlockId}; +use crate::utils::{self, meta_keys, Meta, db_err, open_database, read_db, block_id_to_lookup_key, read_meta}; -use DatabaseSettings; +use crate::DatabaseSettings; +use log::{trace, warn, debug}; pub(crate) mod columns { - pub const META: Option = ::utils::COLUMN_META; + pub const META: Option = crate::utils::COLUMN_META; pub const KEY_LOOKUP: Option = Some(1); pub const HEADER: Option = Some(2); pub const CACHE: Option = Some(3); @@ -71,8 +73,8 @@ impl LightStorage Self::from_kvdb(db as Arc<_>) } - #[cfg(test)] - pub(crate) fn new_test() -> Self { + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test() -> Self { use utils::NUM_COLUMNS; let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); @@ -135,7 +137,7 @@ impl BlockchainHeaderBackend for LightStorage Block: BlockT, { fn header(&self, id: BlockId) -> ClientResult> { - ::utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) + utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) } fn info(&self) -> ClientResult> { @@ -167,7 +169,7 @@ impl BlockchainHeaderBackend for LightStorage fn number(&self, hash: Block::Hash) -> ClientResult>> { if let Some(lookup_key) = block_id_to_lookup_key::(&*self.db, columns::KEY_LOOKUP, BlockId::Hash(hash))? { - let number = ::utils::lookup_key_to_number(&lookup_key)?; + let number = utils::lookup_key_to_number(&lookup_key)?; Ok(Some(number)) } else { Ok(None) @@ -188,12 +190,68 @@ impl LightStorage { .cloned())) } + /// Handle setting head within a transaction. `route_to` should be the last + /// block that existed in the database. `best_to` should be the best block + /// to be set. + /// + /// In the case where the new best block is a block to be imported, `route_to` + /// should be the parent of `best_to`. In the case where we set an existing block + /// to be best, `route_to` should equal to `best_to`. + fn set_head_with_transaction(&self, transaction: &mut DBTransaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash)) -> Result<(), client::error::Error> { + let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1); + + // handle reorg. + let meta = self.meta.read(); + if meta.best_hash != Default::default() { + let tree_route = ::client::blockchain::tree_route( + self, + BlockId::Hash(meta.best_hash), + BlockId::Hash(route_to), + )?; + + // update block number to hash lookup entries. + for retracted in tree_route.retracted() { + if retracted.hash == meta.finalized_hash { + // TODO: can we recover here? + warn!("Safety failure: reverting finalized block {:?}", + (&retracted.number, &retracted.hash)); + } + + utils::remove_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + retracted.number + ); + } + + for enacted in tree_route.enacted() { + utils::insert_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + enacted.number, + enacted.hash + ); + } + } + + transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); + utils::insert_number_to_key_mapping( + transaction, + columns::KEY_LOOKUP, + best_to.0, + best_to.1, + ); + + Ok(()) + } + // Note that a block is finalized. Only call with child of last finalized block. fn note_finalized( &self, transaction: &mut DBTransaction, header: &Block::Header, hash: Block::Hash, + displaced: &mut Option>>, ) -> ClientResult<()> { let meta = self.meta.read(); if &meta.finalized_hash != header.parent_hash() { @@ -203,7 +261,7 @@ impl LightStorage { ).into()) } - let lookup_key = ::utils::number_and_hash_to_lookup_key(header.number().clone(), hash); + let lookup_key = utils::number_and_hash_to_lookup_key(header.number().clone(), hash); transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); // build new CHT(s) if required @@ -243,7 +301,7 @@ impl LightStorage { if let Some(hash) = self.hash(prune_block)? { let lookup_key = block_id_to_lookup_key::(&*self.db, columns::KEY_LOOKUP, BlockId::Number(prune_block))? .expect("retrieved hash for `prune_block` right above. therefore retrieving lookup key must succeed. q.e.d."); - ::utils::remove_key_mappings( + utils::remove_key_mappings( transaction, columns::KEY_LOOKUP, prune_block, @@ -255,6 +313,12 @@ impl LightStorage { } } + let new_displaced = self.leaves.write().finalize_height(header.number().clone()); + match displaced { + x @ &mut None => *x = Some(new_displaced), + &mut Some(ref mut displaced) => displaced.merge(new_displaced), + } + Ok(()) } @@ -306,10 +370,11 @@ impl LightBlockchainStorage for LightStorage fn import_header( &self, header: Block::Header, - authorities: Option>, + authorities: Option>>, leaf_state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()> { + let mut finalization_displaced_leaves = None; let mut transaction = DBTransaction::new(); let hash = header.hash(); @@ -324,55 +389,13 @@ impl LightBlockchainStorage for LightStorage } // blocks are keyed by number + hash. - let lookup_key = ::utils::number_and_hash_to_lookup_key(number, hash); + let lookup_key = utils::number_and_hash_to_lookup_key(number, &hash); if leaf_state.is_best() { - // handle reorg. - { - let meta = self.meta.read(); - if meta.best_hash != Default::default() { - let tree_route = ::client::blockchain::tree_route( - self, - BlockId::Hash(meta.best_hash), - BlockId::Hash(parent_hash), - )?; - - // update block number to hash lookup entries. - for retracted in tree_route.retracted() { - if retracted.hash == meta.finalized_hash { - // TODO: can we recover here? - warn!("Safety failure: reverting finalized block {:?}", - (&retracted.number, &retracted.hash)); - } - - ::utils::remove_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - retracted.number - ); - } - - for enacted in tree_route.enacted() { - ::utils::insert_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - enacted.number, - enacted.hash - ); - } - } - } - - transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key); - ::utils::insert_number_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - number, - hash, - ); + self.set_head_with_transaction(&mut transaction, parent_hash, (number, hash))?; } - ::utils::insert_hash_to_key_mapping( + utils::insert_hash_to_key_mapping( &mut transaction, columns::KEY_LOOKUP, number, @@ -380,18 +403,24 @@ impl LightBlockchainStorage for LightStorage ); transaction.put(columns::HEADER, &lookup_key, &header.encode()); - if number.is_zero() { - transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &lookup_key); + let is_genesis = number.is_zero(); + if is_genesis { transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref()); } let finalized = match leaf_state { + _ if is_genesis => true, NewBlockState::Final => true, _ => false, }; if finalized { - self.note_finalized(&mut transaction, &header, hash)?; + self.note_finalized( + &mut transaction, + &header, + hash, + &mut finalization_displaced_leaves, + )?; } { @@ -411,10 +440,18 @@ impl LightBlockchainStorage for LightStorage debug!("Light DB Commit {:?} ({})", hash, number); let write_result = self.db.write(transaction).map_err(db_err); if let Err(e) = write_result { + let mut leaves = self.leaves.write(); + let mut undo = leaves.undo(); + // revert leaves set update if there was one. if let Some(displaced_leaf) = displaced_leaf { - leaves.undo(displaced_leaf); + undo.undo_import(displaced_leaf); + } + + if let Some(finalization_displaced) = finalization_displaced_leaves { + undo.undo_finalization(finalization_displaced); } + return Err(e); } @@ -426,6 +463,20 @@ impl LightBlockchainStorage for LightStorage Ok(()) } + fn set_head(&self, id: BlockId) -> ClientResult<()> { + if let Some(header) = self.header(id)? { + let hash = header.hash(); + let number = header.number(); + + let mut transaction = DBTransaction::new(); + self.set_head_with_transaction(&mut transaction, hash.clone(), (number.clone(), hash.clone()))?; + self.db.write(transaction).map_err(db_err)?; + Ok(()) + } else { + Err(ClientErrorKind::UnknownBlock(format!("Cannot set head {:?}", id)).into()) + } + } + fn header_cht_root(&self, cht_size: u64, block: NumberFor) -> ClientResult { self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block) } @@ -436,11 +487,11 @@ impl LightBlockchainStorage for LightStorage fn finalize_header(&self, id: BlockId) -> ClientResult<()> { if let Some(header) = self.header(id)? { + let mut displaced = None; let mut transaction = DBTransaction::new(); - // TODO: ensure best chain contains this block. let hash = header.hash(); let number = *header.number(); - self.note_finalized(&mut transaction, &header, hash.clone())?; + self.note_finalized(&mut transaction, &header, hash.clone(), &mut displaced)?; { let mut cache = self.cache.0.write(); let cache_ops = cache.transaction(&mut transaction) @@ -450,7 +501,12 @@ impl LightBlockchainStorage for LightStorage )? .into_ops(); - self.db.write(transaction).map_err(db_err)?; + if let Err(e) = self.db.write(transaction).map_err(db_err) { + if let Some(displaced) = displaced { + self.leaves.write().undo().undo_finalization(displaced); + } + return Err(e); + } cache.commit(cache_ops); } self.update_meta(hash, header.number().clone(), false, true); @@ -466,14 +522,14 @@ impl LightBlockchainStorage for LightStorage } fn cache(&self) -> Option<&BlockchainCache> { - None + Some(&self.cache) } } /// Build the key for inserting header-CHT at given block. fn cht_key>(cht_type: u8, block: N) -> [u8; 5] { let mut key = [cht_type; 5]; - key[1..].copy_from_slice(&::utils::number_index_key(block)); + key[1..].copy_from_slice(&utils::number_index_key(block)); key } @@ -485,6 +541,7 @@ pub(crate) mod tests { use super::*; type Block = RawBlock>; + type AuthorityId = AuthorityIdFor; pub fn default_header(parent: &Hash, number: u64) -> Header { Header { @@ -510,7 +567,7 @@ pub(crate) mod tests { pub fn insert_block Header>( db: &LightStorage, - authorities: Option>, + authorities: Option>>, header: F, ) -> Hash { let header = header(); @@ -521,7 +578,7 @@ pub(crate) mod tests { fn insert_final_block Header>( db: &LightStorage, - authorities: Option>, + authorities: Option>>, header: F, ) -> Hash { let header = header(); @@ -532,7 +589,7 @@ pub(crate) mod tests { fn insert_non_best_block Header>( db: &LightStorage, - authorities: Option>, + authorities: Option>>, header: F, ) -> Hash { let header = header(); @@ -553,7 +610,7 @@ pub(crate) mod tests { #[test] fn does_not_return_unknown_header() { let db = LightStorage::::new_test(); - assert!(db.header(BlockId::Hash(1.into())).unwrap().is_none()); + assert!(db.header(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap().is_none()); assert!(db.header(BlockId::Number(0)).unwrap().is_none()); } @@ -578,7 +635,7 @@ pub(crate) mod tests { let genesis_hash = insert_block(&db, None, || default_header(&Default::default(), 0)); assert_eq!(db.status(BlockId::Hash(genesis_hash)).unwrap(), BlockStatus::InChain); assert_eq!(db.status(BlockId::Number(0)).unwrap(), BlockStatus::InChain); - assert_eq!(db.status(BlockId::Hash(1.into())).unwrap(), BlockStatus::Unknown); + assert_eq!(db.status(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap(), BlockStatus::Unknown); assert_eq!(db.status(BlockId::Number(1)).unwrap(), BlockStatus::Unknown); } @@ -762,7 +819,7 @@ pub(crate) mod tests { fn authorites_are_cached() { let db = LightStorage::new_test(); - fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>)]) { + fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>>)]) { for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { let actual = db.cache().authorities_at(BlockId::Number(*at)); assert_eq!(*expected, actual); @@ -775,10 +832,10 @@ pub(crate) mod tests { let checks = vec![ (0, None), (1, None), - (2, Some(vec![[1u8; 32].into()])), - (3, Some(vec![[1u8; 32].into()])), - (4, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), - (5, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), + (2, Some(vec![AuthorityId::from_raw([1u8; 32])])), + (3, Some(vec![AuthorityId::from_raw([1u8; 32])])), + (4, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])])), + (5, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])])), (6, None), (7, None), // block will work for 'future' block too ]; @@ -787,13 +844,13 @@ pub(crate) mod tests { run_checks(&db, 0, &checks); let hash1 = insert_final_block(&db, None, || default_header(&hash0, 1)); run_checks(&db, 1, &checks); - let hash2 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash1, 2)); + let hash2 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash1, 2)); run_checks(&db, 2, &checks); - let hash3 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); + let hash3 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash2, 3)); run_checks(&db, 3, &checks); - let hash4 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash3, 4)); + let hash4 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash3, 4)); run_checks(&db, 4, &checks); - let hash5 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash4, 5)); + let hash5 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash4, 5)); run_checks(&db, 5, &checks); let hash6 = insert_final_block(&db, None, || default_header(&hash5, 6)); run_checks(&db, 7, &checks); @@ -805,9 +862,9 @@ pub(crate) mod tests { // some older non-best blocks are inserted // ... -> B2(1) -> B2_1(1) -> B2_2(2) // => the cache ignores all writes before best finalized block - let hash2_1 = insert_non_best_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); + let hash2_1 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash2, 3)); assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_1))); - let hash2_2 = insert_non_best_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash2_1, 4)); + let hash2_2 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash2_1, 4)); assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_2))); } @@ -818,39 +875,39 @@ pub(crate) mod tests { // \> B6_1_1(5) // \> B6_1_2(6) -> B6_1_3(7) - let hash7 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash6, 7)); + let hash7 = insert_block(&db, Some(vec![AuthorityId::from_raw([3u8; 32])]), || default_header(&hash6, 7)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - let hash8 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash7, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + let hash8 = insert_block(&db, Some(vec![AuthorityId::from_raw([3u8; 32])]), || default_header(&hash7, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - let hash6_1 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6, 7)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + let hash6_1 = insert_block(&db, Some(vec![AuthorityId::from_raw([4u8; 32])]), || default_header(&hash6, 7)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - let hash6_1_1 = insert_non_best_block(&db, Some(vec![[5u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + let hash6_1_1 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([5u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - let hash6_1_2 = insert_non_best_block(&db, Some(vec![[6u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + let hash6_1_2 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([6u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - let hash6_2 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + let hash6_2 = insert_block(&db, Some(vec![AuthorityId::from_raw([4u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) }; @@ -861,19 +918,19 @@ pub(crate) mod tests { assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); // finalize block hash6_2 db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); } } @@ -913,4 +970,28 @@ pub(crate) mod tests { assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); assert_eq!(db.get_aux(&[3]).unwrap(), Some(vec![103])); } + + #[test] + fn test_leaves_pruned_on_finality() { + let db = LightStorage::::new_test(); + let block0 = insert_block(&db, None, || default_header(&Default::default(), 0)); + + let block1_a = insert_block(&db, None, || default_header(&block0, 1)); + let block1_b = insert_block(&db, None, || header_with_extrinsics_root(&block0, 1, [1; 32].into())); + let block1_c = insert_block(&db, None, || header_with_extrinsics_root(&block0, 1, [2; 32].into())); + + assert_eq!(db.leaves.read().hashes(), vec![block1_a, block1_b, block1_c]); + + let block2_a = insert_block(&db, None, || default_header(&block1_a, 2)); + let block2_b = insert_block(&db, None, || header_with_extrinsics_root(&block1_b, 2, [1; 32].into())); + let block2_c = insert_block(&db, None, || header_with_extrinsics_root(&block1_b, 2, [2; 32].into())); + + assert_eq!(db.leaves.read().hashes(), vec![block2_a, block2_b, block2_c, block1_c]); + + db.finalize_header(BlockId::hash(block1_a)).unwrap(); + db.finalize_header(BlockId::hash(block2_a)).unwrap(); + + // leaves at same height stay. Leaves at lower heights pruned. + assert_eq!(db.leaves.read().hashes(), vec![block2_a, block2_b, block2_c]); + } } diff --git a/core/client/db/src/storage_cache.rs b/core/client/db/src/storage_cache.rs new file mode 100644 index 0000000000000000000000000000000000000000..6cfdbdd09b53db4ea986965550d076831cd07eae --- /dev/null +++ b/core/client/db/src/storage_cache.rs @@ -0,0 +1,421 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Global cache state. + +use std::collections::{VecDeque, HashSet, HashMap}; +use std::sync::Arc; +use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; +use lru_cache::LruCache; +use hash_db::Hasher; +use runtime_primitives::traits::{Block, Header}; +use state_machine::{backend::Backend as StateBackend, TrieBackend}; +use log::trace; + +const STATE_CACHE_BLOCKS: usize = 12; + +type StorageKey = Vec; +type StorageValue = Vec; + +/// Shared canonical state cache. +pub struct Cache { + /// Storage cache. `None` indicates that key is known to be missing. + storage: LruCache>, + /// Storage hashes cache. `None` indicates that key is known to be missing. + hashes: LruCache>, + /// Information on the modifications in recently committed blocks; specifically which keys + /// changed in which block. Ordered by block number. + modifications: VecDeque>, +} + +pub type SharedCache = Arc>>; + +/// Create new shared cache instance with given max memory usage. +pub fn new_shared_cache(shared_cache_size: usize) -> SharedCache { + let cache_items = shared_cache_size / 100; // Guestimate, potentially inaccurate + Arc::new(Mutex::new(Cache { + storage: LruCache::new(cache_items), + hashes: LruCache::new(cache_items), + modifications: VecDeque::new(), + })) +} + +#[derive(Debug)] +/// Accumulates a list of storage changed in a block. +struct BlockChanges { + /// Block number. + number: B::Number, + /// Block hash. + hash: B::Hash, + /// Parent block hash. + parent: B::Hash, + /// A set of modified storage keys. + storage: HashSet, + /// Block is part of the canonical chain. + is_canon: bool, +} + +/// Cached values specific to a state. +struct LocalCache { + /// Storage cache. `None` indicates that key is known to be missing. + storage: HashMap>, + /// Storage hashes cache. `None` indicates that key is known to be missing. + hashes: HashMap>, +} + +/// State abstraction. +/// Manages shared global state cache which reflects the canonical +/// state as it is on the disk. +/// A instance of `CachingState` may be created as canonical or not. +/// For canonical instances local cache is accumulated and applied +/// in `sync_cache` along with the change overlay. +/// For non-canonical clones local cache and changes are dropped. +pub struct CachingState, B: Block> { + /// Backing state. + state: S, + /// Shared canonical state cache. + shared_cache: SharedCache, + /// Local cache of values for this state. + local_cache: RwLock>, + /// Hash of the block on top of which this instance was created or + /// `None` if cache is disabled + pub parent_hash: Option, +} + +impl, B: Block> CachingState { + /// Create a new instance wrapping generic State and shared cache. + pub fn new(state: S, shared_cache: SharedCache, parent_hash: Option) -> CachingState { + CachingState { + state, + shared_cache, + local_cache: RwLock::new(LocalCache { + storage: Default::default(), + hashes: Default::default(), + }), + parent_hash: parent_hash, + } + } + + /// Propagate local cache into the shared cache and synchronize + /// the shared cache with the best block state. + /// This function updates the shared cache by removing entries + /// that are invalidated by chain reorganization. `sync_cache` + /// should be called after the block has been committed and the + /// blockchain route has been calculated. + pub fn sync_cache bool> ( + &mut self, + enacted: &[B::Hash], + retracted: &[B::Hash], + changes: Vec<(StorageKey, Option)>, + commit_hash: Option, + commit_number: Option<::Number>, + is_best: F, + ) { + let mut cache = self.shared_cache.lock(); + let is_best = is_best(); + trace!("Syncing cache, id = (#{:?}, {:?}), parent={:?}, best={}", commit_number, commit_hash, self.parent_hash, is_best); + let cache = &mut *cache; + + // Purge changes from re-enacted and retracted blocks. + // Filter out commiting block if any. + let mut clear = false; + for block in enacted.iter().filter(|h| commit_hash.as_ref().map_or(true, |p| *h != p)) { + clear = clear || { + if let Some(ref mut m) = cache.modifications.iter_mut().find(|m| &m.hash == block) { + trace!("Reverting enacted block {:?}", block); + m.is_canon = true; + for a in &m.storage { + trace!("Reverting enacted key {:?}", a); + cache.storage.remove(a); + } + false + } else { + true + } + }; + } + + for block in retracted { + clear = clear || { + if let Some(ref mut m) = cache.modifications.iter_mut().find(|m| &m.hash == block) { + trace!("Retracting block {:?}", block); + m.is_canon = false; + for a in &m.storage { + trace!("Retracted key {:?}", a); + cache.storage.remove(a); + } + false + } else { + true + } + }; + } + if clear { + // We don't know anything about the block; clear everything + trace!("Wiping cache"); + cache.storage.clear(); + cache.modifications.clear(); + } + + // Propagate cache only if committing on top of the latest canonical state + // blocks are ordered by number and only one block with a given number is marked as canonical + // (contributed to canonical state cache) + if let Some(_) = self.parent_hash { + let mut local_cache = self.local_cache.write(); + if is_best { + trace!("Committing {} local, {} hashes, {} modified entries", local_cache.storage.len(), local_cache.hashes.len(), changes.len()); + for (k, v) in local_cache.storage.drain() { + cache.storage.insert(k, v); + } + for (k, v) in local_cache.hashes.drain() { + cache.hashes.insert(k, v); + } + } + } + + if let ( + Some(ref number), Some(ref hash), Some(ref parent)) + = (commit_number, commit_hash, self.parent_hash) + { + if cache.modifications.len() == STATE_CACHE_BLOCKS { + cache.modifications.pop_back(); + } + let mut modifications = HashSet::new(); + for (k, v) in changes.into_iter() { + modifications.insert(k.clone()); + if is_best { + cache.hashes.remove(&k); + cache.storage.insert(k, v); + } + } + // Save modified storage. These are ordered by the block number. + let block_changes = BlockChanges { + storage: modifications, + number: *number, + hash: hash.clone(), + is_canon: is_best, + parent: parent.clone(), + }; + let insert_at = cache.modifications.iter() + .enumerate() + .find(|&(_, m)| m.number < *number) + .map(|(i, _)| i); + trace!("Inserting modifications at {:?}", insert_at); + if let Some(insert_at) = insert_at { + cache.modifications.insert(insert_at, block_changes); + } else { + cache.modifications.push_back(block_changes); + } + } + } + + /// Check if the key can be returned from cache by matching current block parent hash against canonical + /// state and filtering out entries modified in later blocks. + fn is_allowed( + key: &[u8], + parent_hash: &Option, + modifications: + &VecDeque> + ) -> bool + { + let mut parent = match *parent_hash { + None => { + trace!("Cache lookup skipped for {:?}: no parent hash", key); + return false; + } + Some(ref parent) => parent, + }; + if modifications.is_empty() { + trace!("Cache lookup allowed for {:?}", key); + return true; + } + // Ignore all storage modified in later blocks + // Modifications contains block ordered by the number + // We search for our parent in that list first and then for + // all its parent until we hit the canonical block, + // checking against all the intermediate modifications. + for m in modifications { + if &m.hash == parent { + if m.is_canon { + return true; + } + parent = &m.parent; + } + if m.storage.contains(key) { + trace!("Cache lookup skipped for {:?}: modified in a later block", key); + return false; + } + } + trace!("Cache lookup skipped for {:?}: parent hash is unknown", key); + false + } +} + +impl, B:Block> StateBackend for CachingState { + type Error = S::Error; + type Transaction = S::Transaction; + type TrieBackendStorage = S::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + let local_cache = self.local_cache.upgradable_read(); + if let Some(entry) = local_cache.storage.get(key).cloned() { + trace!("Found in local cache: {:?}", key); + return Ok(entry) + } + let mut cache = self.shared_cache.lock(); + if Self::is_allowed(key, &self.parent_hash, &cache.modifications) { + if let Some(entry) = cache.storage.get_mut(key).map(|a| a.clone()) { + trace!("Found in shared cache: {:?}", key); + return Ok(entry) + } + } + trace!("Cache miss: {:?}", key); + let value = self.state.storage(key)?; + RwLockUpgradableReadGuard::upgrade(local_cache).storage.insert(key.to_vec(), value.clone()); + Ok(value) + } + + fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + let local_cache = self.local_cache.upgradable_read(); + if let Some(entry) = local_cache.hashes.get(key).cloned() { + trace!("Found hash in local cache: {:?}", key); + return Ok(entry) + } + let mut cache = self.shared_cache.lock(); + if Self::is_allowed(key, &self.parent_hash, &cache.modifications) { + if let Some(entry) = cache.hashes.get_mut(key).map(|a| a.clone()) { + trace!("Found hash in shared cache: {:?}", key); + return Ok(entry) + } + } + trace!("Cache hash miss: {:?}", key); + let hash = self.state.storage_hash(key)?; + RwLockUpgradableReadGuard::upgrade(local_cache).hashes.insert(key.to_vec(), hash.clone()); + Ok(hash) + } + + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { + self.state.child_storage(storage_key, key) + } + + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.storage(key)?.is_some()) + } + + fn exists_child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result { + self.state.exists_child_storage(storage_key, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_keys_with_prefix(prefix, f) + } + + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { + self.state.for_keys_in_child_storage(storage_key, f) + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord + { + self.state.storage_root(delta) + } + + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord + { + self.state.child_storage_root(storage_key, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.state.pairs() + } + + fn keys(&self, prefix: &Vec) -> Vec> { + self.state.keys(prefix) + } + + fn try_into_trie_backend(self) -> Option> { + self.state.try_into_trie_backend() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; + use state_machine::backend::InMemory; + use primitives::Blake2Hasher; + + type Block = RawBlock>; + #[test] + fn smoke() { + //init_log(); + let root_parent = H256::random(); + let key = H256::random()[..].to_vec(); + let h0 = H256::random(); + let h1a = H256::random(); + let h1b = H256::random(); + let h2a = H256::random(); + let h2b = H256::random(); + let h3a = H256::random(); + let h3b = H256::random(); + + let shared = new_shared_cache::(256*1024); + + // blocks [ 3a(c) 2a(c) 2b 1b 1a(c) 0 ] + // state [ 5 5 4 3 2 2 ] + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(root_parent.clone())); + s.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], Some(h0.clone()), Some(0), || true); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h0.clone())); + s.sync_cache(&[], &[], vec![], Some(h1a.clone()), Some(1), || true); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h0.clone())); + s.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], Some(h1b.clone()), Some(1), || false); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1b.clone())); + s.sync_cache(&[], &[], vec![(key.clone(), Some(vec![4]))], Some(h2b.clone()), Some(2), || false); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1a.clone())); + s.sync_cache(&[], &[], vec![(key.clone(), Some(vec![5]))], Some(h2a.clone()), Some(2), || true); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h2a.clone())); + s.sync_cache(&[], &[], vec![], Some(h3a.clone()), Some(3), || true); + + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h3a.clone())); + assert_eq!(s.storage(&key).unwrap().unwrap(), vec![5]); + + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1a.clone())); + assert!(s.storage(&key).unwrap().is_none()); + + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h2b.clone())); + assert!(s.storage(&key).unwrap().is_none()); + + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1b.clone())); + assert!(s.storage(&key).unwrap().is_none()); + + // reorg to 3b + // blocks [ 3b(c) 3a 2a 2b(c) 1b 1a 0 ] + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h2b.clone())); + s.sync_cache(&[h1b.clone(), h2b.clone(), h3b.clone()], &[h1a.clone(), h2a.clone(), h3a.clone()], vec![], Some(h3b.clone()), Some(3), || true); + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h3a.clone())); + assert!(s.storage(&key).unwrap().is_none()); + } +} diff --git a/core/client/db/src/utils.rs b/core/client/db/src/utils.rs index 416bf239b280faa794b1d8e51cd7a1a7b1c8d2f0..ce843a93a2fa4531761d1f94925bb14a23d9f72a 100644 --- a/core/client/db/src/utils.rs +++ b/core/client/db/src/utils.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,13 +22,14 @@ use std::io; use kvdb::{KeyValueDB, DBTransaction}; use kvdb_rocksdb::{Database, DatabaseConfig}; +use log::debug; use client; -use codec::Decode; +use parity_codec::Decode; use trie::DBValue; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, Zero}; -use DatabaseSettings; +use crate::DatabaseSettings; /// Number of columns in the db. Must be the same for both full && light dbs. /// Otherwise RocksDb will fail to open database && check its type. @@ -50,6 +51,8 @@ pub mod meta_keys { pub const GENESIS_HASH: &[u8; 3] = b"gen"; /// Leaves prefix list key. pub const LEAF_PREFIX: &[u8; 4] = b"leaf"; + /// Children prefix list key. + pub const CHILDREN_PREFIX: &[u8; 8] = b"children"; } /// Database metadata. diff --git a/core/client/src/backend.rs b/core/client/src/backend.rs index 290159bdc5be8d4f63c390e4e18a3bacb49b8904..a0975db888d7531eada2cde5452a9be5f6e9d2a1 100644 --- a/core/client/src/backend.rs +++ b/core/client/src/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,10 +16,10 @@ //! Substrate Client data backend -use error; -use primitives::AuthorityId; -use runtime_primitives::{generic::BlockId, Justification, StorageMap, ChildrenStorageMap}; -use runtime_primitives::traits::{Block as BlockT, NumberFor}; +use crate::error; +use primitives::ChangesTrieConfiguration; +use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; +use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, NumberFor}; use state_machine::backend::Backend as StateBackend; use state_machine::ChangesTrieStorage as StateChangesTrieStorage; use hash_db::Hasher; @@ -44,6 +44,14 @@ impl NewBlockState { NewBlockState::Normal => false, } } + + /// Whether this block is considered final. + pub fn is_final(self) -> bool { + match self { + NewBlockState::Final => true, + NewBlockState::Best | NewBlockState::Normal => false, + } + } } /// Block insertion operation. Keeps hold if the inserted block state and data. @@ -67,16 +75,22 @@ pub trait BlockImportOperation where /// Append authorities set to the transaction. This is a set of parent block (set which /// has been used to check justification of this block). - fn update_authorities(&mut self, authorities: Vec); + fn update_authorities(&mut self, authorities: Vec>); /// Inject storage data into the database. - fn update_storage(&mut self, update: >::Transaction) -> error::Result<()>; + fn update_db_storage(&mut self, update: >::Transaction) -> error::Result<()>; /// Inject storage data into the database replacing any existing data. - fn reset_storage(&mut self, top: StorageMap, children: ChildrenStorageMap) -> error::Result; + fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result; + /// Set top level storage changes. + fn update_storage(&mut self, update: Vec<(Vec, Option>)>) -> error::Result<()>; /// Inject changes trie data into the database. fn update_changes_trie(&mut self, update: MemoryDB) -> error::Result<()>; - /// Update auxiliary keys. Values are `None` if should be deleted. - fn set_aux(&mut self, ops: I) -> error::Result<()> + /// Insert auxiliary keys. Values are `None` if should be deleted. + fn insert_aux(&mut self, ops: I) -> error::Result<()> where I: IntoIterator, Option>)>; + /// Mark a block as finalized. + fn mark_finalized(&mut self, id: BlockId, justification: Option) -> error::Result<()>; + /// Mark a block as new head. If both block import and set head are specified, set head overrides block import's best block rule. + fn mark_head(&mut self, id: BlockId) -> error::Result<()>; } /// Provides access to an auxiliary database. @@ -106,17 +120,19 @@ pub trait Backend: AuxStore + Send + Sync where H: Hasher, { /// Associated block insertion operation type. - type BlockImportOperation: BlockImportOperation; + type BlockImportOperation: BlockImportOperation; /// Associated blockchain backend type. - type Blockchain: ::blockchain::Backend; + type Blockchain: crate::blockchain::Backend; /// Associated state backend type. type State: StateBackend; /// Changes trie storage. - type ChangesTrieStorage: StateChangesTrieStorage; + type ChangesTrieStorage: PrunableStateChangesTrieStorage; /// Begin a new block insertion transaction with given parent block id. /// When constructing the genesis, this is called with all-zero hash. - fn begin_operation(&self, block: BlockId) -> error::Result; + fn begin_operation(&self) -> error::Result; + /// Note an operation to contain state transition. + fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> error::Result<()>; /// Commit block insertion. fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>; /// Finalize block with given Id. This should only be called if the parent of the given @@ -128,6 +144,10 @@ pub trait Backend: AuxStore + Send + Sync where fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage>; /// Returns state backend with post-state of given block. fn state_at(&self, block: BlockId) -> error::Result; + /// Destroy state and save any useful data, such as cache. + fn destroy_state(&self, _state: Self::State) -> error::Result<()> { + Ok(()) + } /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were /// successfully reverted. fn revert(&self, n: NumberFor) -> error::Result>; @@ -149,6 +169,12 @@ pub trait Backend: AuxStore + Send + Sync where } } +/// Changes trie storage that supports pruning. +pub trait PrunableStateChangesTrieStorage: StateChangesTrieStorage { + /// Get number block of oldest, non-pruned changes trie. + fn oldest_changes_trie_block(&self, config: &ChangesTrieConfiguration, best_finalized: u64) -> u64; +} + /// Mark for all Backend implementations, that are making use of state data, stored locally. pub trait LocalBackend: Backend where @@ -161,4 +187,7 @@ pub trait RemoteBackend: Backend where Block: BlockT, H: Hasher, -{} +{ + /// Returns true if the state for given block is available locally. + fn is_local_state_available(&self, block: &BlockId) -> bool; +} diff --git a/core/client/src/block_builder/api.rs b/core/client/src/block_builder/api.rs index d122909eaf2f4271103847f1c65a51543e76b2b8..731f4c86328b637298e53f99d11855bf39137462 100644 --- a/core/client/src/block_builder/api.rs +++ b/core/client/src/block_builder/api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,12 +16,51 @@ //! The runtime api for building blocks. -use runtime_primitives::{traits::Block as BlockT, ApplyResult, CheckInherentError}; +use runtime_primitives::{traits::Block as BlockT, ApplyResult, RuntimeString}; use rstd::vec::Vec; +use sr_api_macros::decl_runtime_apis; +pub use inherents::{InherentData, CheckInherentsResult}; +use parity_codec::{Encode, Decode}; + +/// The old representation of the inherent data. +#[doc(hide)] +#[derive(Encode, Decode)] +pub struct OldInherentData { + /// Current timestamp. + pub timestamp: u64, + /// Blank report. + pub consensus: (), + /// Aura expected slot. Can take any value during block construction. + pub aura_expected_slot: u64, +} + +impl OldInherentData { + /// Create a new `BasicInherentData` instance. + pub fn new(timestamp: u64, expected_slot: u64) -> Self { + Self { + timestamp, + consensus: (), + aura_expected_slot: expected_slot, + } + } +} + +/// Error type used while checking inherents. +#[doc(hide)] +#[derive(Encode, PartialEq)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum OldCheckInherentError { + /// The inherents are generally valid but a delay until the given timestamp + /// is required. + ValidAtTimestamp(u64), + /// Some other error has occurred. + Other(RuntimeString), +} decl_runtime_apis! { /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. - pub trait BlockBuilder { + #[api_version(2)] + pub trait BlockBuilder { /// Apply the given extrinsics. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; /// Finish the current block. @@ -29,7 +68,12 @@ decl_runtime_apis! { /// Generate inherent extrinsics. The inherent data will vary from chain to chain. fn inherent_extrinsics(inherent: InherentData) -> Vec<::Extrinsic>; /// Check that the inherents are valid. The inherent data will vary from chain to chain. - fn check_inherents(block: Block, data: InherentData) -> Result<(), CheckInherentError>; + fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; + /// Check that the inherents are valid. The inherent data will vary from chain to chain. + /// + /// Old version that is used by the CC network. + #[changed_in(2)] + fn check_inherents(block: Block, data: OldInherentData) -> ::std::result::Result<(), OldCheckInherentError>; /// Generate a random seed. fn random_seed() -> ::Hash; } diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 8656bfed5351293d666680d3885d6704972d34b4..39969fc157dd3353935b87be75c7870989e3d077 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,32 +16,31 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; -use std::marker::PhantomData; -use codec::Encode; -use blockchain::HeaderBackend; +use parity_codec::Encode; +use crate::blockchain::HeaderBackend; use runtime_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef }; use primitives::H256; use runtime_primitives::generic::BlockId; -use runtime_api::Core; -use error; -use runtime_primitives::ApplyOutcome; +use crate::runtime_api::Core; +use crate::error; +use runtime_primitives::{ApplyOutcome, ExecutionContext}; + /// Utility for building new (valid) blocks from a stream of extrinsics. -pub struct BlockBuilder<'a, Block, InherentData, A: ProvideRuntimeApi> where Block: BlockT { +pub struct BlockBuilder<'a, Block, A: ProvideRuntimeApi> where Block: BlockT { header: ::Header, extrinsics: Vec<::Extrinsic>, api: ApiRef<'a, A::Api>, block_id: BlockId, - _marker: PhantomData, } -impl<'a, Block, A, InherentData> BlockBuilder<'a, Block, InherentData, A> +impl<'a, Block, A> BlockBuilder<'a, Block, A> where Block: BlockT, A: ProvideRuntimeApi + HeaderBackend + 'a, - A::Api: BlockBuilderApi, + A::Api: BlockBuilderApi, { /// Create a new instance of builder from the given client, building on the latest block. pub fn new(api: &'a A) -> error::Result { @@ -57,7 +56,6 @@ where let parent_hash = api.block_hash_from_id(block_id)? .ok_or_else(|| error::ErrorKind::UnknownBlock(format!("{}", block_id)))?; - let header = <::Header as HeaderT>::new( number, Default::default(), @@ -65,49 +63,41 @@ where parent_hash, Default::default() ); - let api = api.runtime_api(); - api.initialise_block(block_id, &header)?; - + api.initialise_block_with_context(block_id, ExecutionContext::BlockConstruction, &header)?; Ok(BlockBuilder { header, extrinsics: Vec::new(), api, block_id: *block_id, - _marker: PhantomData, }) } - /// Push onto the block's list of extrinsics. This will ensure the extrinsic - /// can be validly executed (by executing it); if it is invalid, it'll be returned along with - /// the error. Otherwise, it will return a mutable reference to self (in order to chain). + /// Push onto the block's list of extrinsics. + /// + /// This will ensure the extrinsic can be validly executed (by executing it); pub fn push(&mut self, xt: ::Extrinsic) -> error::Result<()> { - fn impl_push<'a, T, Block: BlockT, InherentData>( - api: &mut ApiRef<'a, T>, - block_id: &BlockId, - xt: Block::Extrinsic, - extrinsics: &mut Vec - ) -> error::Result<()> where T: BlockBuilderApi { - api.map_api_result(|api| { - match api.apply_extrinsic(block_id, &xt)? { - Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => { - extrinsics.push(xt); - Ok(()) - } - Err(e) => { - Err(error::ErrorKind::ApplyExtrinsicFailed(e).into()) - } - } - }) - } + use crate::runtime_api::ApiExt; - //FIXME: Please NLL, help me! - impl_push(&mut self.api, &self.block_id, xt, &mut self.extrinsics) + let block_id = &self.block_id; + let extrinsics = &mut self.extrinsics; + + self.api.map_api_result(|api| { + match api.apply_extrinsic_with_context(block_id, ExecutionContext::BlockConstruction, xt.clone())? { + Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => { + extrinsics.push(xt); + Ok(()) + } + Err(e) => { + Err(error::ErrorKind::ApplyExtrinsicFailed(e).into()) + } + } + }) } /// Consume the builder to return a valid `Block` containing all pushed extrinsics. pub fn bake(mut self) -> error::Result { - self.header = self.api.finalise_block(&self.block_id)?; + self.header = self.api.finalise_block_with_context(&self.block_id, ExecutionContext::BlockConstruction)?; debug_assert_eq!( self.header.extrinsics_root().clone(), diff --git a/core/client/src/block_builder/mod.rs b/core/client/src/block_builder/mod.rs index f22f599ffdd9a2ae356bef3006aff19a4225bd2d..7f617044a42cf7cbb734f516a702591f60742c10 100644 --- a/core/client/src/block_builder/mod.rs +++ b/core/client/src/block_builder/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/client/src/blockchain.rs b/core/client/src/blockchain.rs index ddc8ba866ae9646609d1d906b5c2176758aee5f5..a18c6e5d577a8bef1dbbacf53614869373f148e4 100644 --- a/core/client/src/blockchain.rs +++ b/core/client/src/blockchain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,12 +16,11 @@ //! Substrate blockchain trait -use primitives::AuthorityId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor}; use runtime_primitives::generic::BlockId; use runtime_primitives::Justification; -use error::{ErrorKind, Result}; +use crate::error::{ErrorKind, Result}; /// Blockchain database header backend. Does not perform any validation. pub trait HeaderBackend: Send + Sync { @@ -85,24 +84,15 @@ pub trait Backend: HeaderBackend { /// in other words, that have no children, are chain heads. /// Results must be ordered best (longest, heighest) chain first. fn leaves(&self) -> Result>; + + /// Return hashes of all blocks that are children of the block with `parent_hash`. + fn children(&self, parent_hash: Block::Hash) -> Result>; } /// Blockchain optional data cache. pub trait Cache: Send + Sync { /// Returns the set of authorities, that was active at given block or None if there's no entry in the cache. - fn authorities_at(&self, block: BlockId) -> Option>; -} - -/// Block import outcome -pub enum ImportResult { - /// Imported successfully. - Imported, - /// Block already exists, skippped. - AlreadyInChain, - /// Unknown parent. - UnknownParent, - /// Other errror. - Err(E), + fn authorities_at(&self, block: BlockId) -> Option>>; } /// Blockchain info diff --git a/core/client/src/call_executor.rs b/core/client/src/call_executor.rs index 8cbb40dfa2a3b7f3679e50de881250286823d335..c7872718745ab8f4856ef6c60884df5874f5c1c6 100644 --- a/core/client/src/call_executor.rs +++ b/core/client/src/call_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,31 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::sync::Arc; -use std::cmp::Ord; -use codec::Encode; +use std::{sync::Arc, cmp::Ord, panic::UnwindSafe, result}; +use parity_codec::{Encode, Decode}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::Block as BlockT; -use state_machine::{self, OverlayedChanges, Ext, - CodeExecutor, ExecutionManager, native_when_possible}; +use state_machine::{ + self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, ExecutionStrategy +}; use executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use hash_db::Hasher; use trie::MemoryDB; -use codec::Decode; -use primitives::{H256, Blake2Hasher}; -use primitives::storage::well_known_keys; +use primitives::{H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue}; -use backend; -use error; - -/// Information regarding the result of a call. -#[derive(Debug, Clone)] -pub struct CallResult { - /// The data that was returned from the call. - pub return_data: Vec, - /// The changes made to the state by the call. - pub changes: OverlayedChanges, -} +use crate::backend; +use crate::error; /// Method call executor. pub trait CallExecutor @@ -58,7 +47,8 @@ where id: &BlockId, method: &str, call_data: &[u8], - ) -> Result; + strategy: ExecutionStrategy, + ) -> Result, error::Error>; /// Execute a contextual call on top of state in a block of a given hash. /// @@ -67,7 +57,12 @@ where /// of the execution context. fn contextual_call< PB: Fn() -> error::Result, - EM: Fn(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, @@ -76,8 +71,9 @@ where changes: &mut OverlayedChanges, initialised_block: &mut Option>, prepare_environment_block: PB, - manager: ExecutionManager, - ) -> error::Result> where ExecutionManager: Clone; + execution_manager: ExecutionManager, + native_call: Option, + ) -> error::Result> where ExecutionManager: Clone; /// Extract RuntimeVersion of given block /// @@ -89,14 +85,20 @@ where /// No changes are made. fn call_at_state< S: state_machine::Backend, - F: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + F: FnOnce( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, overlay: &mut OverlayedChanges, method: &str, call_data: &[u8], - manager: ExecutionManager - ) -> Result<(Vec, S::Transaction, Option>), error::Error>; + manager: ExecutionManager, + native_call: Option, + ) -> Result<(NativeOrEncoded, S::Transaction, Option>), error::Error>; /// Execute a call to a contract on top of given state, gathering execution proof. /// @@ -153,7 +155,7 @@ impl Clone for LocalCallExecutor where E: Clone { impl CallExecutor for LocalCallExecutor where - B: backend::LocalBackend, + B: backend::Backend, E: CodeExecutor + RuntimeInfo, Block: BlockT, { @@ -163,21 +165,35 @@ where id: &BlockId, method: &str, call_data: &[u8], - ) -> error::Result { + strategy: ExecutionStrategy + ) -> error::Result> { let mut changes = OverlayedChanges::default(); - let (return_data, _, _) = self.call_at_state( - &self.backend.state_at(*id)?, + let state = self.backend.state_at(*id)?; + let return_data = state_machine::new( + &state, + self.backend.changes_trie_storage(), &mut changes, + &self.executor, method, call_data, - native_when_possible(), - )?; - Ok(CallResult { return_data, changes }) + ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + strategy.get_manager(), + false, + None, + ) + .map(|(result, _, _)| result)?; + self.backend.destroy_state(state)?; + Ok(return_data.into_encoded()) } fn contextual_call< PB: Fn() -> error::Result, - EM: Fn(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, @@ -186,56 +202,84 @@ where changes: &mut OverlayedChanges, initialised_block: &mut Option>, prepare_environment_block: PB, - manager: ExecutionManager, - ) -> Result, error::Error> where ExecutionManager: Clone { + execution_manager: ExecutionManager, + native_call: Option, + ) -> Result, error::Error> where ExecutionManager: Clone { let state = self.backend.state_at(*at)?; - //TODO: Find a better way to prevent double block initialization if method != "Core_initialise_block" && initialised_block.map(|id| id != *at).unwrap_or(true) { let header = prepare_environment_block()?; - self.call_at_state(&state, changes, "Core_initialise_block", &header.encode(), manager.clone())?; + state_machine::new( + &state, + self.backend.changes_trie_storage(), + changes, + &self.executor, + "Core_initialise_block", + &header.encode(), + ).execute_using_consensus_failure_handler::<_, R, fn() -> _>( + execution_manager.clone(), + false, + None, + )?; *initialised_block = Some(*at); } - self.call_at_state(&state, changes, method, call_data, manager).map(|cr| cr.0) + let result = state_machine::new( + &state, + self.backend.changes_trie_storage(), + changes, + &self.executor, + method, + call_data, + ).execute_using_consensus_failure_handler( + execution_manager, + false, + native_call, + ).map(|(result, _, _)| result)?; + + // If the method is `initialise_block` we need to set the `initialised_block` + if method == "Core_initialise_block" { + *initialised_block = Some(*at); + } + + self.backend.destroy_state(state)?; + Ok(result) } fn runtime_version(&self, id: &BlockId) -> error::Result { let mut overlay = OverlayedChanges::default(); let state = self.backend.state_at(*id)?; - use state_machine::Backend; - let code = state.storage(well_known_keys::CODE) - .map_err(|e| error::ErrorKind::Execution(Box::new(e)))? - .ok_or(error::ErrorKind::VersionInvalid)? - .to_vec(); - let heap_pages = state.storage(well_known_keys::HEAP_PAGES) - .map_err(|e| error::ErrorKind::Execution(Box::new(e)))? - .and_then(|v| u64::decode(&mut &v[..])) - .unwrap_or(1024) as usize; - let mut ext = Ext::new(&mut overlay, &state, self.backend.changes_trie_storage()); - self.executor.runtime_version(&mut ext, heap_pages, &code) + self.executor.runtime_version(&mut ext) .ok_or(error::ErrorKind::VersionInvalid.into()) } fn call_at_state< S: state_machine::Backend, - F: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + F: FnOnce( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, changes: &mut OverlayedChanges, method: &str, call_data: &[u8], manager: ExecutionManager, - ) -> error::Result<(Vec, S::Transaction, Option>)> { - state_machine::execute_using_consensus_failure_handler( + native_call: Option, + ) -> error::Result<(NativeOrEncoded, S::Transaction, Option>)> { + state_machine::new( state, self.backend.changes_trie_storage(), changes, &self.executor, method, call_data, + ).execute_using_consensus_failure_handler( manager, true, + native_call, ) .map(|(result, storage_tx, changes_tx)| ( result, diff --git a/core/client/src/children.rs b/core/client/src/children.rs new file mode 100644 index 0000000000000000000000000000000000000000..48b39d18cdd60d8c11585aae71d30ce1ab9ce335 --- /dev/null +++ b/core/client/src/children.rs @@ -0,0 +1,121 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Functionality for reading and storing children hashes from db. + +use kvdb::{KeyValueDB, DBTransaction}; +use parity_codec::{Encode, Decode}; +use crate::error; +use std::hash::Hash; + + +/// Returns the hashes of the children blocks of the block with `parent_hash`. +pub fn read_children< + K: Eq + Hash + Clone + Encode + Decode, + V: Eq + Hash + Clone + Encode + Decode, +>(db: &KeyValueDB, column: Option, prefix: &[u8], parent_hash: K) -> error::Result> { + let mut buf = prefix.to_vec(); + parent_hash.using_encoded(|s| buf.extend(s)); + + let raw_val_opt = match db.get(column, &buf[..]) { + Ok(raw_val_opt) => raw_val_opt, + Err(_) => return Err(error::ErrorKind::Backend("Error reading value from database".into()).into()), + }; + + let raw_val = match raw_val_opt { + Some(val) => val, + None => return Ok(Vec::new()), + }; + + let children: Vec = match Decode::decode(&mut &raw_val[..]) { + Some(children) => children, + None => return Err(error::ErrorKind::Backend("Error decoding children".into()).into()), + }; + + Ok(children) +} + +/// Insert the key-value pair (`parent_hash`, `children_hashes`) in the transaction. +/// Any existing value is overwritten upon write. +pub fn write_children< + K: Eq + Hash + Clone + Encode + Decode, + V: Eq + Hash + Clone + Encode + Decode, +>( + tx: &mut DBTransaction, + column: Option, + prefix: &[u8], + parent_hash: K, + children_hashes: V, +) { + let mut key = prefix.to_vec(); + parent_hash.using_encoded(|s| key.extend(s)); + tx.put_vec(column, &key[..], children_hashes.encode()); +} + +/// Prepare transaction to remove the children of `parent_hash`. +pub fn remove_children< + K: Eq + Hash + Clone + Encode + Decode, +>( + tx: &mut DBTransaction, + column: Option, + prefix: &[u8], + parent_hash: K, +) { + let mut key = prefix.to_vec(); + parent_hash.using_encoded(|s| key.extend(s)); + tx.delete(column, &key[..]); +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn children_write_read_remove() { + const PREFIX: &[u8] = b"children"; + let db = ::kvdb_memorydb::create(0); + + let mut tx = DBTransaction::new(); + + let mut children1 = Vec::new(); + children1.push(1_3); + children1.push(1_5); + write_children(&mut tx, None, PREFIX, 1_1, children1); + + let mut children2 = Vec::new(); + children2.push(1_4); + children2.push(1_6); + write_children(&mut tx, None, PREFIX, 1_2, children2); + + db.write(tx.clone()).unwrap(); + + let r1: Vec = read_children(&db, None, PREFIX, 1_1).unwrap(); + let r2: Vec = read_children(&db, None, PREFIX, 1_2).unwrap(); + + assert_eq!(r1, vec![1_3, 1_5]); + assert_eq!(r2, vec![1_4, 1_6]); + + remove_children(&mut tx, None, PREFIX, 1_2); + db.write(tx).unwrap(); + + let r1: Vec = read_children(&db, None, PREFIX, 1_1).unwrap(); + let r2: Vec = read_children(&db, None, PREFIX, 1_2).unwrap(); + + assert_eq!(r1, vec![1_3, 1_5]); + assert_eq!(r2.len(), 0); + } +} \ No newline at end of file diff --git a/core/client/src/cht.rs b/core/client/src/cht.rs index 51fb485da6b1cee0e987b30f08ef9b9d6e0eb440..d8e7ffbff33a74ab65539913fa9f23839422660f 100644 --- a/core/client/src/cht.rs +++ b/core/client/src/cht.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ use state_machine::backend::InMemory as InMemoryState; use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend}; -use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use crate::error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; /// The size of each CHT. This value is passed to every CHT-related function from /// production code. Other values are passed from tests. @@ -339,20 +339,20 @@ mod tests { #[test] fn build_pairs_fails_when_no_enough_blocks() { assert!(build_pairs::(SIZE, 0, - ::std::iter::repeat_with(|| Ok(Some(1.into()))).take(SIZE as usize / 2)).is_err()); + ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize / 2)).is_err()); } #[test] fn build_pairs_fails_when_missing_block() { - assert!(build_pairs::(SIZE, 0, ::std::iter::repeat_with(|| Ok(Some(1.into()))).take(SIZE as usize / 2) + assert!(build_pairs::(SIZE, 0, ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize / 2) .chain(::std::iter::once(Ok(None))) - .chain(::std::iter::repeat_with(|| Ok(Some(2.into()))).take(SIZE as usize / 2 - 1))).is_err()); + .chain(::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(2)))).take(SIZE as usize / 2 - 1))).is_err()); } #[test] fn compute_root_works() { assert!(compute_root::(SIZE, 42, - ::std::iter::repeat_with(|| Ok(Some(1.into()))).take(SIZE as usize)).is_ok()); + ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize)).is_ok()); } #[test] @@ -360,14 +360,14 @@ mod tests { fn build_proof_panics_when_querying_wrong_block() { assert!(build_proof::( SIZE, 0, vec![(SIZE * 1000) as u64], - ::std::iter::repeat_with(|| Ok(Some(1.into()))).take(SIZE as usize)).is_err()); + ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize)).is_err()); } #[test] fn build_proof_works() { assert!(build_proof::( SIZE, 0, vec![(SIZE / 2) as u64], - ::std::iter::repeat_with(|| Ok(Some(1.into()))).take(SIZE as usize)).is_ok()); + ::std::iter::repeat_with(|| Ok(Some(H256::from_low_u64_be(1)))).take(SIZE as usize)).is_ok()); } #[test] diff --git a/core/client/src/client.rs b/core/client/src/client.rs index a37bd163b254833489f42db7c21b2cdeceeafdac..34723deb8cca1316ec736bfc06273ce54199ad47 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,40 +16,55 @@ //! Substrate Client -use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc}; -use error::Error; +use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe, result}; +use crate::error::Error; use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; -use primitives::AuthorityId; +use primitives::NativeOrEncoded; use runtime_primitives::{ Justification, generic::{BlockId, SignedBlock}, }; -use consensus::{ImportBlock, ImportResult, BlockOrigin}; +use consensus::{ + Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, + BlockOrigin, ForkChoiceStrategy, +}; use runtime_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash, - ApiRef, ProvideRuntimeApi, Digest, DigestItem, + ApiRef, ProvideRuntimeApi, Digest, DigestItem, AuthorityIdFor }; -use runtime_primitives::BuildStorage; -use runtime_api::{Core as CoreAPI, CallRuntimeAt, ConstructRuntimeApi}; -use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash}; +use runtime_primitives::{BuildStorage, ExecutionContext}; +use crate::runtime_api::{CallRuntimeAt, ConstructRuntimeApi}; +use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue}; use primitives::storage::{StorageKey, StorageData}; use primitives::storage::well_known_keys; -use codec::Decode; +use parity_codec::{Encode, Decode}; use state_machine::{ DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager, prove_read, ChangesTrieRootsStorage, ChangesTrieStorage, - key_changes, key_changes_proof, OverlayedChanges + key_changes, key_changes_proof, OverlayedChanges, }; +use hash_db::Hasher; -use backend::{self, BlockImportOperation}; -use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend}; -use call_executor::{CallExecutor, LocalCallExecutor}; +use crate::backend::{self, BlockImportOperation, PrunableStateChangesTrieStorage}; +use crate::blockchain::{ + self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend +}; +use crate::call_executor::{CallExecutor, LocalCallExecutor}; use executor::{RuntimeVersion, RuntimeInfo}; -use notifications::{StorageNotifications, StorageEventStream}; -use light::{call_executor::prove_execution, fetcher::ChangesProof}; -use {cht, error, in_mem, block_builder::{self, api::BlockBuilder as BlockBuilderAPI}, genesis, consensus}; +use crate::notifications::{StorageNotifications, StorageEventStream}; +use crate::light::{call_executor::prove_execution, fetcher::ChangesProof}; +use crate::cht; +use crate::error::{self, ErrorKind}; +use crate::in_mem; +use crate::block_builder::{self, api::BlockBuilder as BlockBuilderAPI}; +use crate::genesis; +use consensus; +use substrate_telemetry::{telemetry, SUBSTRATE_INFO}; + +use log::{info, trace, warn}; +use error_chain::bail; /// Type that implements `futures::Stream` of block import events. pub type ImportNotifications = mpsc::UnboundedReceiver>; @@ -57,6 +72,33 @@ pub type ImportNotifications = mpsc::UnboundedReceiver = mpsc::UnboundedReceiver>; +type StorageUpdate = <<>::BlockImportOperation as BlockImportOperation>::State as state_machine::Backend>::Transaction; +type ChangesUpdate = trie::MemoryDB; + +/// Execution strategies settings. +#[derive(Debug, Clone)] +pub struct ExecutionStrategies { + /// Execution strategy used when syncing. + pub syncing: ExecutionStrategy, + /// Execution strategy used when importing blocks. + pub importing: ExecutionStrategy, + /// Execution strategy used when constructing blocks. + pub block_construction: ExecutionStrategy, + /// Execution strategy used in other cases. + pub other: ExecutionStrategy, +} + +impl Default for ExecutionStrategies { + fn default() -> ExecutionStrategies { + ExecutionStrategies { + syncing: ExecutionStrategy::NativeElseWasm, + importing: ExecutionStrategy::NativeElseWasm, + block_construction: ExecutionStrategy::AlwaysWasm, + other: ExecutionStrategy::NativeElseWasm, + } + } +} + /// Substrate Client pub struct Client where Block: BlockT { backend: Arc, @@ -65,12 +107,19 @@ pub struct Client where Block: BlockT { import_notification_sinks: Mutex>>>, finality_notification_sinks: Mutex>>>, import_lock: Mutex<()>, - importing_block: RwLock>, // holds the block hash currently being imported. TODO: replace this with block queue - block_execution_strategy: ExecutionStrategy, - api_execution_strategy: ExecutionStrategy, + // holds the block hash currently being imported. TODO: replace this with block queue + importing_block: RwLock>, + execution_strategies: ExecutionStrategies, _phantom: PhantomData, } +/// Client import operation, a wrapper for the backend. +pub struct ClientImportOperation, B: backend::Backend> { + op: B::BlockImportOperation, + notify_imported: Option<(Block::Hash, BlockOrigin, Block::Header, bool, Option, Option>)>>)>, + notify_finalized: Vec, +} + /// A source of blockchain events. pub trait BlockchainEvents { /// Get block import event stream. Not guaranteed to be fired for every @@ -103,7 +152,6 @@ pub trait BlockBody { } /// Client info -// TODO: split queue info from chain info and amalgamate into single struct. #[derive(Debug)] pub struct ClientInfo { /// Best block hash. @@ -211,7 +259,7 @@ pub fn new_with_backend( B: backend::LocalBackend { let call_executor = LocalCallExecutor::new(backend.clone(), executor); - Client::new(backend, call_executor, build_genesis_storage, ExecutionStrategy::NativeWhenPossible, ExecutionStrategy::NativeWhenPossible) + Client::new(backend, call_executor, build_genesis_storage, Default::default()) } impl Client where @@ -224,21 +272,20 @@ impl Client where backend: Arc, executor: E, build_genesis_storage: S, - block_execution_strategy: ExecutionStrategy, - api_execution_strategy: ExecutionStrategy, + execution_strategies: ExecutionStrategies ) -> error::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { let (genesis_storage, children_genesis_storage) = build_genesis_storage.build_storage()?; - let mut op = backend.begin_operation(BlockId::Hash(Default::default()))?; + let mut op = backend.begin_operation()?; + backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?; let state_root = op.reset_storage(genesis_storage, children_genesis_storage)?; - let genesis_block = genesis::construct_genesis_block::(state_root.into()); info!("Initialising Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), genesis_block.header().hash()); op.set_block_data( genesis_block.deconstruct().0, Some(vec![]), None, - ::backend::NewBlockState::Final + crate::backend::NewBlockState::Final )?; backend.commit_operation(op)?; } @@ -251,12 +298,16 @@ impl Client where finality_notification_sinks: Default::default(), import_lock: Default::default(), importing_block: Default::default(), - block_execution_strategy, - api_execution_strategy, + execution_strategies, _phantom: Default::default(), }) } + /// Get a reference to the execution strategies. + pub fn execution_strategies(&self) -> &ExecutionStrategies { + &self.execution_strategies + } + /// Get a reference to the state at a given block. pub fn state_at(&self, block: &BlockId) -> error::Result { self.backend.state_at(*block) @@ -267,6 +318,12 @@ impl Client where &self.backend } + /// Return storage entry keys in state in a block of given hash with given prefix. + pub fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> error::Result> { + let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); + Ok(keys) + } + /// Return single storage entry of contract under given address in state in a block of given hash. pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result> { Ok(self.state_at(id)? @@ -281,18 +338,17 @@ impl Client where } /// Get the set of authorities at a given block. - pub fn authorities_at(&self, id: &BlockId) -> error::Result> { + pub fn authorities_at(&self, id: &BlockId) -> error::Result>> { match self.backend.blockchain().cache().and_then(|cache| cache.authorities_at(*id)) { Some(cached_value) => Ok(cached_value), - None => self.executor.call(id, "Core_authorities",&[]) - .and_then(|r| Vec::::decode(&mut &r.return_data[..]) - .ok_or(error::ErrorKind::InvalidAuthoritiesSet.into())) + None => self.executor.call(id, "Core_authorities", &[], ExecutionStrategy::NativeElseWasm) + .and_then(|r| Vec::>::decode(&mut &r[..]) + .ok_or_else(|| error::ErrorKind::InvalidAuthoritiesSet.into())) } } /// Get the RuntimeVersion at a given block. pub fn runtime_version_at(&self, id: &BlockId) -> error::Result { - // TODO: Post Poc-2 return an error if version is missing self.executor.runtime_version(id) } @@ -341,35 +397,54 @@ impl Client where Ok((header, proof)) } + /// Get longest range within [first; last] that is possible to use in `key_changes` + /// and `key_changes_proof` calls. + /// Range could be shortened from the beginning if some changes tries have been pruned. + /// Returns Ok(None) if changes trues are not supported. + pub fn max_key_changes_range( + &self, + first: NumberFor, + last: BlockId, + ) -> error::Result, BlockId)>> { + let (config, storage) = match self.require_changes_trie().ok() { + Some((config, storage)) => (config, storage), + None => return Ok(None), + }; + let first = first.as_(); + let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?.as_(); + if first > last_num { + return Err(error::ErrorKind::ChangesTrieAccessFailed("Invalid changes trie range".into()).into()); + } + let finalized_number = self.backend.blockchain().info()?.finalized_number; + let oldest = storage.oldest_changes_trie_block(&config, finalized_number.as_()); + let first = As::sa(::std::cmp::max(first, oldest)); + Ok(Some((first, last))) + } + /// Get pairs of (block, extrinsic) where key has been changed at given blocks range. /// Works only for runtimes that are supporting changes tries. pub fn key_changes( &self, - first: Block::Hash, - last: Block::Hash, - key: &[u8] + first: NumberFor, + last: BlockId, + key: &StorageKey ) -> error::Result, u32)>> { - let config = self.changes_trie_config()?; - let storage = self.backend.changes_trie_storage(); - let (config, storage) = match (config, storage) { - (Some(config), Some(storage)) => (config, storage), - _ => return Err(error::ErrorKind::ChangesTriesNotSupported.into()), - }; + let (config, storage) = self.require_changes_trie()?; + let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?.as_(); + let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - let first_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(first))?.as_(); - let last_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(last))?.as_(); key_changes::<_, Blake2Hasher>( &config, - storage, - first_number, + &*storage, + first.as_(), &ChangesTrieAnchorBlockId { - hash: convert_hash(&last), + hash: convert_hash(&last_hash), number: last_number, }, self.backend.blockchain().info()?.best_number.as_(), - key) + &key.0) + .and_then(|r| r.map(|r| r.map(|(block, tx)| (As::sa(block), tx))).collect::>()) .map_err(|err| error::ErrorKind::ChangesTrieAccessFailed(err).into()) - .map(|r| r.into_iter().map(|(b, e)| (As::sa(b), e)).collect()) } /// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range. @@ -384,7 +459,7 @@ impl Client where last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &[u8] + key: &StorageKey ) -> error::Result> { self.key_changes_proof_with_cht_size( first, @@ -403,7 +478,7 @@ impl Client where last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &[u8], + key: &StorageKey, cht_size: u64, ) -> error::Result> { struct AccessedRootsRecorder<'a, Block: BlockT> { @@ -433,14 +508,9 @@ impl Client where } } - let config = self.changes_trie_config()?; - let storage = self.backend.changes_trie_storage(); - let (config, storage) = match (config, storage) { - (Some(config), Some(storage)) => (config, storage), - _ => return Err(error::ErrorKind::ChangesTriesNotSupported.into()), - }; - + let (config, storage) = self.require_changes_trie()?; let min_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?; + let recording_storage = AccessedRootsRecorder:: { storage, min: min_number.as_(), @@ -464,7 +534,7 @@ impl Client where number: last_number, }, max_number.as_(), - key + &key.0 ) .map_err(|err| error::Error::from(error::ErrorKind::ChangesTrieAccessFailed(err)))?; @@ -514,36 +584,173 @@ impl Client where Ok(proof) } + /// Returns changes trie configuration and storage or an error if it is not supported. + fn require_changes_trie(&self) -> error::Result<(ChangesTrieConfiguration, &B::ChangesTrieStorage)> { + let config = self.changes_trie_config()?; + let storage = self.backend.changes_trie_storage(); + match (config, storage) { + (Some(config), Some(storage)) => Ok((config, storage)), + _ => Err(error::ErrorKind::ChangesTriesNotSupported.into()), + } + } + /// Create a new block, built on the head of the chain. - pub fn new_block( + pub fn new_block( &self - ) -> error::Result> where + ) -> error::Result> where E: Clone + Send + Sync, - RA: BlockBuilderAPI + RA: Send + Sync, + Self: ProvideRuntimeApi, + ::Api: BlockBuilderAPI { block_builder::BlockBuilder::new(self) } /// Create a new block, built on top of `parent`. - pub fn new_block_at( + pub fn new_block_at( &self, parent: &BlockId - ) -> error::Result> where + ) -> error::Result> where E: Clone + Send + Sync, - RA: BlockBuilderAPI + RA: Send + Sync, + Self: ProvideRuntimeApi, + ::Api: BlockBuilderAPI { block_builder::BlockBuilder::at_block(parent, &self) } + /// Lock the import lock, and run operations inside. + pub fn lock_import_and_run(&self, f: F) -> Result where + F: FnOnce(&mut ClientImportOperation) -> Result, + Err: From, + { + let inner = || { + let _import_lock = self.import_lock.lock(); + + let mut op = ClientImportOperation { + op: self.backend.begin_operation()?, + notify_imported: None, + notify_finalized: Vec::new(), + }; + + let r = f(&mut op)?; + + let ClientImportOperation { op, notify_imported, notify_finalized } = op; + self.backend.commit_operation(op)?; + self.notify_finalized(notify_finalized)?; + + if let Some(notify_imported) = notify_imported { + self.notify_imported(notify_imported)?; + } + + Ok(r) + }; + + let result = inner(); + *self.importing_block.write() = None; + + result + } + + /// Set a block as best block. + pub fn set_head( + &self, + id: BlockId + ) -> error::Result<()> { + self.lock_import_and_run(|operation| { + self.apply_head(operation, id) + }) + } + + /// Set a block as best block, and apply it to an operation. + pub fn apply_head( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + ) -> error::Result<()> { + operation.op.mark_head(id) + } + + /// Apply a checked and validated block to an operation. If a justification is provided + /// then `finalized` *must* be true. + pub fn apply_block( + &self, + operation: &mut ClientImportOperation, + import_block: ImportBlock, + new_authorities: Option>>, + ) -> error::Result where + E: CallExecutor + Send + Sync + Clone, + { + use runtime_primitives::traits::Digest; + + let ImportBlock { + origin, + header, + justification, + post_digests, + body, + finalized, + auxiliary, + fork_choice, + } = import_block; + + assert!(justification.is_some() && finalized || justification.is_none()); + + let parent_hash = header.parent_hash().clone(); + + match self.backend.blockchain().status(BlockId::Hash(parent_hash))? { + blockchain::BlockStatus::InChain => {}, + blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), + } + + let import_headers = if post_digests.is_empty() { + PrePostHeader::Same(header) + } else { + let mut post_header = header.clone(); + for item in post_digests { + post_header.digest_mut().push(item); + } + PrePostHeader::Different(header, post_header) + }; + + let hash = import_headers.post().hash(); + let height: u64 = import_headers.post().number().as_(); + + *self.importing_block.write() = Some(hash); + + let result = self.execute_and_import_block( + operation, + origin, + hash, + import_headers, + justification, + body, + new_authorities, + finalized, + auxiliary, + fork_choice, + ); + + telemetry!(SUBSTRATE_INFO; "block.import"; + "height" => height, + "best" => ?hash, + "origin" => ?origin + ); + + result + } + fn execute_and_import_block( &self, + operation: &mut ClientImportOperation, origin: BlockOrigin, hash: Block::Hash, import_headers: PrePostHeader, justification: Option, body: Option>, - authorities: Option>, + authorities: Option>>, finalized: bool, aux: Vec<(Vec, Option>)>, + fork_choice: ForkChoiceStrategy, ) -> error::Result where E: CallExecutor + Send + Sync + Clone, { @@ -566,60 +773,32 @@ impl Client where BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false, }; + self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; + // ensure parent block is finalized to maintain invariant that // finality is called sequentially. if finalized { - self.apply_finality(parent_hash, None, last_best, make_notifications)?; + self.apply_finality_with_block_hash(operation, parent_hash, None, last_best, make_notifications)?; } - let mut transaction = self.backend.begin_operation(BlockId::Hash(parent_hash))?; - let (storage_update, changes_update, storage_changes) = match transaction.state()? { - Some(transaction_state) => { - let mut overlay = Default::default(); - let mut r = self.executor.call_at_state( - transaction_state, - &mut overlay, - "Core_execute_block", - &::new(import_headers.pre().clone(), body.clone().unwrap_or_default()).encode(), - match (origin, self.block_execution_strategy) { - (BlockOrigin::NetworkInitialSync, _) | (_, ExecutionStrategy::NativeWhenPossible) => - ExecutionManager::NativeWhenPossible, - (_, ExecutionStrategy::AlwaysWasm) => ExecutionManager::AlwaysWasm, - _ => ExecutionManager::Both(|wasm_result, native_result| { - let header = import_headers.post(); - warn!("Consensus error between wasm and native block execution at block {}", hash); - warn!(" Header {:?}", header); - warn!(" Native result {:?}", native_result); - warn!(" Wasm result {:?}", wasm_result); - telemetry!("block.execute.consensus_failure"; - "hash" => ?hash, - "origin" => ?origin, - "header" => ?header - ); - wasm_result - }), - }, - ); - let (_, storage_update, changes_update) = r?; - overlay.commit_prospective(); - (Some(storage_update), Some(changes_update), Some(overlay.into_committed())) - }, - None => (None, None, None) - }; + // FIXME #1232: correct path logic for when to execute this function + let (storage_update,changes_update,storage_changes) = self.block_execution(&operation.op, &import_headers, origin, hash, body.clone())?; - // TODO: non longest-chain rule. - let is_new_best = finalized || import_headers.post().number() > &last_best_number; + let is_new_best = finalized || match fork_choice { + ForkChoiceStrategy::LongestChain => import_headers.post().number() > &last_best_number, + ForkChoiceStrategy::Custom(v) => v, + }; let leaf_state = if finalized { - ::backend::NewBlockState::Final + crate::backend::NewBlockState::Final } else if is_new_best { - ::backend::NewBlockState::Best + crate::backend::NewBlockState::Best } else { - ::backend::NewBlockState::Normal + crate::backend::NewBlockState::Normal }; trace!("Imported {}, (#{}), best={}, origin={:?}", hash, import_headers.post().number(), is_new_best, origin); - transaction.set_block_data( + operation.op.set_block_data( import_headers.post().clone(), body, justification, @@ -627,54 +806,92 @@ impl Client where )?; if let Some(authorities) = authorities { - transaction.update_authorities(authorities); + operation.op.update_authorities(authorities); } if let Some(storage_update) = storage_update { - transaction.update_storage(storage_update)?; + operation.op.update_db_storage(storage_update)?; + } + if let Some(storage_changes) = storage_changes.clone() { + operation.op.update_storage(storage_changes)?; } if let Some(Some(changes_update)) = changes_update { - transaction.update_changes_trie(changes_update)?; + operation.op.update_changes_trie(changes_update)?; } - transaction.set_aux(aux)?; - self.backend.commit_operation(transaction)?; + operation.op.insert_aux(aux)?; if make_notifications { - if let Some(storage_changes) = storage_changes { - // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? - self.storage_notifications.lock() - .trigger(&hash, storage_changes); + if finalized { + operation.notify_finalized.push(hash); } - if finalized { - let notification = FinalityNotification:: { - hash, - header: import_headers.post().clone(), - }; + operation.notify_imported = Some((hash, origin, import_headers.into_post(), is_new_best, storage_changes)); + } - self.finality_notification_sinks.lock() - .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - } + Ok(ImportResult::imported()) + } - let notification = BlockImportNotification:: { - hash, - origin, - header: import_headers.into_post(), - is_new_best, - }; + fn block_execution( + &self, + transaction: &B::BlockImportOperation, + import_headers: &PrePostHeader, + origin: BlockOrigin, + hash: Block::Hash, + body: Option>, + ) -> error::Result<( + Option>, + Option>, + Option, Option>)>>, + )> + where + E: CallExecutor + Send + Sync + Clone, + { + match transaction.state()? { + Some(transaction_state) => { + let mut overlay = Default::default(); + let get_execution_manager = |execution_strategy: ExecutionStrategy| { + match execution_strategy { + ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm, + ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, + ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, + ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { + let header = import_headers.post(); + warn!("Consensus error between wasm and native block execution at block {}", hash); + warn!(" Header {:?}", header); + warn!(" Native result {:?}", native_result); + warn!(" Wasm result {:?}", wasm_result); + telemetry!(SUBSTRATE_INFO; "block.execute.consensus_failure"; + "hash" => ?hash, + "origin" => ?origin, + "header" => ?header + ); + wasm_result + }), + } + }; + let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> _>( + transaction_state, + &mut overlay, + "Core_execute_block", + &::new(import_headers.pre().clone(), body.unwrap_or_default()).encode(), + match origin { + BlockOrigin::NetworkInitialSync => get_execution_manager(self.execution_strategies().syncing), + _ => get_execution_manager(self.execution_strategies().importing), + }, + None, + )?; - self.import_notification_sinks.lock() - .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - } + overlay.commit_prospective(); - Ok(ImportResult::Queued) + Ok((Some(storage_update), Some(changes_update), Some(overlay.into_committed().collect()))) + }, + None => Ok((None, None, None)) + } } - /// Finalizes all blocks up to given. If a justification is provided it is - /// stored with the given finalized block (any other finalized blocks are - /// left unjustified). - fn apply_finality( + fn apply_finality_with_block_hash( &self, + operation: &mut ClientImportOperation, block: Block::Hash, justification: Option, best_block: Block::Hash, @@ -683,8 +900,12 @@ impl Client where // find tree route from last finalized to given block. let last_finalized = self.backend.blockchain().last_finalized()?; - if block == last_finalized { return Ok(()) } - let route_from_finalized = ::blockchain::tree_route( + if block == last_finalized { + warn!("Possible safety violation: attempted to re-finalize last finalized block {:?} ", last_finalized); + return Ok(()); + } + + let route_from_finalized = crate::blockchain::tree_route( self.backend.blockchain(), BlockId::Hash(last_finalized), BlockId::Hash(block), @@ -697,7 +918,7 @@ impl Client where bail!(error::ErrorKind::NotInFinalizedChain); } - let route_from_best = ::blockchain::tree_route( + let route_from_best = crate::blockchain::tree_route( self.backend.blockchain(), BlockId::Hash(best_block), BlockId::Hash(block), @@ -706,18 +927,18 @@ impl Client where // if the block is not a direct ancestor of the current best chain, // then some other block is the common ancestor. if route_from_best.common_block().hash != block { - // TODO: reorganize best block to be the best chain containing + // FIXME: #1442 reorganize best block to be the best chain containing // `block`. } let enacted = route_from_finalized.enacted(); assert!(enacted.len() > 0); for finalize_new in &enacted[..enacted.len() - 1] { - self.backend.finalize_block(BlockId::Hash(finalize_new.hash), None)?; + operation.op.mark_finalized(BlockId::Hash(finalize_new.hash), None)?; } assert_eq!(enacted.last().map(|e| e.hash), Some(block)); - self.backend.finalize_block(BlockId::Hash(block), justification)?; + operation.op.mark_finalized(BlockId::Hash(block), justification)?; if notify { // sometimes when syncing, tons of blocks can be finalized at once. @@ -725,22 +946,95 @@ impl Client where const MAX_TO_NOTIFY: usize = 256; let enacted = route_from_finalized.enacted(); let start = enacted.len() - ::std::cmp::min(enacted.len(), MAX_TO_NOTIFY); - let mut sinks = self.finality_notification_sinks.lock(); for finalized in &enacted[start..] { - let header = self.header(&BlockId::Hash(finalized.hash))? - .expect("header already known to exist in DB because it is indicated in the tree route; qed"); - let notification = FinalityNotification { - header, - hash: finalized.hash, - }; - - sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + operation.notify_finalized.push(finalized.hash); } } Ok(()) } + fn notify_finalized( + &self, + notify_finalized: Vec, + ) -> error::Result<()> { + let mut sinks = self.finality_notification_sinks.lock(); + + for finalized_hash in notify_finalized { + let header = self.header(&BlockId::Hash(finalized_hash))? + .expect("header already known to exist in DB because it is indicated in the tree route; qed"); + + let notification = FinalityNotification { + header, + hash: finalized_hash, + }; + + sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + } + + Ok(()) + } + + fn notify_imported( + &self, + notify_import: (Block::Hash, BlockOrigin, Block::Header, bool, Option, Option>)>>), + ) -> error::Result<()> { + let (hash, origin, header, is_new_best, storage_changes) = notify_import; + + if let Some(storage_changes) = storage_changes { + // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? + self.storage_notifications.lock() + .trigger(&hash, storage_changes.into_iter()); + } + + let notification = BlockImportNotification:: { + hash, + origin, + header, + is_new_best, + }; + + self.import_notification_sinks.lock() + .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + + Ok(()) + } + + /// Apply auxiliary data insertion into an operation. + pub fn apply_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >( + &self, + operation: &mut ClientImportOperation, + insert: I, + delete: D + ) -> error::Result<()> { + operation.op.insert_aux( + insert.into_iter() + .map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + .chain(delete.into_iter().map(|k| (k.to_vec(), None))) + ) + } + + /// Mark all blocks up to given as finalized in operation. If a + /// justification is provided it is stored with the given finalized + /// block (any other finalized blocks are left unjustified). + pub fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> error::Result<()> { + let last_best = self.backend.blockchain().info()?.best_hash; + let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; + self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) + } + /// Finalize a block. This will implicitly finalize all blocks up to it and /// fire finality notifications. /// @@ -748,9 +1042,11 @@ impl Client where /// This is usually tied to some synchronization state, where we don't send notifications /// while performing major synchronization work. pub fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { - let last_best = self.backend.blockchain().info()?.best_hash; - let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; - self.apply_finality(to_finalize_hash, justification, last_best, notify) + self.lock_import_and_run(|operation| { + let last_best = self.backend.blockchain().info()?.best_hash; + let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; + self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) + }) } /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were @@ -771,7 +1067,7 @@ impl Client where /// Get block status. pub fn block_status(&self, id: &BlockId) -> error::Result { - // TODO: more efficient implementation + // this can probably be implemented more efficiently if let BlockId::Hash(ref h) = id { if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { return Ok(BlockStatus::Queued); @@ -817,12 +1113,16 @@ impl Client where /// Get the most recent block hash of the best (longest) chains /// that contain block with the given `target_hash`. + /// + /// The search space is always limited to blocks which are in the finalized + /// chain or descendents of it. + /// /// If `maybe_max_block_number` is `Some(max_block_number)` /// the search is limited to block `numbers <= max_block_number`. /// in other words as if there were no blocks greater `max_block_number`. - /// TODO [snd] possibly implement this on blockchain::Backend and just redirect here + /// TODO : we want to move this implement to `blockchain::Backend`, see [#1443](https://github.com/paritytech/substrate/issues/1443) /// Returns `Ok(None)` if `target_hash` is not found in search space. - /// TODO [snd] write down time complexity + /// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) pub fn best_containing(&self, target_hash: Block::Hash, maybe_max_number: Option>) -> error::Result> { @@ -861,7 +1161,11 @@ impl Client where } return Ok(Some(info.best_hash)); + } else if info.finalized_number >= *target_header.number() { + // header is on a dead fork. + return Ok(None); } + (self.backend.blockchain().leaves()?, info.best_hash) }; @@ -882,7 +1186,6 @@ impl Client where // waiting until we are <= max_number if let Some(max_number) = maybe_max_number { loop { - // TODO [snd] this should be a panic let current_header = self.backend.blockchain().header(BlockId::Hash(current_hash.clone()))? .ok_or_else(|| error::Error::from(format!("failed to get header for hash {}", current_hash)))?; @@ -902,7 +1205,6 @@ impl Client where return Ok(Some(best_hash)); } - // TODO [snd] this should be a panic let current_header = self.backend.blockchain().header(BlockId::Hash(current_hash.clone()))? .ok_or_else(|| error::Error::from(format!("failed to get header for hash {}", current_hash)))?; @@ -915,7 +1217,49 @@ impl Client where } } - unreachable!("this is a bug. `target_hash` is in blockchain but wasn't found following all leaves backwards"); + // header may be on a dead fork -- the only leaves that are considered are + // those which can still be finalized. + // + // FIXME #1558 only issue this warning when not on a dead fork + warn!( + "Block {:?} exists in chain but not found when following all \ + leaves backwards. Number limit = {:?}", + target_hash, + maybe_max_number, + ); + + Ok(None) + } + + /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. + pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> error::Result> { + let load_header = |id: Block::Hash| -> error::Result { + match self.backend.blockchain().header(BlockId::Hash(id))? { + Some(hdr) => Ok(hdr), + None => Err(ErrorKind::UnknownBlock(format!("Unknown block {:?}", id)).into()), + } + }; + + let genesis_hash = self.backend.blockchain().info()?.genesis_hash; + if genesis_hash == target_hash { return Ok(Vec::new()); } + + let mut current_hash = target_hash; + let mut current = load_header(current_hash)?; + let mut ancestor_hash = *current.parent_hash(); + let mut ancestor = load_header(ancestor_hash)?; + let mut uncles = Vec::new(); + + for _generation in 0..max_generation.as_() { + let children = self.backend.blockchain().children(ancestor_hash)?; + uncles.extend(children.into_iter().filter(|h| h != ¤t_hash)); + current_hash = ancestor_hash; + if genesis_hash == current_hash { break; } + current = ancestor; + ancestor_hash = *current.parent_hash(); + ancestor = load_header(ancestor_hash)?; + } + + Ok(uncles) } fn changes_trie_config(&self) -> Result, Error> { @@ -968,44 +1312,48 @@ impl ProvideRuntimeApi for Client where B: backend::Backend, E: CallExecutor + Clone + Send + Sync, Block: BlockT, - RA: CoreAPI + RA: ConstructRuntimeApi { - type Api = RA; + type Api = >::RuntimeApi; fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - Self::Api::construct_runtime_api(self) + RA::construct_runtime_api(self) } } impl CallRuntimeAt for Client where B: backend::Backend, E: CallExecutor + Clone + Send + Sync, - Block: BlockT, - RA: CoreAPI, // not strictly necessary at the moment - // but we want to bound to make sure the API is actually available. + Block: BlockT { - fn call_api_at( + fn call_api_at< + R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe + >( &self, at: &BlockId, function: &'static str, args: Vec, changes: &mut OverlayedChanges, initialised_block: &mut Option>, - ) -> error::Result> { - let execution_manager = match self.api_execution_strategy { - ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, - ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, - ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { - warn!("Consensus error between wasm and native runtime execution at block {:?}", at); - warn!(" Function {:?}", function); - warn!(" Native result {:?}", native_result); - warn!(" Wasm result {:?}", wasm_result); - wasm_result - }), + native_call: Option, + context: ExecutionContext + ) -> error::Result> { + let manager = match context { + ExecutionContext::BlockConstruction => self.execution_strategies.block_construction.get_manager(), + ExecutionContext::Syncing => self.execution_strategies.syncing.get_manager(), + ExecutionContext::Importing => self.execution_strategies.importing.get_manager(), + ExecutionContext::Other => self.execution_strategies.other.get_manager(), }; - - self.executor.contextual_call(at, function, &args, changes, initialised_block, - || self.prepare_environment_block(at), execution_manager) + self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( + at, + function, + &args, + changes, + initialised_block, + || self.prepare_environment_block(at), + manager, + native_call, + ) } fn runtime_version_at(&self, at: &BlockId) -> error::Result { @@ -1013,75 +1361,46 @@ impl CallRuntimeAt for Client where } } - impl consensus::BlockImport for Client where B: backend::Backend, E: CallExecutor + Clone + Send + Sync, Block: BlockT, { - type Error = Error; + type Error = ConsensusError; /// Import a checked and validated block. If a justification is provided in /// `ImportBlock` then `finalized` *must* be true. fn import_block( &self, import_block: ImportBlock, - new_authorities: Option>, + new_authorities: Option>>, ) -> Result { - use runtime_primitives::traits::Digest; - - let ImportBlock { - origin, - header, - justification, - post_digests, - body, - finalized, - auxiliary, - } = import_block; - - assert!(justification.is_some() && finalized || justification.is_none()); - - let parent_hash = header.parent_hash().clone(); + self.lock_import_and_run(|operation| { + self.apply_block(operation, import_block, new_authorities) + }).map_err(|e| ConsensusErrorKind::ClientImport(e.to_string()).into()) + } - match self.backend.blockchain().status(BlockId::Hash(parent_hash))? { + /// Check block preconditions. + fn check_block( + &self, + hash: Block::Hash, + parent_hash: Block::Hash, + ) -> Result { + match self.backend.blockchain().status(BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))? + { blockchain::BlockStatus::InChain => {}, blockchain::BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), } - let import_headers = if post_digests.is_empty() { - PrePostHeader::Same(header) - } else { - let mut post_header = header.clone(); - for item in post_digests { - post_header.digest_mut().push(item); - } - PrePostHeader::Different(header, post_header) - }; - - let hash = import_headers.post().hash(); - let _import_lock = self.import_lock.lock(); - let height: u64 = import_headers.post().number().as_(); - *self.importing_block.write() = Some(hash); - - let result = self.execute_and_import_block( - origin, - hash, - import_headers, - justification, - body, - new_authorities, - finalized, - auxiliary, - ); + match self.backend.blockchain().status(BlockId::Hash(hash)) + .map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))? + { + blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain), + blockchain::BlockStatus::Unknown => {}, + } - *self.importing_block.write() = None; - telemetry!("block.import"; - "height" => height, - "best" => ?hash, - "origin" => ?origin - ); - result.map_err(|e| e.into()) + Ok(ImportResult::imported()) } } @@ -1091,14 +1410,14 @@ impl consensus::Authorities for Client Block: BlockT, { type Error = Error; - fn authorities(&self, at: &BlockId) -> Result, Self::Error> { + fn authorities(&self, at: &BlockId) -> Result>, Self::Error> { self.authorities_at(at).map_err(|e| e.into()) } } impl CurrentHeight for Client where B: backend::Backend, - E: CallExecutor + Clone, + E: CallExecutor, Block: BlockT, { type BlockNumber = ::Number; @@ -1109,7 +1428,7 @@ impl CurrentHeight for Client where impl BlockNumberToHash for Client where B: backend::Backend, - E: CallExecutor + Clone, + E: CallExecutor, Block: BlockT, { type BlockNumber = ::Number; @@ -1184,26 +1503,31 @@ impl backend::AuxStore for Client I: IntoIterator, D: IntoIterator, >(&self, insert: I, delete: D) -> error::Result<()> { - ::backend::AuxStore::insert_aux(&*self.backend, insert, delete) + // Import is locked here because we may have other block import + // operations that tries to set aux data. Note that for consensus + // layer, one can always use atomic operations to make sure + // import is only locked once. + self.lock_import_and_run(|operation| { + self.apply_aux(operation, insert, delete) + }) } /// Query auxiliary data from key-value store. fn get_aux(&self, key: &[u8]) -> error::Result>> { - ::backend::AuxStore::get_aux(&*self.backend, key) + crate::backend::AuxStore::get_aux(&*self.backend, key) } } #[cfg(test)] pub(crate) mod tests { use std::collections::HashMap; use super::*; - use keyring::Keyring; use primitives::twox_128; use runtime_primitives::traits::DigestItem as DigestItemT; use runtime_primitives::generic::DigestItem; - use test_client::{self, TestClient}; + use test_client::{self, TestClient, AccountKeyring, AuthorityKeyring}; use consensus::BlockOrigin; - use test_client::client::{backend::Backend as TestBackend, runtime_api::ApiExt}; + use test_client::client::backend::Backend as TestBackend; use test_client::BlockBuilderExt; - use test_client::runtime::{self, Block, Transfer, RuntimeApi, test_api::TestAPI}; + use test_client::runtime::{self, Block, Transfer, RuntimeApi, TestAPI}; /// Returns tuple, consisting of: /// 1) test client pre-filled with blocks changing balances; @@ -1216,10 +1540,10 @@ pub(crate) mod tests { ) { // prepare block structure let blocks_transfers = vec![ - vec![(Keyring::Alice, Keyring::Dave), (Keyring::Bob, Keyring::Dave)], - vec![(Keyring::Charlie, Keyring::Eve)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], + vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], vec![], - vec![(Keyring::Alice, Keyring::Dave)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave)], ]; // prepare client ang import blocks @@ -1230,8 +1554,8 @@ pub(crate) mod tests { let mut builder = remote_client.new_block().unwrap(); for (from, to) in block_transfers { builder.push_transfer(Transfer { - from: from.to_raw_public().into(), - to: to.to_raw_public().into(), + from: from.into(), + to: to.into(), amount: 1, nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), }).unwrap(); @@ -1246,12 +1570,12 @@ pub(crate) mod tests { } // prepare test cases - let alice = twox_128(&runtime::system::balance_of_key(Keyring::Alice.to_raw_public().into())).to_vec(); - let bob = twox_128(&runtime::system::balance_of_key(Keyring::Bob.to_raw_public().into())).to_vec(); - let charlie = twox_128(&runtime::system::balance_of_key(Keyring::Charlie.to_raw_public().into())).to_vec(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); - let eve = twox_128(&runtime::system::balance_of_key(Keyring::Eve.to_raw_public().into())).to_vec(); - let ferdie = twox_128(&runtime::system::balance_of_key(Keyring::Ferdie.to_raw_public().into())).to_vec(); + let alice = twox_128(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); + let bob = twox_128(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); + let charlie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let eve = twox_128(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); + let ferdie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); let test_cases = vec![ (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), (1, 3, alice.clone(), vec![(1, 0)]), @@ -1285,39 +1609,28 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 1000 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 0 ); } - #[test] - fn runtime_api_has_test_api() { - let client = test_client::new(); - - assert!( - client.runtime_api().has_api::>( - &BlockId::Number(client.info().unwrap().chain.best_number), - ).unwrap() - ); - } - #[test] fn authorities_call_works() { let client = test_client::new(); assert_eq!(client.info().unwrap().chain.best_number, 0); assert_eq!(client.authorities_at(&BlockId::Number(0)).unwrap(), vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into() + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Bob.into(), + AuthorityKeyring::Charlie.into() ]); } @@ -1339,8 +1652,8 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -1348,18 +1661,18 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); assert_eq!(client.info().unwrap().chain.best_number, 1); - assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap()); + assert!(client.state_at(&BlockId::Number(1)).unwrap().pairs() != client.state_at(&BlockId::Number(0)).unwrap().pairs()); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 958 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - &Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 42 ); @@ -1367,14 +1680,11 @@ pub(crate) mod tests { #[test] fn client_uses_authorities_from_blockchain_cache() { - let client = test_client::new(); - test_client::client::in_mem::cache_authorities_at( - client.backend().blockchain(), - Default::default(), - Some(vec![[1u8; 32].into()])); - assert_eq!(client.authorities_at( - &BlockId::Hash(Default::default())).unwrap(), - vec![[1u8; 32].into()]); + let client = test_client::new_light(); + let genesis_hash = client.header(&BlockId::Number(0)).unwrap().unwrap().hash(); + // authorities cache is first filled in genesis block + // => should be read from cache here (remote request will fail in this test) + assert!(!client.authorities_at(&BlockId::Hash(genesis_hash)).unwrap().is_empty()); } #[test] @@ -1384,15 +1694,15 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); assert!(builder.push_transfer(Transfer { - from: Keyring::Eve.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Eve.into(), + to: AccountKeyring::Alice.into(), amount: 42, nonce: 0, }).is_err()); @@ -1400,7 +1710,7 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); assert_eq!(client.info().unwrap().chain.best_number, 1); - assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap()); + assert!(client.state_at(&BlockId::Number(1)).unwrap().pairs() != client.state_at(&BlockId::Number(0)).unwrap().pairs()); assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) } @@ -1428,6 +1738,117 @@ pub(crate) mod tests { assert_eq!(None, client.best_containing(uninserted_block.hash().clone(), None).unwrap()); } + #[test] + fn uncles_with_only_ancestors() { + // block tree: + // G -> A1 -> A2 + let client = test_client::new(); + + // G -> A1 + let a1 = client.new_block().unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block().unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + let v: Vec = Vec::new(); + assert_eq!(v, client.uncles(a2.hash(), 3).unwrap()); + } + + #[test] + fn uncles_with_multiple_forks() { + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let client = test_client::new(); + + // G -> A1 + let a1 = client.new_block().unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.info().unwrap().chain.genesis_hash; + + let uncles1 = client.uncles(a4.hash(), 10).unwrap(); + assert_eq!(vec![b2.hash(), d2.hash()], uncles1); + + let uncles2 = client.uncles(a4.hash(), 0).unwrap(); + assert_eq!(0, uncles2.len()); + + let uncles3 = client.uncles(a1.hash(), 10).unwrap(); + assert_eq!(0, uncles3.len()); + + let uncles4 = client.uncles(genesis_hash, 10).unwrap(); + assert_eq!(0, uncles4.len()); + + let uncles5 = client.uncles(d2.hash(), 10).unwrap(); + assert_eq!(vec![a2.hash(), b2.hash()], uncles5); + + let uncles6 = client.uncles(b3.hash(), 1).unwrap(); + assert_eq!(vec![c3.hash()], uncles6); + } + #[test] fn best_containing_with_single_chain_3_blocks() { // block tree: @@ -1488,8 +1909,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -1508,8 +1929,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -1520,8 +1941,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -1689,9 +2110,8 @@ pub(crate) mod tests { let (client, _, test_cases) = prepare_client_with_key_changes(); for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let begin = client.block_hash(begin).unwrap().unwrap(); let end = client.block_hash(end).unwrap().unwrap(); - let actual_result = client.key_changes(begin, end, &key).unwrap(); + let actual_result = client.key_changes(begin, BlockId::Hash(end), &StorageKey(key)).unwrap(); match actual_result == expected_result { true => (), false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", diff --git a/core/client/src/error.rs b/core/client/src/error.rs index 2a793e804945f7bd7d99c84a3e3b99bbc2af9ca0..edc179ec6a701b6a3db48d44463c05f487f09601 100644 --- a/core/client/src/error.rs +++ b/core/client/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,12 +16,16 @@ //! Substrate client possible errors. +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/substrate/issues/1547 +#![allow(deprecated)] #![allow(missing_docs)] use std; use state_machine; use runtime_primitives::ApplyError; use consensus; +use error_chain::*; error_chain! { links { @@ -112,6 +116,12 @@ error_chain! { display("Error decoding call result of {}", method) } + /// Error converting a parameter between runtime and node. + RuntimeParamConversion(param: &'static str) { + description("Error converting parameter between runtime and node") + display("Error converting `{}` between runtime and node", param) + } + /// Changes tries are not supported. ChangesTriesNotSupported { description("changes tries are not supported"), @@ -144,7 +154,6 @@ error_chain! { } } -// TODO [ToDr] Temporary, state_machine::Error should be a regular error not Box. impl From> for Error { fn from(e: Box) -> Self { ErrorKind::Execution(e).into() diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs index d7d398a4e908b74aec1f1f75510d5a0e771b288e..9ee003368524e42830556a4286ef2afcde010647 100644 --- a/core/client/src/genesis.rs +++ b/core/client/src/genesis.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -40,21 +40,23 @@ pub fn construct_genesis_block< #[cfg(test)] mod tests { use super::*; - use codec::{Encode, Decode, Joiner}; - use keyring::Keyring; - use executor::NativeExecutionDispatch; - use state_machine::{execute, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage}; + use parity_codec::{Encode, Decode, Joiner}; + use executor::{NativeExecutionDispatch, native_executor_instance}; + use state_machine::{self, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage}; use state_machine::backend::InMemory; - use test_client; - use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; - use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}; + use test_client::{ + runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}, + runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}, + AccountKeyring, AuthorityKeyring + }; use runtime_primitives::traits::BlakeTwo256; - use primitives::{Blake2Hasher, ed25519::{Public, Pair}}; + use primitives::Blake2Hasher; + use hex::*; native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); - fn executor() -> ::executor::NativeExecutor { - NativeExecutionDispatch::new() + fn executor() -> executor::NativeExecutor { + NativeExecutionDispatch::new(None) } fn construct_block( @@ -67,15 +69,14 @@ mod tests { use trie::ordered_trie_root; let transactions = txs.into_iter().map(|tx| { - let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.to_fixed_bytes())).unwrap()) + let signature = AccountKeyring::from_public(&tx.from).unwrap() .sign(&tx.encode()).into(); - Extrinsic { transfer: tx, signature } + Extrinsic::Transfer(tx, signature) }).collect::>(); let extrinsics_root = ordered_trie_root::(transactions.iter().map(Encode::encode)).into(); - println!("root before: {:?}", extrinsics_root); let mut header = Header { parent_hash, number, @@ -86,39 +87,41 @@ mod tests { let hash = header.hash(); let mut overlay = OverlayedChanges::default(); - execute( + state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, &executor(), "Core_initialise_block", &header.encode(), - ExecutionStrategy::NativeWhenPossible, + ).execute( + ExecutionStrategy::NativeElseWasm, ).unwrap(); for tx in transactions.iter() { - execute( + state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, &executor(), "BlockBuilder_apply_extrinsic", &tx.encode(), - ExecutionStrategy::NativeWhenPossible, + ).execute( + ExecutionStrategy::NativeElseWasm, ).unwrap(); } - let (ret_data, _, _) = execute( + let (ret_data, _, _) = state_machine::new( backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, &executor(), "BlockBuilder_finalise_block", &[], - ExecutionStrategy::NativeWhenPossible, + ).execute( + ExecutionStrategy::NativeElseWasm, ).unwrap(); header = Header::decode(&mut &ret_data[..]).unwrap(); - println!("root after: {:?}", header.extrinsics_root); (vec![].and(&Block { header, extrinsics: transactions }), hash) } @@ -130,8 +133,8 @@ mod tests { genesis_hash, hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), vec![Transfer { - from: Keyring::One.to_raw_public().into(), - to: Keyring::Two.to_raw_public().into(), + from: AccountKeyring::One.into(), + to: AccountKeyring::Two.into(), amount: 69, nonce: 0, }] @@ -140,8 +143,10 @@ mod tests { #[test] fn construct_genesis_should_work_with_native() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -152,21 +157,24 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = execute( + let _ = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, &executor(), "Core_execute_block", &b1data, - ExecutionStrategy::NativeWhenPossible, + ).execute( + ExecutionStrategy::NativeElseWasm, ).unwrap(); } #[test] fn construct_genesis_should_work_with_wasm() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -177,22 +185,24 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = execute( + let _ = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, &executor(), "Core_execute_block", &b1data, + ).execute( ExecutionStrategy::AlwaysWasm, ).unwrap(); } #[test] - #[should_panic] fn construct_genesis_with_bad_transaction_should_panic() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 68 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 68 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -203,14 +213,16 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = execute( + let r = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, - &Executor::new(), + &Executor::new(None), "Core_execute_block", &b1data, - ExecutionStrategy::NativeWhenPossible, - ).unwrap(); + ).execute( + ExecutionStrategy::NativeElseWasm, + ); + assert!(r.is_err()); } } diff --git a/core/client/src/in_mem.rs b/core/client/src/in_mem.rs index 1bf50d715d62aa309723f2c03d3530d8096a3655..fc95e9664b4e4480ba82403a1ffb90ed76660df4 100644 --- a/core/client/src/in_mem.rs +++ b/core/client/src/in_mem.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,22 +19,23 @@ use std::collections::HashMap; use std::sync::Arc; use parking_lot::RwLock; -use error; -use backend::{self, NewBlockState}; -use light; -use primitives::{AuthorityId, storage::well_known_keys}; +use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, - NumberFor, As, Digest, DigestItem}; -use runtime_primitives::{Justification, StorageMap, ChildrenStorageMap}; -use blockchain::{self, BlockStatus, HeaderBackend}; + NumberFor, As, Digest, DigestItem, AuthorityIdFor}; +use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay}; use state_machine::backend::{Backend as StateBackend, InMemory, Consolidate}; -use state_machine::InMemoryChangesTrieStorage; +use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId}; use hash_db::Hasher; use heapsize::HeapSizeOf; -use leaves::LeafSet; use trie::MemoryDB; +use crate::error; +use crate::backend::{self, NewBlockState}; +use crate::light; +use crate::leaves::LeafSet; +use crate::blockchain::{self, BlockStatus, HeaderBackend}; + struct PendingBlock { block: StoredBlock, state: NewBlockState, @@ -108,7 +109,7 @@ pub struct Blockchain { struct Cache { storage: Arc>>, - authorities_at: RwLock>>>, + authorities_at: RwLock>>>>, } impl Clone for Blockchain { @@ -166,62 +167,35 @@ impl Blockchain { justification: Option, body: Option::Extrinsic>>, new_state: NewBlockState, - ) -> ::error::Result<()> { + ) -> crate::error::Result<()> { let number = header.number().clone(); - let best_tree_route = match new_state.is_best() { - false => None, - true => { - let best_hash = self.storage.read().best_hash; - if &best_hash == header.parent_hash() { - None - } else { - let route = ::blockchain::tree_route( - self, - BlockId::Hash(best_hash), - BlockId::Hash(*header.parent_hash()), - )?; - Some(route) - } - } - }; - - let mut storage = self.storage.write(); - - storage.leaves.import(hash.clone(), number.clone(), header.parent_hash().clone()); - if new_state.is_best() { - if let Some(tree_route) = best_tree_route { - // apply retraction and enaction when reorganizing up to parent hash - let enacted = tree_route.enacted(); - - for entry in enacted { - storage.hashes.insert(entry.number, entry.hash); - } - - for entry in tree_route.retracted().iter().skip(enacted.len()) { - storage.hashes.remove(&entry.number); - } - } - - storage.best_hash = hash.clone(); - storage.best_number = number.clone(); - storage.hashes.insert(number, hash.clone()); + self.apply_head(&header)?; } - storage.blocks.insert(hash.clone(), StoredBlock::new(header, body, justification)); + { + let mut storage = self.storage.write(); + storage.leaves.import(hash.clone(), number.clone(), header.parent_hash().clone()); + storage.blocks.insert(hash.clone(), StoredBlock::new(header, body, justification)); - if let NewBlockState::Final = new_state { - storage.finalized_hash = hash; - storage.finalized_number = number.clone(); - } + if let NewBlockState::Final = new_state { + storage.finalized_hash = hash; + storage.finalized_number = number.clone(); + } - if number == Zero::zero() { - storage.genesis_hash = hash; + if number == Zero::zero() { + storage.genesis_hash = hash; + } } Ok(()) } + /// Get total number of blocks. + pub fn blocks_count(&self) -> usize { + self.storage.read().blocks.len() + } + /// Compare this blockchain with another in-mem blockchain pub fn equals_to(&self, other: &Self) -> bool { self.canon_equals_to(other) && self.storage.read().blocks == other.storage.read().blocks @@ -242,6 +216,58 @@ impl Blockchain { self.storage.write().header_cht_roots.insert(block, cht_root); } + /// Set an existing block as head. + pub fn set_head(&self, id: BlockId) -> error::Result<()> { + let header = match self.header(id)? { + Some(h) => h, + None => return Err(error::ErrorKind::UnknownBlock(format!("{}", id)).into()), + }; + + self.apply_head(&header) + } + + fn apply_head(&self, header: &::Header) -> error::Result<()> { + let hash = header.hash(); + let number = header.number(); + + // Note: this may lock storage, so it must happen before obtaining storage + // write lock. + let best_tree_route = { + let best_hash = self.storage.read().best_hash; + if &best_hash == header.parent_hash() { + None + } else { + let route = crate::blockchain::tree_route( + self, + BlockId::Hash(best_hash), + BlockId::Hash(*header.parent_hash()), + )?; + Some(route) + } + }; + + let mut storage = self.storage.write(); + + if let Some(tree_route) = best_tree_route { + // apply retraction and enaction when reorganizing up to parent hash + let enacted = tree_route.enacted(); + + for entry in enacted { + storage.hashes.insert(entry.number, entry.hash); + } + + for entry in tree_route.retracted().iter().skip(enacted.len()) { + storage.hashes.remove(&entry.number); + } + } + + storage.best_hash = hash.clone(); + storage.best_number = number.clone(); + storage.hashes.insert(number.clone(), hash.clone()); + + Ok(()) + } + fn finalize_header(&self, id: BlockId, justification: Option) -> error::Result<()> { let hash = match self.header(id)? { Some(h) => h.hash(), @@ -336,6 +362,10 @@ impl blockchain::Backend for Blockchain { fn leaves(&self) -> error::Result> { Ok(self.storage.read().leaves.hashes()) } + + fn children(&self, _parent_hash: Block::Hash) -> error::Result> { + unimplemented!() + } } impl backend::AuxStore for Blockchain { @@ -368,7 +398,7 @@ impl light::blockchain::Storage for Blockchain fn import_header( &self, header: Block::Header, - authorities: Option>, + authorities: Option>>, state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> error::Result<()> { @@ -383,6 +413,10 @@ impl light::blockchain::Storage for Blockchain Ok(()) } + fn set_head(&self, id: BlockId) -> error::Result<()> { + Blockchain::set_head(self, id) + } + fn last_finalized(&self) -> error::Result { Ok(self.storage.read().finalized_hash.clone()) } @@ -409,11 +443,13 @@ impl light::blockchain::Storage for Blockchain /// In-memory operation. pub struct BlockImportOperation { pending_block: Option>, - pending_authorities: Option>, + pending_authorities: Option>>, old_state: InMemory, new_state: Option>, changes_trie_update: Option>, - aux: Option, Option>)>>, + aux: Vec<(Vec, Option>)>, + finalized_blocks: Vec<(BlockId, Option)>, + set_head: Option>, } impl backend::BlockImportOperation for BlockImportOperation @@ -444,11 +480,11 @@ where Ok(()) } - fn update_authorities(&mut self, authorities: Vec) { + fn update_authorities(&mut self, authorities: Vec>) { self.pending_authorities = Some(authorities); } - fn update_storage(&mut self, update: as StateBackend>::Transaction) -> error::Result<()> { + fn update_db_storage(&mut self, update: as StateBackend>::Transaction) -> error::Result<()> { self.new_state = Some(self.old_state.update(update)); Ok(()) } @@ -458,18 +494,12 @@ where Ok(()) } - fn reset_storage(&mut self, mut top: StorageMap, children: ChildrenStorageMap) -> error::Result { - if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { - return Err(error::ErrorKind::GenesisInvalid.into()); - } + fn reset_storage(&mut self, mut top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result { + check_genesis_storage(&top, &children)?; let mut transaction: Vec<(Option>, Vec, Option>)> = Default::default(); for (child_key, child_map) in children { - if !well_known_keys::is_child_storage_key(&child_key) { - return Err(error::ErrorKind::GenesisInvalid.into()); - } - let (root, is_default, update) = self.old_state.child_storage_root(&child_key, child_map.into_iter().map(|(k, v)| (k, Some(v)))); transaction.consolidate(update); @@ -485,10 +515,25 @@ where Ok(root) } - fn set_aux(&mut self, ops: I) -> error::Result<()> + fn insert_aux(&mut self, ops: I) -> error::Result<()> where I: IntoIterator, Option>)> { - self.aux = Some(ops.into_iter().collect()); + self.aux.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage(&mut self, _update: Vec<(Vec, Option>)>) -> error::Result<()> { + Ok(()) + } + + fn mark_finalized(&mut self, block: BlockId, justification: Option) -> error::Result<()> { + self.finalized_blocks.push((block, justification)); + Ok(()) + } + + fn mark_head(&mut self, block: BlockId) -> error::Result<()> { + assert!(self.pending_block.is_none(), "Only one set block per operation is allowed"); + self.set_head = Some(block); Ok(()) } } @@ -501,7 +546,7 @@ where H::Out: HeapSizeOf + Ord, { states: RwLock>>, - changes_trie_storage: InMemoryChangesTrieStorage, + changes_trie_storage: ChangesTrieStorage, blockchain: Blockchain, } @@ -515,7 +560,7 @@ where pub fn new() -> Backend { Backend { states: RwLock::new(HashMap::new()), - changes_trie_storage: InMemoryChangesTrieStorage::new(), + changes_trie_storage: ChangesTrieStorage(InMemoryChangesTrieStorage::new()), blockchain: Blockchain::new(), } } @@ -551,25 +596,34 @@ where type BlockImportOperation = BlockImportOperation; type Blockchain = Blockchain; type State = InMemory; - type ChangesTrieStorage = InMemoryChangesTrieStorage; - - fn begin_operation(&self, block: BlockId) -> error::Result { - let state = match block { - BlockId::Hash(ref h) if h.clone() == Default::default() => Self::State::default(), - _ => self.state_at(block)?, - }; + type ChangesTrieStorage = ChangesTrieStorage; + fn begin_operation(&self) -> error::Result { + let old_state = self.state_at(BlockId::Hash(Default::default()))?; Ok(BlockImportOperation { pending_block: None, pending_authorities: None, - old_state: state, + old_state, new_state: None, changes_trie_update: None, - aux: None, + aux: Default::default(), + finalized_blocks: Default::default(), + set_head: None, }) } + fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> error::Result<()> { + operation.old_state = self.state_at(block)?; + Ok(()) + } + fn commit_operation(&self, operation: Self::BlockImportOperation) -> error::Result<()> { + if !operation.finalized_blocks.is_empty() { + for (block, justification) in operation.finalized_blocks { + self.blockchain.finalize_header(block, justification)?; + } + } + if let Some(pending_block) = operation.pending_block { let old_state = &operation.old_state; let (header, body, justification) = pending_block.block.into_inner(); @@ -583,7 +637,7 @@ where if let Some(changes_trie_root) = changes_trie_root { if let Some(changes_trie_update) = operation.changes_trie_update { let changes_trie_root: H::Out = changes_trie_root.into(); - self.changes_trie_storage.insert(header.number().as_(), changes_trie_root, changes_trie_update); + self.changes_trie_storage.0.insert(header.number().as_(), changes_trie_root, changes_trie_update); } } @@ -594,9 +648,14 @@ where } } - if let Some(ops) = operation.aux { - self.blockchain.write_aux(ops); + if !operation.aux.is_empty() { + self.blockchain.write_aux(operation.aux); } + + if let Some(set_head) = operation.set_head { + self.blockchain.set_head(set_head)?; + } + Ok(()) } @@ -613,6 +672,13 @@ where } fn state_at(&self, block: BlockId) -> error::Result { + match block { + BlockId::Hash(h) if h == Default::default() => { + return Ok(Self::State::default()); + }, + _ => {}, + } + match self.blockchain.id(block).and_then(|id| self.states.read().get(&id).cloned()) { Some(state) => Ok(state), None => Err(error::ErrorKind::UnknownBlock(format!("{}", block)).into()), @@ -631,14 +697,27 @@ where H::Out: HeapSizeOf + Ord, {} +impl backend::RemoteBackend for Backend +where + Block: BlockT, + H: Hasher, + H::Out: HeapSizeOf + Ord, +{ + fn is_local_state_available(&self, block: &BlockId) -> bool { + self.blockchain.expect_block_number_from_id(block) + .map(|num| num.is_zero()) + .unwrap_or(false) + } +} + impl Cache { - fn insert(&self, at: Block::Hash, authorities: Option>) { + fn insert(&self, at: Block::Hash, authorities: Option>>) { self.authorities_at.write().insert(at, authorities); } } impl blockchain::Cache for Cache { - fn authorities_at(&self, block: BlockId) -> Option> { + fn authorities_at(&self, block: BlockId) -> Option>> { let hash = match block { BlockId::Hash(hash) => hash, BlockId::Number(number) => self.storage.read().hashes.get(&number).cloned()?, @@ -648,15 +727,48 @@ impl blockchain::Cache for Cache { } } +/// Prunable in-memory changes trie storage. +pub struct ChangesTrieStorage(InMemoryChangesTrieStorage) where H::Out: HeapSizeOf; +impl backend::PrunableStateChangesTrieStorage for ChangesTrieStorage where H::Out: HeapSizeOf { + fn oldest_changes_trie_block(&self, _config: &ChangesTrieConfiguration, _best_finalized: u64) -> u64 { + 0 + } +} + +impl state_machine::ChangesTrieRootsStorage for ChangesTrieStorage where H::Out: HeapSizeOf { + fn root(&self, anchor: &ChangesTrieAnchorBlockId, block: u64) -> Result, String> { + self.0.root(anchor, block) + } +} + +impl state_machine::ChangesTrieStorage for ChangesTrieStorage where H::Out: HeapSizeOf { + fn get(&self, key: &H::Out) -> Result, String> { + self.0.get(key) + } +} + /// Insert authorities entry into in-memory blockchain cache. Extracted as a separate function to use it in tests. pub fn cache_authorities_at( blockchain: &Blockchain, at: Block::Hash, - authorities: Option> + authorities: Option>> ) { blockchain.cache.insert(at, authorities); } +/// Check that genesis storage is valid. +pub fn check_genesis_storage(top: &StorageOverlay, children: &ChildrenStorageOverlay) -> error::Result<()> { + if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { + return Err(error::ErrorKind::GenesisInvalid.into()); + } + + if children.keys().any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) { + return Err(error::ErrorKind::GenesisInvalid.into()); + } + + Ok(()) +} + #[cfg(test)] mod tests { use std::sync::Arc; diff --git a/core/client/src/leaves.rs b/core/client/src/leaves.rs index a41f91933c07680e0bb100623c7e945cb4df143d..cc906d59a4bb1882211df3de855afe3d683aad7c 100644 --- a/core/client/src/leaves.rs +++ b/core/client/src/leaves.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,72 +14,71 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::collections::BTreeSet; -use std::cmp::{Ord, Ordering}; +//! Helper for managing the set of available leaves in the chain for DB implementations. + +use std::collections::BTreeMap; +use std::cmp::Reverse; use kvdb::{KeyValueDB, DBTransaction}; use runtime_primitives::traits::SimpleArithmetic; -use codec::{Encode, Decode}; -use error; +use parity_codec::{Encode, Decode}; +use crate::error; -/// helper wrapper type to keep a list of block hashes ordered -/// by `number` descending in a `BTreeSet` which allows faster and simpler -/// insertion and removal than keeping them in a list. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] struct LeafSetItem { hash: H, - number: N, + number: Reverse, } -impl Ord for LeafSetItem where N: Ord { - fn cmp(&self, other: &Self) -> Ordering { - // reverse (descending) order - other.number.cmp(&self.number) - } +/// A displaced leaf after import. +#[must_use = "Displaced items from the leaf set must be handled."] +pub struct ImportDisplaced { + new_hash: H, + displaced: LeafSetItem, } -impl PartialOrd for LeafSetItem where N: PartialOrd { - fn partial_cmp(&self, other: &Self) -> Option { - // reverse (descending) order - other.number.partial_cmp(&self.number) - } +/// Displaced leaves after finalization. +#[must_use = "Displaced items from the leaf set must be handled."] +pub struct FinalizationDisplaced { + leaves: BTreeMap, Vec>, } -impl PartialEq for LeafSetItem where N: PartialEq { - fn eq(&self, other: &LeafSetItem) -> bool { - self.number == other.number +impl FinalizationDisplaced { + /// Merge with another. This should only be used for displaced items that + /// are produced within one transaction of each other. + pub fn merge(&mut self, mut other: Self) { + // this will ignore keys that are in duplicate, however + // if these are actually produced correctly via the leaf-set within + // one transaction, then there will be no overlap in the keys. + self.leaves.append(&mut other.leaves); } } -impl Eq for LeafSetItem where N: PartialEq {} - -/// A displaced leaf after import. -pub struct DisplacedLeaf { - new_hash: H, - displaced: LeafSetItem, -} - /// list of leaf hashes ordered by number (descending). /// stored in memory for fast access. /// this allows very fast checking and modification of active leaves. #[derive(Debug, Clone, PartialEq, Eq)] pub struct LeafSet { - storage: BTreeSet>, + storage: BTreeMap, Vec>, + pending_added: Vec>, + pending_removed: Vec, } impl LeafSet where - H: Clone + Decode + Encode, - N: Clone + SimpleArithmetic + Decode + Encode, + H: Clone + PartialEq + Decode + Encode, + N: std::fmt::Debug + Clone + SimpleArithmetic + Decode + Encode, { /// Construct a new, blank leaf set. pub fn new() -> Self { Self { - storage: BTreeSet::new() + storage: BTreeMap::new(), + pending_added: Vec::new(), + pending_removed: Vec::new(), } } /// Read the leaf list from the DB, using given prefix for keys. pub fn read_from_db(db: &KeyValueDB, column: Option, prefix: &[u8]) -> error::Result { - let mut storage = BTreeSet::new(); + let mut storage = BTreeMap::new(); for (key, value) in db.iter_from_prefix(column, prefix) { if !key.starts_with(prefix) { break } @@ -92,25 +91,30 @@ impl LeafSet where Some(number) => number, None => return Err(error::ErrorKind::Backend("Error decoding number".into()).into()), }; - storage.insert(LeafSetItem { hash, number }); + storage.entry(Reverse(number)).or_insert_with(Vec::new).push(hash); } - Ok(Self { storage }) + Ok(Self { + storage, + pending_added: Vec::new(), + pending_removed: Vec::new(), + }) } /// update the leaf list on import. returns a displaced leaf if there was one. - pub fn import(&mut self, hash: H, number: N, parent_hash: H) -> Option> { + pub fn import(&mut self, hash: H, number: N, parent_hash: H) -> Option> { // avoid underflow for genesis. let displaced = if number != N::zero() { - let displaced = LeafSetItem { - hash: parent_hash, - number: number.clone() - N::one(), - }; - let was_displaced = self.storage.remove(&displaced); + let new_number = Reverse(number.clone() - N::one()); + let was_displaced = self.remove_leaf(&new_number, &parent_hash); if was_displaced { - Some(DisplacedLeaf { + self.pending_removed.push(parent_hash.clone()); + Some(ImportDisplaced { new_hash: hash.clone(), - displaced, + displaced: LeafSetItem { + hash: parent_hash, + number: new_number, + }, }) } else { None @@ -119,42 +123,130 @@ impl LeafSet where None }; - self.storage.insert(LeafSetItem { hash, number }); + self.insert_leaf(Reverse(number.clone()), hash.clone()); + self.pending_added.push(LeafSetItem { hash, number: Reverse(number) }); displaced } - /// Undo an import operation, with a displaced leaf. - pub fn undo(&mut self, displaced: DisplacedLeaf) { - let new_number = displaced.displaced.number.clone() + N::one(); - self.storage.remove(&LeafSetItem { hash: displaced.new_hash, number: new_number }); - self.storage.insert(displaced.displaced); + /// Note a block height finalized, displacing all leaves with number less than the finalized block's. + /// + /// Although it would be more technically correct to also prune out leaves at the + /// same number as the finalized block, but with different hashes, the current behavior + /// is simpler and our assumptions about how finalization works means that those leaves + /// will be pruned soon afterwards anyway. + pub fn finalize_height(&mut self, number: N) -> FinalizationDisplaced { + let boundary = if number == N::zero() { + return FinalizationDisplaced { leaves: BTreeMap::new() }; + } else { + number - N::one() + }; + + let below_boundary = self.storage.split_off(&Reverse(boundary)); + self.pending_removed.extend(below_boundary.values().flat_map(|h| h.iter()).cloned()); + FinalizationDisplaced { + leaves: below_boundary, + } + } + + /// Undo all pending operations. + /// + /// This returns an `Undo` struct, where any + /// `Displaced` objects that have returned by previous method calls + /// should be passed to via the appropriate methods. Otherwise, + /// the on-disk state may get out of sync with in-memory state. + pub fn undo(&mut self) -> Undo { + Undo { inner: self } } /// currently since revert only affects the canonical chain /// we assume that parent has no further children /// and we add it as leaf again pub fn revert(&mut self, hash: H, number: N, parent_hash: H) { - self.storage.insert(LeafSetItem { - hash: parent_hash, - number: number.clone() - N::one(), - }); - self.storage.remove(&LeafSetItem { hash, number }); + self.insert_leaf(Reverse(number.clone() - N::one()), parent_hash); + self.remove_leaf(&Reverse(number), &hash); } /// returns an iterator over all hashes in the leaf set /// ordered by their block number descending. pub fn hashes(&self) -> Vec { - self.storage.iter().map(|item| item.hash.clone()).collect() + self.storage.iter().flat_map(|(_, hashes)| hashes.iter()).cloned().collect() } /// Write the leaf list to the database transaction. - pub fn prepare_transaction(&self, tx: &mut DBTransaction, column: Option, prefix: &[u8]) { + pub fn prepare_transaction(&mut self, tx: &mut DBTransaction, column: Option, prefix: &[u8]) { let mut buf = prefix.to_vec(); - for &LeafSetItem { ref hash, ref number } in &self.storage { + for LeafSetItem { hash, number } in self.pending_added.drain(..) { hash.using_encoded(|s| buf.extend(s)); - tx.put_vec(column, &buf[..], number.encode()); + tx.put_vec(column, &buf[..], number.0.encode()); buf.truncate(prefix.len()); // reuse allocation. } + for hash in self.pending_removed.drain(..) { + hash.using_encoded(|s| buf.extend(s)); + tx.delete(column, &buf[..]); + buf.truncate(prefix.len()); // reuse allocation. + } + } + + #[cfg(test)] + fn contains(&self, number: N, hash: H) -> bool { + self.storage.get(&Reverse(number)).map_or(false, |hashes| hashes.contains(&hash)) + } + + fn insert_leaf(&mut self, number: Reverse, hash: H) { + self.storage.entry(number).or_insert_with(Vec::new).push(hash); + } + + // returns true if this leaf was contained, false otherwise. + fn remove_leaf(&mut self, number: &Reverse, hash: &H) -> bool { + let mut empty = false; + let removed = self.storage.get_mut(number).map_or(false, |leaves| { + let mut found = false; + leaves.retain(|h| if h == hash { + found = true; + false + } else { + true + }); + + if leaves.is_empty() { empty = true } + + found + }); + + if removed && empty { + self.storage.remove(number); + } + + removed + } +} + +/// Helper for undoing operations. +pub struct Undo<'a, H: 'a, N: 'a> { + inner: &'a mut LeafSet, +} + +impl<'a, H: 'a, N: 'a> Undo<'a, H, N> where + H: Clone + PartialEq + Decode + Encode, + N: std::fmt::Debug + Clone + SimpleArithmetic + Decode + Encode, +{ + /// Undo an imported block by providing the displaced leaf. + pub fn undo_import(&mut self, displaced: ImportDisplaced) { + let new_number = Reverse(displaced.displaced.number.0.clone() + N::one()); + self.inner.remove_leaf(&new_number, &displaced.new_hash); + self.inner.insert_leaf(new_number, displaced.displaced.hash); + } + + /// Undo a finalization operation by providing the displaced leaves. + pub fn undo_finalization(&mut self, mut displaced: FinalizationDisplaced) { + self.inner.storage.append(&mut displaced.leaves); + } +} + +impl<'a, H: 'a, N: 'a> Drop for Undo<'a, H, N> { + fn drop(&mut self) { + self.inner.pending_added.clear(); + self.inner.pending_removed.clear(); } } @@ -171,15 +263,15 @@ mod tests { set.import(2_1, 2, 1_1); set.import(3_1, 3, 2_1); - assert!(set.storage.contains(&LeafSetItem { hash: 3_1, number: 3 })); - assert!(!set.storage.contains(&LeafSetItem { hash: 2_1, number: 2 })); - assert!(!set.storage.contains(&LeafSetItem { hash: 1_1, number: 1 })); - assert!(!set.storage.contains(&LeafSetItem { hash: 0, number: 0 })); + assert!(set.contains(3, 3_1)); + assert!(!set.contains(2, 2_1)); + assert!(!set.contains(1, 1_1)); + assert!(!set.contains(0, 0)); set.import(2_2, 2, 1_1); - assert!(set.storage.contains(&LeafSetItem { hash: 3_1, number: 3 })); - assert!(set.storage.contains(&LeafSetItem { hash: 2_2, number: 2 })); + assert!(set.contains(3, 3_1)); + assert!(set.contains(2, 2_2)); } #[test] @@ -202,4 +294,63 @@ mod tests { let set2 = LeafSet::read_from_db(&db, None, PREFIX).unwrap(); assert_eq!(set, set2); } + + #[test] + fn two_leaves_same_height_can_be_included() { + let mut set = LeafSet::new(); + + set.import(1_1u32, 10u32,0u32); + set.import(1_2, 10, 0); + + assert!(set.storage.contains_key(&Reverse(10))); + assert!(set.contains(10, 1_1)); + assert!(set.contains(10, 1_2)); + assert!(!set.contains(10, 1_3)); + } + + #[test] + fn finalization_consistent_with_disk() { + const PREFIX: &[u8] = b"prefix"; + let db = ::kvdb_memorydb::create(0); + + let mut set = LeafSet::new(); + set.import(10_1u32, 10u32, 0u32); + set.import(11_1, 11, 10_2); + set.import(11_2, 11, 10_2); + set.import(12_1, 12, 11_123); + + assert!(set.contains(10, 10_1)); + + let mut tx = DBTransaction::new(); + set.prepare_transaction(&mut tx, None, PREFIX); + db.write(tx).unwrap(); + + let _ = set.finalize_height(11); + let mut tx = DBTransaction::new(); + set.prepare_transaction(&mut tx, None, PREFIX); + db.write(tx).unwrap(); + + assert!(set.contains(11, 11_1)); + assert!(set.contains(11, 11_2)); + assert!(set.contains(12, 12_1)); + assert!(!set.contains(10, 10_1)); + + let set2 = LeafSet::read_from_db(&db, None, PREFIX).unwrap(); + assert_eq!(set, set2); + } + + #[test] + fn undo_finalization() { + let mut set = LeafSet::new(); + set.import(10_1u32, 10u32, 0u32); + set.import(11_1, 11, 10_2); + set.import(11_2, 11, 10_2); + set.import(12_1, 12, 11_123); + + let displaced = set.finalize_height(11); + assert!(!set.contains(10, 10_1)); + + set.undo().undo_finalization(displaced); + assert!(set.contains(10, 10_1)); + } } diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index fb07c130b25ff104ddcab987cfc51bcbc51aa6df..d2da243d14a4db3980bcc91c200deb80ba0aed0e 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,59 +20,6 @@ #![warn(missing_docs)] #![recursion_limit="128"] -#[cfg(feature = "std")] -extern crate substrate_trie as trie; -extern crate parity_codec as codec; -extern crate substrate_primitives as primitives; -extern crate sr_primitives as runtime_primitives; -#[cfg(feature = "std")] -extern crate substrate_state_machine as state_machine; -#[cfg(feature = "std")] -extern crate substrate_consensus_common as consensus; -extern crate sr_version as runtime_version; -extern crate sr_std as rstd; -#[macro_use] -extern crate sr_api_macros; -#[cfg(test)] -extern crate substrate_keyring as keyring; -#[cfg(test)] -extern crate substrate_test_client as test_client; -#[cfg(feature = "std")] -#[macro_use] -extern crate substrate_telemetry; -#[cfg(feature = "std")] -#[macro_use] -extern crate slog; // needed until we can reexport `slog_info` from `substrate_telemetry` - -#[cfg(feature = "std")] -extern crate fnv; -#[cfg(feature = "std")] -extern crate futures; -#[cfg(feature = "std")] -extern crate parking_lot; -#[cfg(feature = "std")] -extern crate hash_db; -#[cfg(feature = "std")] -extern crate heapsize; -#[cfg(feature = "std")] -extern crate kvdb; - -#[cfg(feature = "std")] -#[macro_use] -extern crate error_chain; -#[cfg(feature = "std")] -#[macro_use] -extern crate log; -#[cfg(feature = "std")] -#[cfg_attr(test, macro_use)] -extern crate substrate_executor as executor; -#[cfg(test)] -#[macro_use] -extern crate hex_literal; -#[cfg(feature = "std")] -#[cfg(test)] -extern crate kvdb_memorydb; - #[macro_use] pub mod runtime_api; #[cfg(feature = "std")] @@ -91,7 +38,9 @@ pub mod block_builder; #[cfg(feature = "std")] pub mod light; #[cfg(feature = "std")] -mod leaves; +pub mod leaves; +#[cfg(feature = "std")] +pub mod children; #[cfg(feature = "std")] mod call_executor; #[cfg(feature = "std")] @@ -99,23 +48,24 @@ mod client; #[cfg(feature = "std")] mod notifications; + #[cfg(feature = "std")] -pub use blockchain::Info as ChainInfo; +pub use crate::blockchain::Info as ChainInfo; #[cfg(feature = "std")] -pub use call_executor::{CallResult, CallExecutor, LocalCallExecutor}; +pub use crate::call_executor::{CallExecutor, LocalCallExecutor}; #[cfg(feature = "std")] -pub use client::{ +pub use crate::client::{ new_with_backend, new_in_mem, BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents, - BlockImportNotification, Client, ClientInfo, ChainHead, + BlockImportNotification, Client, ClientInfo, ChainHead, ExecutionStrategies, }; #[cfg(feature = "std")] -pub use notifications::{StorageEventStream, StorageChangeSet}; +pub use crate::notifications::{StorageEventStream, StorageChangeSet}; #[cfg(feature = "std")] pub use state_machine::ExecutionStrategy; #[cfg(feature = "std")] -pub use leaves::LeafSet; +pub use crate::leaves::LeafSet; #[doc(inline)] pub use sr_api_macros::{decl_runtime_apis, impl_runtime_apis}; diff --git a/core/client/src/light/backend.rs b/core/client/src/light/backend.rs index 185b7cfa0697175cb9a577a3be4e1f23eae1599f..a00d42e67394f239023491fa3a4888c12935cc39 100644 --- a/core/client/src/light/backend.rs +++ b/core/client/src/light/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,36 +17,41 @@ //! Light client backend. Only stores headers and justifications of blocks. //! Everything else is requested from full nodes on demand. +use std::collections::HashMap; use std::sync::{Arc, Weak}; use futures::{Future, IntoFuture}; use parking_lot::RwLock; -use primitives::AuthorityId; -use runtime_primitives::{generic::BlockId, Justification, StorageMap, ChildrenStorageMap}; -use state_machine::{Backend as StateBackend, InMemoryChangesTrieStorage, TrieBackend}; -use runtime_primitives::traits::{Block as BlockT, NumberFor}; - -use in_mem; -use backend::{AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState}; -use blockchain::HeaderBackend as BlockchainHeaderBackend; -use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; -use light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use light::fetcher::{Fetcher, RemoteReadRequest}; +use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; +use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState}; +use runtime_primitives::traits::{Block as BlockT, NumberFor, AuthorityIdFor, Zero, Header}; +use crate::in_mem::{self, check_genesis_storage}; +use crate::backend::{AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState}; +use crate::blockchain::HeaderBackend as BlockchainHeaderBackend; +use crate::error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use crate::light::fetcher::{Fetcher, RemoteReadRequest}; use hash_db::Hasher; use trie::MemoryDB; use heapsize::HeapSizeOf; +const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always suceeds; qed"; + /// Light client backend. -pub struct Backend { +pub struct Backend { blockchain: Arc>, + genesis_state: RwLock>>, } /// Light block (header and justification) import operation. -pub struct ImportOperation { +pub struct ImportOperation { header: Option, - authorities: Option>, + authorities: Option>>, leaf_state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, + finalized_blocks: Vec>, + set_head: Option>, + storage_update: Option>, _phantom: ::std::marker::PhantomData<(S, F)>, } @@ -58,10 +63,21 @@ pub struct OnDemandState { cached_header: RwLock>, } -impl Backend { +/// On-demand or in-memory genesis state. +pub enum OnDemandOrGenesisState { + /// On-demand state - storage values are fetched from remote nodes. + OnDemand(OnDemandState), + /// Genesis state - storage values are stored in-memory. + Genesis(InMemoryState), +} + +impl Backend { /// Create new light backend. pub fn new(blockchain: Arc>) -> Self { - Self { blockchain } + Self { + blockchain, + genesis_state: RwLock::new(None), + } } /// Get shared blockchain reference. @@ -70,7 +86,7 @@ impl Backend { } } -impl AuxStore for Backend { +impl AuxStore for Backend { fn insert_aux< 'a, 'b: 'a, @@ -86,36 +102,76 @@ impl AuxStore for Backend { } } -impl ClientBackend for Backend where +impl ClientBackend for Backend where Block: BlockT, S: BlockchainStorage, F: Fetcher, H: Hasher, H::Out: HeapSizeOf + Ord, { - type BlockImportOperation = ImportOperation; + type BlockImportOperation = ImportOperation; type Blockchain = Blockchain; - type State = OnDemandState; - type ChangesTrieStorage = InMemoryChangesTrieStorage; + type State = OnDemandOrGenesisState; + type ChangesTrieStorage = in_mem::ChangesTrieStorage; - fn begin_operation(&self, _block: BlockId) -> ClientResult { + fn begin_operation(&self) -> ClientResult { Ok(ImportOperation { header: None, authorities: None, leaf_state: NewBlockState::Normal, aux_ops: Vec::new(), + finalized_blocks: Vec::new(), + set_head: None, + storage_update: None, _phantom: Default::default(), }) } - fn commit_operation(&self, operation: Self::BlockImportOperation) -> ClientResult<()> { - let header = operation.header.expect("commit is called after set_block_data; set_block_data sets header; qed"); - self.blockchain.storage().import_header( - header, - operation.authorities, - operation.leaf_state, - operation.aux_ops, - ) + fn begin_state_operation( + &self, + _operation: &mut Self::BlockImportOperation, + _block: BlockId + ) -> ClientResult<()> { + Ok(()) + } + + fn commit_operation(&self, mut operation: Self::BlockImportOperation) -> ClientResult<()> { + if !operation.finalized_blocks.is_empty() { + for block in operation.finalized_blocks { + self.blockchain.storage().finalize_header(block)?; + } + } + + if let Some(header) = operation.header { + let is_genesis_import = header.number().is_zero(); + self.blockchain.storage().import_header( + header, + operation.authorities, + operation.leaf_state, + operation.aux_ops, + )?; + + // when importing genesis block => remember its state + if is_genesis_import { + *self.genesis_state.write() = operation.storage_update.take(); + } + } else { + for (key, maybe_val) in operation.aux_ops { + match maybe_val { + Some(val) => self.blockchain.storage().insert_aux( + &[(&key[..], &val[..])], + ::std::iter::empty(), + )?, + None => self.blockchain.storage().insert_aux(::std::iter::empty(), &[&key[..]])?, + } + } + } + + if let Some(set_head) = operation.set_head { + self.blockchain.storage().set_head(set_head)?; + } + + Ok(()) } fn finalize_block(&self, block: BlockId, _justification: Option) -> ClientResult<()> { @@ -131,17 +187,23 @@ impl ClientBackend for Backend where } fn state_at(&self, block: BlockId) -> ClientResult { - let block_hash = match block { - BlockId::Hash(h) => Some(h), - BlockId::Number(n) => self.blockchain.hash(n).unwrap_or_default(), - }; + let block_number = self.blockchain.expect_block_number_from_id(&block)?; + + // special case for genesis block + if block_number.is_zero() { + if let Some(genesis_state) = self.genesis_state.read().clone() { + return Ok(OnDemandOrGenesisState::Genesis(genesis_state)); + } + } - Ok(OnDemandState { + // else create on-demand state + let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; + Ok(OnDemandOrGenesisState::OnDemand(OnDemandState { fetcher: self.blockchain.fetcher(), blockchain: Arc::downgrade(&self.blockchain), - block: block_hash.ok_or_else(|| ClientErrorKind::UnknownBlock(format!("{}", block)))?, + block: block_hash, cached_header: RwLock::new(None), - }) + })) } fn revert(&self, _n: NumberFor) -> ClientResult> { @@ -149,16 +211,23 @@ impl ClientBackend for Backend where } } -impl RemoteBackend for Backend +impl RemoteBackend for Backend where Block: BlockT, S: BlockchainStorage, F: Fetcher, H: Hasher, H::Out: HeapSizeOf + Ord, -{} +{ + fn is_local_state_available(&self, block: &BlockId) -> bool { + self.genesis_state.read().is_some() + && self.blockchain.expect_block_number_from_id(block) + .map(|num| num.is_zero()) + .unwrap_or(false) + } +} -impl BlockImportOperation for ImportOperation +impl BlockImportOperation for ImportOperation where Block: BlockT, F: Fetcher, @@ -166,7 +235,7 @@ where H: Hasher, H::Out: HeapSizeOf + Ord, { - type State = OnDemandState; + type State = OnDemandOrGenesisState; fn state(&self) -> ClientResult> { // None means 'locally-stateless' backend @@ -185,11 +254,11 @@ where Ok(()) } - fn update_authorities(&mut self, authorities: Vec) { + fn update_authorities(&mut self, authorities: Vec>) { self.authorities = Some(authorities); } - fn update_storage(&mut self, _update: >::Transaction) -> ClientResult<()> { + fn update_db_storage(&mut self, _update: >::Transaction) -> ClientResult<()> { // we're not storing anything locally => ignore changes Ok(()) } @@ -199,16 +268,41 @@ where Ok(()) } - fn reset_storage(&mut self, top: StorageMap, children: ChildrenStorageMap) -> ClientResult { - let in_mem = in_mem::Backend::::new(); - let mut op = in_mem.begin_operation(BlockId::Hash(Default::default()))?; - op.reset_storage(top, children) + fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> ClientResult { + check_genesis_storage(&top, &children)?; + + // this is only called when genesis block is imported => shouldn't be performance bottleneck + let mut storage: HashMap>, StorageOverlay> = HashMap::new(); + storage.insert(None, top); + for (child_key, child_storage) in children { + storage.insert(Some(child_key), child_storage); + } + let storage_update: InMemoryState = storage.into(); + let (storage_root, _) = storage_update.storage_root(::std::iter::empty()); + self.storage_update = Some(storage_update); + + Ok(storage_root) } - fn set_aux(&mut self, ops: I) -> ClientResult<()> + fn insert_aux(&mut self, ops: I) -> ClientResult<()> where I: IntoIterator, Option>)> { - self.aux_ops = ops.into_iter().collect(); + self.aux_ops.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage(&mut self, _update: Vec<(Vec, Option>)>) -> ClientResult<()> { + // we're not storing anything locally => ignore changes + Ok(()) + } + + fn mark_finalized(&mut self, block: BlockId, _justification: Option) -> ClientResult<()> { + self.finalized_blocks.push(block); + Ok(()) + } + + fn mark_head(&mut self, block: BlockId) -> ClientResult<()> { + self.set_head = Some(block); Ok(()) } } @@ -275,7 +369,156 @@ where Vec::new() } + fn keys(&self, _prefix: &Vec) -> Vec> { + // whole state is not available on light node + Vec::new() + } + fn try_into_trie_backend(self) -> Option> { None } } + +impl StateBackend for OnDemandOrGenesisState +where + Block: BlockT, + F: Fetcher, + S: BlockchainStorage, + H: Hasher, + H::Out: HeapSizeOf + Ord, +{ + type Error = ClientError; + type Transaction = (); + type TrieBackendStorage = MemoryDB; + + fn storage(&self, key: &[u8]) -> ClientResult>> { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::storage(state, key), + OnDemandOrGenesisState::Genesis(ref state) => + Ok(state.storage(key).expect(IN_MEMORY_EXPECT_PROOF)), + } + } + + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> ClientResult>> { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::child_storage(state, storage_key, key), + OnDemandOrGenesisState::Genesis(ref state) => + Ok(state.child_storage(storage_key, key).expect(IN_MEMORY_EXPECT_PROOF)), + } + } + + fn for_keys_with_prefix(&self, prefix: &[u8], action: A) { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::for_keys_with_prefix(state, prefix, action), + OnDemandOrGenesisState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action), + } + } + + fn for_keys_in_child_storage(&self, storage_key: &[u8], action: A) { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::for_keys_in_child_storage(state, storage_key, action), + OnDemandOrGenesisState::Genesis(ref state) => state.for_keys_in_child_storage(storage_key, action), + } + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)> + { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::storage_root(state, delta), + OnDemandOrGenesisState::Genesis(ref state) => { + let (root, _) = state.storage_root(delta); + (root, ()) + }, + } + } + + fn child_storage_root(&self, key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + where + I: IntoIterator, Option>)> + { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::child_storage_root(state, key, delta), + OnDemandOrGenesisState::Genesis(ref state) => { + let (root, is_equal, _) = state.child_storage_root(key, delta); + (root, is_equal, ()) + }, + } + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::pairs(state), + OnDemandOrGenesisState::Genesis(ref state) => state.pairs(), + } + } + + fn keys(&self, prefix: &Vec) -> Vec> { + match *self { + OnDemandOrGenesisState::OnDemand(ref state) => + StateBackend::::keys(state, prefix), + OnDemandOrGenesisState::Genesis(ref state) => state.keys(prefix), + } + } + + fn try_into_trie_backend(self) -> Option> { + match self { + OnDemandOrGenesisState::OnDemand(state) => state.try_into_trie_backend(), + OnDemandOrGenesisState::Genesis(state) => state.try_into_trie_backend(), + } + } +} + +#[cfg(test)] +mod tests { + use primitives::Blake2Hasher; + use test_client::{self, runtime::Block}; + use crate::backend::NewBlockState; + use crate::light::blockchain::tests::{DummyBlockchain, DummyStorage}; + use super::*; + + #[test] + fn local_state_is_created_when_genesis_state_is_available() { + let def = Default::default(); + let header0 = test_client::runtime::Header::new(0, def, def, def, Default::default()); + + let backend: Backend<_, _, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + let mut op = backend.begin_operation().unwrap(); + op.set_block_data(header0, None, None, NewBlockState::Final).unwrap(); + op.reset_storage(Default::default(), Default::default()).unwrap(); + backend.commit_operation(op).unwrap(); + + match backend.state_at(BlockId::Number(0)).unwrap() { + OnDemandOrGenesisState::Genesis(_) => (), + _ => panic!("unexpected state"), + } + } + + #[test] + fn remote_state_is_created_when_genesis_state_is_inavailable() { + let backend: Backend<_, _, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + + match backend.state_at(BlockId::Number(0)).unwrap() { + OnDemandOrGenesisState::OnDemand(_) => (), + _ => panic!("unexpected state"), + } + } + + #[test] + fn light_aux_store_is_updated_via_non_importing_op() { + let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + let mut op = ClientBackend::::begin_operation(&backend).unwrap(); + BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); + ClientBackend::::commit_operation(&backend, op).unwrap(); + + assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); + } +} diff --git a/core/client/src/light/blockchain.rs b/core/client/src/light/blockchain.rs index ed750431649564cdc32a2d3087e08cd219f29fd6..973096ad0c5c2e1263779e5dd84114544ce35828 100644 --- a/core/client/src/light/blockchain.rs +++ b/core/client/src/light/blockchain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,16 +21,15 @@ use std::sync::Weak; use futures::{Future, IntoFuture}; use parking_lot::Mutex; -use primitives::AuthorityId; use runtime_primitives::{Justification, generic::BlockId}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT,NumberFor, Zero}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero, AuthorityIdFor}; -use backend::{AuxStore, NewBlockState}; -use blockchain::{Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, +use crate::backend::{AuxStore, NewBlockState}; +use crate::blockchain::{Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; -use cht; -use error::{ErrorKind as ClientErrorKind, Result as ClientResult}; -use light::fetcher::{Fetcher, RemoteHeaderRequest}; +use crate::cht; +use crate::error::{ErrorKind as ClientErrorKind, Result as ClientResult}; +use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; /// Light client blockchain storage. pub trait Storage: AuxStore + BlockchainHeaderBackend { @@ -41,11 +40,14 @@ pub trait Storage: AuxStore + BlockchainHeaderBackend { fn import_header( &self, header: Block::Header, - authorities: Option>, + authorities: Option>>, state: NewBlockState, aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()>; + /// Set an existing block as new best block. + fn set_head(&self, block: BlockId) -> ClientResult<()>; + /// Mark historic header as finalized. fn finalize_header(&self, block: BlockId) -> ClientResult<()>; @@ -142,7 +144,7 @@ impl BlockchainHeaderBackend for Blockchain where Bloc impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher { fn body(&self, _id: BlockId) -> ClientResult>> { - // TODO [light]: fetch from remote node + // TODO: #1445 fetch from remote node Ok(None) } @@ -161,26 +163,32 @@ impl BlockchainBackend for Blockchain where Block: Blo fn leaves(&self) -> ClientResult> { unimplemented!() } + + fn children(&self, _parent_hash: Block::Hash) -> ClientResult> { + unimplemented!() + } } #[cfg(test)] pub mod tests { use std::collections::HashMap; use test_client::runtime::{Hash, Block, Header}; - use blockchain::Info; - use light::fetcher::tests::OkCallFetcher; + use crate::blockchain::Info; + use crate::light::fetcher::tests::OkCallFetcher; use super::*; pub type DummyBlockchain = Blockchain; pub struct DummyStorage { pub changes_tries_cht_roots: HashMap, + pub aux_store: Mutex, Vec>>, } impl DummyStorage { pub fn new() -> Self { DummyStorage { changes_tries_cht_roots: HashMap::new(), + aux_store: Mutex::new(HashMap::new()), } } } @@ -198,12 +206,20 @@ pub mod tests { Err(ClientErrorKind::Backend("Test error".into()).into()) } - fn number(&self, _hash: Hash) -> ClientResult>> { - Err(ClientErrorKind::Backend("Test error".into()).into()) + fn number(&self, hash: Hash) -> ClientResult>> { + if hash == Default::default() { + Ok(Some(Default::default())) + } else { + Err(ClientErrorKind::Backend("Test error".into()).into()) + } } - fn hash(&self, _number: u64) -> ClientResult> { - Err(ClientErrorKind::Backend("Test error".into()).into()) + fn hash(&self, number: u64) -> ClientResult> { + if number == 0 { + Ok(Some(Default::default())) + } else { + Err(ClientErrorKind::Backend("Test error".into()).into()) + } } } @@ -214,12 +230,15 @@ pub mod tests { 'c: 'a, I: IntoIterator, D: IntoIterator, - >(&self, _insert: I, _delete: D) -> ClientResult<()> { - Err(ClientErrorKind::Backend("Test error".into()).into()) + >(&self, insert: I, _delete: D) -> ClientResult<()> { + for (k, v) in insert.into_iter() { + self.aux_store.lock().insert(k.to_vec(), v.to_vec()); + } + Ok(()) } - fn get_aux(&self, _key: &[u8]) -> ClientResult>> { - Err(ClientErrorKind::Backend("Test error".into()).into()) + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + Ok(self.aux_store.lock().get(key).cloned()) } } @@ -227,10 +246,14 @@ pub mod tests { fn import_header( &self, _header: Header, - _authorities: Option>, + _authorities: Option>>, _state: NewBlockState, _aux_ops: Vec<(Vec, Option>)>, ) -> ClientResult<()> { + Ok(()) + } + + fn set_head(&self, _block: BlockId) -> ClientResult<()> { Err(ClientErrorKind::Backend("Test error".into()).into()) } diff --git a/core/client/src/light/call_executor.rs b/core/client/src/light/call_executor.rs index d30e45921538d3bca5b5ff0843637b139e6d95a2..5bc77112f815269e1e8f8faaeaa3b2022111e8f5 100644 --- a/core/client/src/light/call_executor.rs +++ b/core/client/src/light/call_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,64 +17,71 @@ //! Light client call exector. Executes methods on remote full nodes, fetching //! execution proof and checking it locally. -use std::collections::HashSet; -use std::marker::PhantomData; -use std::sync::Arc; +use std::{collections::HashSet, sync::Arc, panic::UnwindSafe, result, marker::PhantomData}; use futures::{IntoFuture, Future}; -use codec::Encode; -use primitives::{H256, Blake2Hasher, convert_hash}; +use parity_codec::{Encode, Decode}; +use primitives::{H256, Blake2Hasher, convert_hash, NativeOrEncoded}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT}; -use state_machine::{self, Backend as StateBackend, CodeExecutor, OverlayedChanges, +use state_machine::{self, Backend as StateBackend, CodeExecutor, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, execution_proof_check_on_trie_backend, ExecutionManager}; use hash_db::Hasher; -use blockchain::Backend as ChainBackend; -use call_executor::{CallExecutor, CallResult}; -use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; -use light::fetcher::{Fetcher, RemoteCallRequest}; +use crate::backend::RemoteBackend; +use crate::blockchain::Backend as ChainBackend; +use crate::call_executor::CallExecutor; +use crate::error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use crate::light::fetcher::{Fetcher, RemoteCallRequest}; use executor::{RuntimeVersion, NativeVersion}; -use codec::Decode; use heapsize::HeapSizeOf; use trie::MemoryDB; /// Call executor that executes methods on remote node, querying execution proof /// and checking proof by re-executing locally. -pub struct RemoteCallExecutor { +pub struct RemoteCallExecutor { blockchain: Arc, fetcher: Arc, - _hasher: PhantomData, } -impl Clone for RemoteCallExecutor { +/// Remote or local call executor. +/// +/// Calls are executed locally if state is available locally. Otherwise, calls +/// are redirected to remote call executor. +pub struct RemoteOrLocalCallExecutor, B, R, L> { + backend: Arc, + remote: R, + local: L, + _block: PhantomData, +} + +impl Clone for RemoteCallExecutor { fn clone(&self) -> Self { RemoteCallExecutor { blockchain: self.blockchain.clone(), fetcher: self.fetcher.clone(), - _hasher: Default::default(), } } } -impl RemoteCallExecutor { +impl RemoteCallExecutor { /// Creates new instance of remote call executor. pub fn new(blockchain: Arc, fetcher: Arc) -> Self { - RemoteCallExecutor { blockchain, fetcher, _hasher: PhantomData } + RemoteCallExecutor { blockchain, fetcher } } } -impl CallExecutor for RemoteCallExecutor +impl CallExecutor for RemoteCallExecutor where - Block: BlockT, + Block: BlockT, B: ChainBackend, F: Fetcher, - H: Hasher, Block::Hash: Ord, { type Error = ClientError; - fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> ClientResult { + fn call(&self, id: &BlockId, method: &str, call_data: &[u8], _strategy: ExecutionStrategy) + -> ClientResult> { let block_hash = self.blockchain.expect_block_hash_from_id(id)?; let block_header = self.blockchain.expect_header(id.clone())?; @@ -89,7 +96,12 @@ where fn contextual_call< PB: Fn() -> ClientResult, - EM: Fn(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC, >( &self, at: &BlockId, @@ -98,38 +110,45 @@ where changes: &mut OverlayedChanges, initialised_block: &mut Option>, _prepare_environment_block: PB, - _manager: ExecutionManager, - ) -> ClientResult> where ExecutionManager: Clone { + execution_manager: ExecutionManager, + _native_call: Option, + ) -> ClientResult> where ExecutionManager: Clone { // it is only possible to execute contextual call if changes are empty if !changes.is_empty() || initialised_block.is_some() { return Err(ClientErrorKind::NotAvailableOnLightClient.into()); } - self.call(at, method, call_data).map(|cr| cr.return_data) + self.call(at, method, call_data, (&execution_manager).into()).map(NativeOrEncoded::Encoded) } fn runtime_version(&self, id: &BlockId) -> ClientResult { - let call_result = self.call(id, "version", &[])?; - RuntimeVersion::decode(&mut call_result.return_data.as_slice()) + let call_result = self.call(id, "version", &[], ExecutionStrategy::NativeElseWasm)?; + RuntimeVersion::decode(&mut call_result.as_slice()) .ok_or_else(|| ClientErrorKind::VersionInvalid.into()) } fn call_at_state< - S: StateBackend, - FF: FnOnce(Result, Self::Error>, Result, Self::Error>) -> Result, Self::Error> + S: StateBackend, + FF: FnOnce( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result, >(&self, _state: &S, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8], - _m: ExecutionManager - ) -> ClientResult<(Vec, S::Transaction, Option>)> { + _m: ExecutionManager, + _native_call: Option, + ) -> ClientResult<(NativeOrEncoded, S::Transaction, Option>)> { Err(ClientErrorKind::NotAvailableOnLightClient.into()) } - fn prove_at_trie_state>( + fn prove_at_trie_state>( &self, - _state: &state_machine::TrieBackend, + _state: &state_machine::TrieBackend, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8] @@ -142,6 +161,178 @@ where } } +impl Clone for RemoteOrLocalCallExecutor + where + Block: BlockT, + B: RemoteBackend, + R: CallExecutor + Clone, + L: CallExecutor + Clone, +{ + fn clone(&self) -> Self { + RemoteOrLocalCallExecutor { + backend: self.backend.clone(), + remote: self.remote.clone(), + local: self.local.clone(), + _block: Default::default(), + } + } +} + +impl RemoteOrLocalCallExecutor + where + Block: BlockT, + B: RemoteBackend, + Remote: CallExecutor, + Local: CallExecutor, +{ + /// Creates new instance of remote/local call executor. + pub fn new(backend: Arc, remote: Remote, local: Local) -> Self { + RemoteOrLocalCallExecutor { backend, remote, local, _block: Default::default(), } + } +} + +impl CallExecutor for + RemoteOrLocalCallExecutor + where + Block: BlockT, + B: RemoteBackend, + Remote: CallExecutor, + Local: CallExecutor, +{ + type Error = ClientError; + + fn call(&self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy) + -> ClientResult> { + match self.backend.is_local_state_available(id) { + true => self.local.call(id, method, call_data, strategy), + false => self.remote.call(id, method, call_data, strategy), + } + } + + fn contextual_call< + PB: Fn() -> ClientResult, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + at: &BlockId, + method: &str, + call_data: &[u8], + changes: &mut OverlayedChanges, + initialised_block: &mut Option>, + prepare_environment_block: PB, + _manager: ExecutionManager, + native_call: Option, + ) -> ClientResult> where ExecutionManager: Clone { + // there's no actual way/need to specify native/wasm execution strategy on light node + // => we can safely ignore passed values + + match self.backend.is_local_state_available(at) { + true => CallExecutor::contextual_call::< + _, + fn( + Result, Local::Error>, + Result, Local::Error>, + ) -> Result, Local::Error>, + _, + NC + >( + &self.local, + at, + method, + call_data, + changes, + initialised_block, + prepare_environment_block, + ExecutionManager::NativeWhenPossible, + native_call, + ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()), + false => CallExecutor::contextual_call::< + _, + fn( + Result, Remote::Error>, + Result, Remote::Error>, + ) -> Result, Remote::Error>, + _, + NC + >( + &self.remote, + at, + method, + call_data, + changes, + initialised_block, + prepare_environment_block, + ExecutionManager::NativeWhenPossible, + native_call, + ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()), + } + } + + fn runtime_version(&self, id: &BlockId) -> ClientResult { + match self.backend.is_local_state_available(id) { + true => self.local.runtime_version(id), + false => self.remote.runtime_version(id), + } + } + + fn call_at_state< + S: StateBackend, + FF: FnOnce( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >(&self, + state: &S, + changes: &mut OverlayedChanges, + method: &str, + call_data: &[u8], + _manager: ExecutionManager, + native_call: Option, + ) -> ClientResult<(NativeOrEncoded, S::Transaction, Option>)> { + // there's no actual way/need to specify native/wasm execution strategy on light node + // => we can safely ignore passed values + + CallExecutor::call_at_state::< + _, + fn( + Result, Remote::Error>, + Result, Remote::Error>, + ) -> Result, Remote::Error>, + _, + NC + >( + &self.remote, + state, + changes, + method, + call_data, + ExecutionManager::NativeWhenPossible, + native_call, + ).map_err(|e| ClientErrorKind::Execution(Box::new(e.to_string())).into()) + } + + fn prove_at_trie_state>( + &self, + state: &state_machine::TrieBackend, + changes: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> ClientResult<(Vec, Vec>)> { + self.remote.prove_at_trie_state(state, changes, method, call_data) + } + + fn native_runtime_version(&self) -> Option<&NativeVersion> { + None + } +} + /// Prove contextual execution using given block header in environment. /// /// Method is executed using passed header as environment' current block. @@ -189,7 +380,7 @@ pub fn check_execution_proof( executor: &E, request: &RemoteCallRequest
, remote_proof: Vec> -) -> ClientResult +) -> ClientResult> where Header: HeaderT, E: CodeExecutor, @@ -226,7 +417,7 @@ pub fn check_execution_proof( &request.call_data, )?; - Ok(CallResult { return_data: local_result, changes }) + Ok(local_result) } #[cfg(test)] @@ -234,6 +425,9 @@ mod tests { use consensus::BlockOrigin; use test_client::{self, runtime::{Block, Header}, runtime::RuntimeApi, TestClient}; use executor::NativeExecutionDispatch; + use crate::backend::{Backend, NewBlockState}; + use crate::in_mem::Backend as InMemBackend; + use crate::light::fetcher::tests::OkCallFetcher; use super::*; #[test] @@ -258,7 +452,7 @@ mod tests { ).unwrap(); // check remote execution proof locally - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_result = check_execution_proof(&local_executor, &RemoteCallRequest { block: test_client::runtime::Hash::default(), header: test_client::runtime::Header { @@ -273,7 +467,7 @@ mod tests { retry_count: None, }, remote_execution_proof).unwrap(); - (remote_result, local_result.return_data) + (remote_result, local_result) } // prepare remote client @@ -300,4 +494,22 @@ mod tests { let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); assert_eq!(local_block.number, 3); } + + #[test] + fn code_is_executed_locally_or_remotely() { + let backend = Arc::new(InMemBackend::new()); + let def = H256::default(); + let header0 = test_client::runtime::Header::new(0, def, def, def, Default::default()); + let hash0 = header0.hash(); + let header1 = test_client::runtime::Header::new(1, def, def, hash0, Default::default()); + let hash1 = header1.hash(); + backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); + backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); + + let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1]))); + let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2]))); + let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor); + assert_eq!(remote_or_local.call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm).unwrap(), vec![1]); + assert_eq!(remote_or_local.call(&BlockId::Number(1), "test_method", &[], ExecutionStrategy::NativeElseWasm).unwrap(), vec![2]); + } } diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index 1171e15f49d6ad35d094345d772adb8e39538484..bb6624f91f1a99036487ccbaad483a22df0ee60f 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,11 +28,10 @@ use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, NumberF use state_machine::{CodeExecutor, ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, TrieBackend, read_proof_check, key_changes_proof_check, create_proof_check_backend_storage}; -use call_executor::CallResult; -use cht; -use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; -use light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use light::call_executor::check_execution_proof; +use crate::cht; +use crate::error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}; +use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use crate::light::call_executor::check_execution_proof; /// Remote call request. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -118,7 +117,7 @@ pub trait Fetcher: Send + Sync { /// Remote storage read future. type RemoteReadResult: IntoFuture>, Error=ClientError>; /// Remote call result future. - type RemoteCallResult: IntoFuture; + type RemoteCallResult: IntoFuture, Error=ClientError>; /// Remote changes result future. type RemoteChangesResult: IntoFuture, u32)>, Error=ClientError>; @@ -156,7 +155,7 @@ pub trait FetchChecker: Send + Sync { &self, request: &RemoteCallRequest, remote_proof: Vec> - ) -> ClientResult; + ) -> ClientResult>; /// Check remote changes query proof. fn check_changes_proof( &self, @@ -344,7 +343,7 @@ impl FetchChecker for LightDataChecker, remote_proof: Vec> - ) -> ClientResult { + ) -> ClientResult> { check_execution_proof::<_, _, H>(&self.executor, request, remote_proof) } @@ -391,31 +390,31 @@ impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number pub mod tests { use futures::future::{ok, err, FutureResult}; use parking_lot::Mutex; - use keyring::Keyring; - use call_executor::CallResult; - use client::tests::prepare_client_with_key_changes; + use crate::client::tests::prepare_client_with_key_changes; use executor::{self, NativeExecutionDispatch}; - use error::Error as ClientError; - use test_client::{self, TestClient, blockchain::HeaderBackend}; - use test_client::runtime::{self, Hash, Block, Header}; + use crate::error::Error as ClientError; + use test_client::{ + self, TestClient, blockchain::HeaderBackend, AccountKeyring, + runtime::{self, Hash, Block, Header} + }; use consensus::BlockOrigin; - use in_mem::{Blockchain as InMemoryBlockchain}; - use light::fetcher::{Fetcher, FetchChecker, LightDataChecker, + use crate::in_mem::{Blockchain as InMemoryBlockchain}; + use crate::light::fetcher::{Fetcher, FetchChecker, LightDataChecker, RemoteCallRequest, RemoteHeaderRequest}; - use light::blockchain::tests::{DummyStorage, DummyBlockchain}; + use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain}; use primitives::{twox_128, Blake2Hasher}; - use primitives::storage::well_known_keys; + use primitives::storage::{StorageKey, well_known_keys}; use runtime_primitives::generic::BlockId; use state_machine::Backend; use super::*; - pub type OkCallFetcher = Mutex; + pub type OkCallFetcher = Mutex>; impl Fetcher for OkCallFetcher { type RemoteHeaderResult = FutureResult; type RemoteReadResult = FutureResult>, ClientError>; - type RemoteCallResult = FutureResult; + type RemoteCallResult = FutureResult, ClientError>; type RemoteChangesResult = FutureResult, u32)>, ClientError>; fn remote_header(&self, _request: RemoteHeaderRequest
) -> Self::RemoteHeaderResult { @@ -456,9 +455,9 @@ pub mod tests { remote_block_header.clone(), None, None, - ::backend::NewBlockState::Final, + crate::backend::NewBlockState::Final, ).unwrap(); - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); (local_checker, remote_block_header, remote_read_proof, authorities_len) } @@ -484,7 +483,7 @@ pub mod tests { if insert_cht { local_storage.insert_cht_root(1, local_cht_root); } - let local_executor = test_client::LocalExecutor::new(); + let local_executor = test_client::LocalExecutor::new(None); let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); (local_checker, local_cht_root, remote_block_header, remote_header_proof) } @@ -537,7 +536,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); let local_checker = &local_checker as &FetchChecker; let max = remote_client.info().unwrap().chain.best_number; @@ -548,6 +547,7 @@ pub mod tests { let end_hash = remote_client.block_hash(end).unwrap().unwrap(); // 'fetch' changes proof from remote node + let key = StorageKey(key); let remote_proof = remote_client.key_changes_proof( begin_hash, end_hash, begin_hash, max_hash, &key ).unwrap(); @@ -560,7 +560,7 @@ pub mod tests { last_block: (end, end_hash), max_block: (max, max_hash), tries_roots: (begin, begin_hash, local_roots_range), - key: key, + key: key.0, retry_count: None, }; let local_result = local_checker.check_changes_proof(&request, ChangesProof { @@ -584,7 +584,8 @@ pub mod tests { // we're testing this test case here: // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); // 'fetch' changes proof from remote node: // we're fetching changes for range b1..b4 @@ -603,7 +604,7 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); // check proof on local client @@ -613,7 +614,7 @@ pub mod tests { last_block: (4, b4), max_block: (4, b4), tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]), - key: dave, + key: dave.0, retry_count: None, }; let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof { @@ -631,7 +632,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); let local_checker = &local_checker as &FetchChecker; let max = remote_client.info().unwrap().chain.best_number; @@ -642,6 +643,7 @@ pub mod tests { let end_hash = remote_client.block_hash(end).unwrap().unwrap(); // 'fetch' changes proof from remote node + let key = StorageKey(key); let remote_proof = remote_client.key_changes_proof( begin_hash, end_hash, begin_hash, max_hash, &key).unwrap(); @@ -652,7 +654,7 @@ pub mod tests { last_block: (end, end_hash), max_block: (max, max_hash), tries_roots: (begin, begin_hash, local_roots_range.clone()), - key: key, + key: key.0, retry_count: None, }; @@ -694,7 +696,8 @@ pub mod tests { let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); let local_cht_root = cht::compute_root::( 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); // 'fetch' changes proof from remote node: // we're fetching changes for range b1..b4 @@ -710,7 +713,7 @@ pub mod tests { // fails when changes trie CHT is missing from the local db let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()).is_err()); @@ -720,7 +723,7 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - test_client::LocalExecutor::new() + test_client::LocalExecutor::new(None) ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, vec![]).is_err()); } diff --git a/core/client/src/light/mod.rs b/core/client/src/light/mod.rs index 8727455d30fcea5e3ae046b951427d4f06e07f4f..2cdcaf49907ac9c8d2abce6843ff0badb48492b0 100644 --- a/core/client/src/light/mod.rs +++ b/core/client/src/light/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,18 +23,19 @@ pub mod fetcher; use std::sync::Arc; +use executor::RuntimeInfo; use primitives::{H256, Blake2Hasher}; use runtime_primitives::BuildStorage; use runtime_primitives::traits::Block as BlockT; -use state_machine::{CodeExecutor, ExecutionStrategy}; +use state_machine::CodeExecutor; -use client::Client; -use error::Result as ClientResult; -use light::backend::Backend; -use light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use light::call_executor::RemoteCallExecutor; -use light::fetcher::{Fetcher, LightDataChecker}; -use hash_db::Hasher; +use crate::call_executor::LocalCallExecutor; +use crate::client::Client; +use crate::error::Result as ClientResult; +use crate::light::backend::Backend; +use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; +use crate::light::call_executor::{RemoteCallExecutor, RemoteOrLocalCallExecutor}; +use crate::light::fetcher::{Fetcher, LightDataChecker}; /// Create an instance of light client blockchain backend. pub fn new_light_blockchain, F>(storage: S) -> Arc> { @@ -42,37 +43,48 @@ pub fn new_light_blockchain, F>(storage: S) - } /// Create an instance of light client backend. -pub fn new_light_backend, F: Fetcher>(blockchain: Arc>, fetcher: Arc) -> Arc> { +pub fn new_light_backend(blockchain: Arc>, fetcher: Arc) -> Arc> + where + B: BlockT, + S: BlockchainStorage, + F: Fetcher, +{ blockchain.set_fetcher(Arc::downgrade(&fetcher)); Arc::new(Backend::new(blockchain)) } /// Create an instance of light client. -pub fn new_light( - backend: Arc>, +pub fn new_light( + backend: Arc>, fetcher: Arc, genesis_storage: GS, -) -> ClientResult, RemoteCallExecutor, F, Blake2Hasher>, B, RA>> -where - B: BlockT, - S: BlockchainStorage, - F: Fetcher, - GS: BuildStorage, - + code_executor: E, +) -> ClientResult, RemoteOrLocalCallExecutor< + B, + Backend, + RemoteCallExecutor, F>, + LocalCallExecutor, E> +>, B, RA>> + where + B: BlockT, + S: BlockchainStorage, + F: Fetcher, + GS: BuildStorage, + E: CodeExecutor + RuntimeInfo, { - let executor = RemoteCallExecutor::new(backend.blockchain().clone(), fetcher); - Client::new(backend, executor, genesis_storage, ExecutionStrategy::NativeWhenPossible, ExecutionStrategy::NativeWhenPossible) + let remote_executor = RemoteCallExecutor::new(backend.blockchain().clone(), fetcher); + let local_executor = LocalCallExecutor::new(backend.clone(), code_executor); + let executor = RemoteOrLocalCallExecutor::new(backend.clone(), remote_executor, local_executor); + Client::new(backend, executor, genesis_storage, Default::default()) } /// Create an instance of fetch data checker. -pub fn new_fetch_checker, F>( +pub fn new_fetch_checker, F>( blockchain: Arc>, executor: E, -) -> LightDataChecker +) -> LightDataChecker where - E: CodeExecutor, - H: Hasher, - + E: CodeExecutor, { LightDataChecker::new(blockchain, executor) } diff --git a/core/client/src/notifications.rs b/core/client/src/notifications.rs index 1856932ca937216505befdc8e7f822a97920a094..139238f3435e6e3a96a4a7c11dc3bef5adeaa043 100644 --- a/core/client/src/notifications.rs +++ b/core/client/src/notifications.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -213,10 +213,10 @@ mod tests { (vec![2], Some(vec![3])), (vec![3], None), ]; - notifications.trigger(&1.into(), changeset.into_iter()); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter()); // then - assert_eq!(recv.next().unwrap(), Ok((1.into(), vec![ + assert_eq!(recv.next().unwrap(), Ok((Hash::from_low_u64_be(1), vec![ (StorageKey(vec![2]), Some(StorageData(vec![3]))), (StorageKey(vec![3]), None), ].into()))); @@ -234,13 +234,13 @@ mod tests { (vec![2], Some(vec![3])), (vec![1], None), ]; - notifications.trigger(&1.into(), changeset.into_iter()); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter()); // then - assert_eq!(recv1.next().unwrap(), Ok((1.into(), vec![ + assert_eq!(recv1.next().unwrap(), Ok((Hash::from_low_u64_be(1), vec![ (StorageKey(vec![1]), None), ].into()))); - assert_eq!(recv2.next().unwrap(), Ok((1.into(), vec![ + assert_eq!(recv2.next().unwrap(), Ok((Hash::from_low_u64_be(1), vec![ (StorageKey(vec![2]), Some(StorageData(vec![3]))), ].into()))); } @@ -262,7 +262,7 @@ mod tests { (vec![2], Some(vec![3])), (vec![1], None), ]; - notifications.trigger(&1.into(), changeset.into_iter()); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter()); // then assert_eq!(notifications.listeners.len(), 0); @@ -278,7 +278,7 @@ mod tests { // when let changeset = vec![]; - notifications.trigger(&1.into(), changeset.into_iter()); + notifications.trigger(&Hash::from_low_u64_be(1), changeset.into_iter()); recv }; diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs index 9ad92fb493c5bc7e52984f29e3cfc3b4ad5c74b7..435a7d70e6fff7400beb42f937e404fbbd29b017 100644 --- a/core/client/src/runtime_api.rs +++ b/core/client/src/runtime_api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,9 +20,12 @@ #[cfg(feature = "std")] pub use state_machine::OverlayedChanges; #[doc(hidden)] +#[cfg(feature = "std")] +pub use primitives::NativeOrEncoded; +#[doc(hidden)] pub use runtime_primitives::{ - traits::{Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, ApiRef, RuntimeApiInfo}, - generic::BlockId, transaction_validity::TransactionValidity + traits::{AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, ApiRef, RuntimeApiInfo}, + generic::BlockId, transaction_validity::TransactionValidity, ExecutionContext, }; #[doc(hidden)] pub use runtime_version::{ApiId, RuntimeVersion, ApisVec, create_apis_vec}; @@ -30,20 +33,23 @@ pub use runtime_version::{ApiId, RuntimeVersion, ApisVec, create_apis_vec}; pub use rstd::{slice, mem}; #[cfg(feature = "std")] use rstd::result; -pub use codec::{Encode, Decode}; +pub use parity_codec::{Encode, Decode}; #[cfg(feature = "std")] -use error; +use crate::error; use rstd::vec::Vec; -use primitives::{AuthorityId, OpaqueMetadata}; - +use sr_api_macros::decl_runtime_apis; +use primitives::OpaqueMetadata; +#[cfg(feature = "std")] +use std::panic::UnwindSafe; /// Something that can be constructed to a runtime api. #[cfg(feature = "std")] -pub trait ConstructRuntimeApi { +pub trait ConstructRuntimeApi> { + /// The actual runtime api that will be constructed. + type RuntimeApi; + /// Construct an instance of the runtime api. - fn construct_runtime_api<'a, T: CallRuntimeAt>( - call: &'a T - ) -> ApiRef<'a, Self> where Self: Sized; + fn construct_runtime_api<'a>(call: &'a C) -> ApiRef<'a, Self::RuntimeApi>; } /// An extension for the `RuntimeApi`. @@ -63,7 +69,21 @@ pub trait ApiExt { fn has_api( &self, at: &BlockId - ) -> error::Result where Self: Sized; + ) -> error::Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api::()) + } + + /// Check if the given api is implemented and the version passes a predicate. + fn has_api_with bool>( + &self, + at: &BlockId, + pred: P, + ) -> error::Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api_with::(pred)) + } + + /// Returns the runtime version at the given block id. + fn runtime_version_at(&self, at: &BlockId) -> error::Result; } /// Something that can call into the runtime at a given block. @@ -71,14 +91,16 @@ pub trait ApiExt { pub trait CallRuntimeAt { /// Calls the given api function with the given encoded arguments at the given block /// and returns the encoded result. - fn call_api_at( + fn call_api_at result::Result + UnwindSafe>( &self, at: &BlockId, function: &'static str, args: Vec, changes: &mut OverlayedChanges, initialised_block: &mut Option>, - ) -> error::Result>; + native_call: Option, + context: ExecutionContext + ) -> error::Result>; /// Returns the runtime version at the given block. fn runtime_version_at(&self, at: &BlockId) -> error::Result; @@ -91,11 +113,11 @@ decl_runtime_apis! { /// Returns the version of the runtime. fn version() -> RuntimeVersion; /// Returns the authorities. - fn authorities() -> Vec; + fn authorities() -> Vec>; /// Execute the given block. fn execute_block(block: Block); /// Initialise a block with the given header. - fn initialise_block(header: ::Header); + fn initialise_block(header: &::Header); } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/core/consensus/aura/Cargo.toml b/core/consensus/aura/Cargo.toml index 7994afc9848fdfe461002e7ab04a3f81be91eb34..ca4f139ee4901b8598898351409ed2a7a7713ec1 100644 --- a/core/consensus/aura/Cargo.toml +++ b/core/consensus/aura/Cargo.toml @@ -3,32 +3,33 @@ name = "substrate-consensus-aura" version = "0.1.0" authors = ["Parity Technologies "] description = "Aura consensus algorithm for substrate" +edition = "2018" [dependencies] -parity-codec = "2.1" -substrate-client = { path = "../../client" } -substrate-primitives = { path = "../../primitives" } -srml-support = { path = "../../../srml/support" } -sr-primitives = { path = "../../sr-primitives" } -sr-version = { path = "../../sr-version" } -sr-io = { path = "../../sr-io" } -substrate-consensus-aura-primitives = { path = "primitives" } - +parity-codec = "3.2" +client = { package = "substrate-client", path = "../../client" } +primitives = { package = "substrate-primitives", path = "../../primitives" } +runtime_support = { package = "srml-support", path = "../../../srml/support" } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } +runtime_version = { package = "sr-version", path = "../../sr-version" } +runtime_io = { package = "sr-io", path = "../../sr-io" } +aura_slots = { package = "substrate-consensus-aura-slots", path = "slots" } +aura_primitives = { package = "substrate-consensus-aura-primitives", path = "primitives" } +inherents = { package = "substrate-inherents", path = "../../inherents" } srml-consensus = { path = "../../../srml/consensus" } +srml-aura = { path = "../../../srml/aura" } +substrate-telemetry = { path = "../../telemetry" } futures = "0.1.17" tokio = "0.1.7" -parking_lot = "0.4" +parking_lot = "0.7.1" error-chain = "0.12" -log = "0.3" -substrate-consensus-common = { path = "../common" } -substrate-network = { path = "../../network" } +log = "0.4" +consensus_common = { package = "substrate-consensus-common", path = "../common" } [dev-dependencies] -substrate-keyring = { path = "../../keyring" } +keyring = { package = "substrate-keyring", path = "../../keyring" } substrate-executor = { path = "../../executor" } -substrate-service = { path = "../../service" } -substrate-test-client = { path = "../../test-client" } -env_logger = "0.4" - -[target.'cfg(test)'.dependencies] -substrate-network = { path = "../../network", features = ["test-helpers"], optional = true } +network = { package = "substrate-network", path = "../../network", features = ["test-helpers"]} +service = { package = "substrate-service", path = "../../service" } +test_client = { package = "substrate-test-client", path = "../../test-client" } +env_logger = "0.6" diff --git a/core/consensus/aura/primitives/Cargo.toml b/core/consensus/aura/primitives/Cargo.toml index 34dac7013ddfdd11359c1eacd6a448a51a18a97b..d55db6b1eeb30a295ac7d29d9832b5237ae2a159 100644 --- a/core/consensus/aura/primitives/Cargo.toml +++ b/core/consensus/aura/primitives/Cargo.toml @@ -3,24 +3,13 @@ name = "substrate-consensus-aura-primitives" version = "0.1.0" authors = ["Parity Technologies "] description = "Primitives for Aura consensus" +edition = "2018" [dependencies] -parity-codec = { version = "2.1", default-features = false } substrate-client = { path = "../../../client", default-features = false } -substrate-primitives = { path = "../../../primitives", default-features = false } -srml-support = { path = "../../../../srml/support", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } -sr-version = { path = "../../../sr-version", default-features = false } -sr-io = { path = "../../../sr-io", default-features = false } [features] default = ["std"] std = [ - "parity-codec/std", "substrate-client/std", - "substrate-primitives/std", - "srml-support/std", - "sr-primitives/std", - "sr-version/std", - "sr-io/std", ] diff --git a/core/consensus/aura/primitives/src/lib.rs b/core/consensus/aura/primitives/src/lib.rs index 54e4149f52590cffcf4b8e6eb1fd37597272f22a..9401b164ced943bc4657128ecb555ad724491f27 100644 --- a/core/consensus/aura/primitives/src/lib.rs +++ b/core/consensus/aura/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,43 +18,16 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate parity_codec as codec; -extern crate substrate_client as client; -extern crate substrate_primitives as primitives; -extern crate srml_support as runtime_support; -extern crate sr_io as runtime_io; -extern crate sr_primitives as runtime_primitives; - -/// The ApiIds for Aura authorship API. -pub mod id { - use client::runtime_api::ApiId; - - /// ApiId for the AuraApi trait. - pub const AURA_API: ApiId = *b"aura_api"; -} - -/// Aura consensus environmental data. Useful for block-proposing code. -pub struct AuraConsensusData { - /// The timestamp the block should be authored with. - pub timestamp: u64, - /// The slot number. - pub slot: u64, - /// The duration of the slot, in seconds. - pub slot_duration: u64, -} - -/// Runtime-APIs -pub mod api { - use client::decl_runtime_apis; - decl_runtime_apis! { - /// API necessary for block authorship with aura. - pub trait AuraApi { - /// Return the slot duration in seconds for Aura. - /// Currently, only the value provided by this type at genesis - /// will be used. - /// - /// Dynamic slot duration may be supported in the future. - fn slot_duration() -> u64; - } +use substrate_client::decl_runtime_apis; + +decl_runtime_apis! { + /// API necessary for block authorship with aura. + pub trait AuraApi { + /// Return the slot duration in seconds for Aura. + /// Currently, only the value provided by this type at genesis + /// will be used. + /// + /// Dynamic slot duration may be supported in the future. + fn slot_duration() -> u64; } } diff --git a/core/consensus/aura/slots/Cargo.toml b/core/consensus/aura/slots/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..3ad763cc181e128d61f5e2c0c652e930183820d5 --- /dev/null +++ b/core/consensus/aura/slots/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "substrate-consensus-aura-slots" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Generic slots-based utilities for consensus" +edition = "2018" + +[dependencies] +codec = { package = "parity-codec", version = "3.2" } +client = { package = "substrate-client", path = "../../../client" } +primitives = { package = "substrate-primitives", path = "../../../primitives" } +runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives" } +aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../primitives" } +consensus_common = { package = "substrate-consensus-common", path = "../../common" } +inherents = { package = "substrate-inherents", path = "../../../inherents" } +futures = "0.1.17" +tokio = "0.1.7" +parking_lot = "0.7.1" +error-chain = "0.12" +log = "0.4" diff --git a/core/consensus/aura/slots/src/lib.rs b/core/consensus/aura/slots/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..53394441301f1e5373bcff46f983775ff1f81285 --- /dev/null +++ b/core/consensus/aura/slots/src/lib.rs @@ -0,0 +1,253 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +mod slots; + +pub use slots::{Slots, SlotInfo}; + +use std::sync::{mpsc, Arc}; +use std::thread; +use futures::prelude::*; +use futures::{Future, IntoFuture, future::{self, Either}}; +use log::{warn, debug, info}; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{ProvideRuntimeApi, Block}; +use consensus_common::SyncOracle; +use inherents::{InherentData, InherentDataProviders}; +use aura_primitives::AuraApi; +use client::ChainHead; +use codec::Encode; + +/// A worker that should be invoked at every new slot. +pub trait SlotWorker { + type OnSlot: IntoFuture; + + /// Called when the proposer starts. + fn on_start( + &self, + slot_duration: u64 + ) -> Result<(), consensus_common::Error>; + + /// Called when a new slot is triggered. + fn on_slot( + &self, + chain_head: B::Header, + slot_info: SlotInfo, + ) -> Self::OnSlot; +} + +/// Slot compatible inherent data. +pub trait SlotCompatible { + /// Extract timestamp and slot from inherent data. + fn extract_timestamp_and_slot(inherent: &InherentData) -> Result<(u64, u64), consensus_common::Error>; +} + +/// Convert an inherent error to common error. +pub fn inherent_to_common_error(err: inherents::RuntimeString) -> consensus_common::Error { + consensus_common::ErrorKind::InherentData(err.into()).into() +} + +/// Start a new slot worker in a separate thread. +pub fn start_slot_worker_thread( + slot_duration: SlotDuration, + client: Arc, + worker: Arc, + sync_oracle: SO, + on_exit: OnExit, + inherent_data_providers: InherentDataProviders, +) -> Result<(), consensus_common::Error> where + B: Block + 'static, + C: ChainHead + Send + Sync + 'static, + W: SlotWorker + Send + Sync + 'static, + SO: SyncOracle + Send + Clone + 'static, + SC: SlotCompatible + 'static, + OnExit: Future + Send + 'static +{ + use tokio::runtime::current_thread::Runtime; + + let (result_sender, result_recv) = mpsc::channel(); + + thread::spawn(move || { + let mut runtime = match Runtime::new() { + Ok(r) => r, + Err(e) => { + warn!("Unable to start authorship: {:?}", e); + return; + } + }; + + let slot_worker_future = match start_slot_worker::<_, _, _, _, SC, _>( + slot_duration, + client, + worker, + sync_oracle, + on_exit, + inherent_data_providers, + ) { + Ok(slot_worker_future) => { + result_sender + .send(Ok(())) + .expect("Receive is not dropped before receiving a result; qed"); + slot_worker_future + }, + Err(e) => { + result_sender + .send(Err(e)) + .expect("Receive is not dropped before receiving a result; qed"); + return; + } + }; + + let _ = runtime.block_on(slot_worker_future); + }); + + result_recv.recv().expect("Aura start thread result sender dropped") +} + +/// Start a new slot worker. +pub fn start_slot_worker( + slot_duration: SlotDuration, + client: Arc, + worker: Arc, + sync_oracle: SO, + on_exit: OnExit, + inherent_data_providers: InherentDataProviders, +) -> Result, consensus_common::Error> where + B: Block, + C: ChainHead, + W: SlotWorker, + SO: SyncOracle + Send + Clone, + SC: SlotCompatible, + OnExit: Future, +{ + worker.on_start(slot_duration.0)?; + + let make_authorship = move || { + let client = client.clone(); + let worker = worker.clone(); + let sync_oracle = sync_oracle.clone(); + let SlotDuration(slot_duration) = slot_duration; + let inherent_data_providers = inherent_data_providers.clone(); + + // rather than use a timer interval, we schedule our waits ourselves + Slots::::new(slot_duration, inherent_data_providers) + .map_err(|e| debug!(target: "aura", "Faulty timer: {:?}", e)) + .for_each(move |slot_info| { + let client = client.clone(); + let worker = worker.clone(); + let sync_oracle = sync_oracle.clone(); + + // only propose when we are not syncing. + if sync_oracle.is_major_syncing() { + debug!(target: "aura", "Skipping proposal slot due to sync."); + return Either::B(future::ok(())); + } + + let slot_num = slot_info.number; + let chain_head = match client.best_block_header() { + Ok(x) => x, + Err(e) => { + warn!(target: "aura", "Unable to author block in slot {}. \ + no best block header: {:?}", slot_num, e); + return Either::B(future::ok(())) + } + }; + + Either::A( + worker.on_slot(chain_head, slot_info).into_future() + .map_err(|e| debug!(target: "aura", "Encountered aura error: {:?}", e)) + ) + }) + }; + + let work = future::loop_fn((), move |()| { + let authorship_task = ::std::panic::AssertUnwindSafe(make_authorship()); + authorship_task.catch_unwind().then(|res| { + match res { + Ok(Ok(())) => (), + Ok(Err(())) => warn!("Aura authorship task terminated unexpectedly. Restarting"), + Err(e) => { + if let Some(s) = e.downcast_ref::<&'static str>() { + warn!("Aura authorship task panicked at {:?}", s); + } + + warn!("Restarting Aura authorship task"); + } + } + + Ok(future::Loop::Continue(())) + }) + }); + + Ok(work.select(on_exit).then(|_| Ok(()))) +} + +/// A header which has been checked +pub enum CheckedHeader { + /// A header which has slot in the future. this is the full header (not stripped) + /// and the slot in which it should be processed. + Deferred(H, u64), + /// A header which is fully checked, including signature. This is the pre-header + /// accompanied by the seal components. + Checked(H, u64, S), +} + +/// A slot duration. Create with `get_or_compute`. +// The internal member should stay private here. +#[derive(Clone, Copy, Debug)] +pub struct SlotDuration(u64); + +impl SlotDuration { + /// Either fetch the slot duration from disk or compute it from the genesis + /// state. + pub fn get_or_compute(client: &C) -> ::client::error::Result where + C: client::backend::AuxStore, + C: ProvideRuntimeApi, + C::Api: AuraApi, + { + use codec::Decode; + const SLOT_KEY: &[u8] = b"aura_slot_duration"; + + match client.get_aux(SLOT_KEY)? { + Some(v) => u64::decode(&mut &v[..]) + .map(SlotDuration) + .ok_or_else(|| ::client::error::ErrorKind::Backend( + format!("Aura slot duration kept in invalid format"), + ).into()), + None => { + use runtime_primitives::traits::Zero; + let genesis_slot_duration = client.runtime_api() + .slot_duration(&BlockId::number(Zero::zero()))?; + + info!( + "Loaded block-time = {:?} seconds from genesis on first-launch", + genesis_slot_duration + ); + + genesis_slot_duration.using_encoded(|s| { + client.insert_aux(&[(SLOT_KEY, &s[..])], &[]) + })?; + + Ok(SlotDuration(genesis_slot_duration)) + } + } + } + + /// Returns slot duration value. + pub fn get(&self) -> u64 { + self.0 + } +} diff --git a/core/consensus/aura/slots/src/slots.rs b/core/consensus/aura/slots/src/slots.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b665ce0d25d6fa7f89384178cdedc96059365b2 --- /dev/null +++ b/core/consensus/aura/slots/src/slots.rs @@ -0,0 +1,149 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utility stream for yielding slots in a loop. +//! +//! This is used instead of `tokio_timer::Interval` because it was unreliable. + +use std::time::{Instant, Duration}; +use std::marker::PhantomData; +use tokio::timer::Delay; +use futures::prelude::*; +use futures::try_ready; +use log::warn; +use inherents::{InherentDataProviders, InherentData}; +use consensus_common::{Error, ErrorKind}; +use crate::SlotCompatible; + +/// Returns current duration since unix epoch. +pub fn duration_now() -> Option { + use std::time::SystemTime; + + let now = SystemTime::now(); + now.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| { + warn!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e); + }).ok() +} + +/// Returns the duration until the next slot, based on current duration since +pub fn time_until_next(now: Duration, slot_duration: u64) -> Duration { + let remaining_full_secs = slot_duration - (now.as_secs() % slot_duration) - 1; + let remaining_nanos = 1_000_000_000 - now.subsec_nanos(); + Duration::new(remaining_full_secs, remaining_nanos) +} + +/// Information about a slot. +pub struct SlotInfo { + /// The slot number. + pub number: u64, + /// Current timestamp. + pub timestamp: u64, + /// The instant at which the slot ends. + pub ends_at: Instant, + /// The inherent data. + pub inherent_data: InherentData, + /// Slot duration. + pub duration: u64, +} + +impl SlotInfo { + /// Yields the remaining duration in the slot. + pub fn remaining_duration(&self) -> Duration { + let now = Instant::now(); + if now < self.ends_at { + self.ends_at.duration_since(now) + } else { + Duration::from_secs(0) + } + } +} + +/// A stream that returns every time there is a new slot. +pub struct Slots { + last_slot: u64, + slot_duration: u64, + inner_delay: Option, + inherent_data_providers: InherentDataProviders, + _marker: PhantomData, +} + +impl Slots { + /// Create a new `Slots` stream. + pub fn new(slot_duration: u64, inherent_data_providers: InherentDataProviders) -> Self { + Slots { + last_slot: 0, + slot_duration, + inner_delay: None, + inherent_data_providers, + _marker: PhantomData, + } + } +} + +impl Stream for Slots { + type Item = SlotInfo; + type Error = Error; + + fn poll(&mut self) -> Poll, Self::Error> { + let slot_duration = self.slot_duration; + self.inner_delay = match self.inner_delay.take() { + None => { + // schedule wait. + let wait_until = match duration_now() { + None => return Ok(Async::Ready(None)), + Some(now) => Instant::now() + time_until_next(now, slot_duration), + }; + + Some(Delay::new(wait_until)) + } + Some(d) => Some(d), + }; + + if let Some(ref mut inner_delay) = self.inner_delay { + try_ready!(inner_delay.poll().map_err(|e| Error::from(ErrorKind::FaultyTimer(e)))); + } + + // timeout has fired. + + let inherent_data = self.inherent_data_providers.create_inherent_data() + .map_err(crate::inherent_to_common_error)?; + let (timestamp, slot_num) = SC::extract_timestamp_and_slot(&inherent_data)?; + + // reschedule delay for next slot. + let ends_at = Instant::now() + time_until_next(Duration::from_secs(timestamp), slot_duration); + self.inner_delay = Some(Delay::new(ends_at)); + + // never yield the same slot twice. + if slot_num > self.last_slot { + self.last_slot = slot_num; + + Ok( + Async::Ready( + Some(SlotInfo { + number: slot_num, + duration: self.slot_duration, + timestamp, + ends_at, + inherent_data, + }) + ) + ) + } else { + // re-poll until we get a new slot. + self.poll() + } + } +} diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index f22e20930c0fd83e009719d63c0f60862e9c6529..3990535401bcacd41f54cbdf4bf96d1db021b581 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -26,55 +26,43 @@ //! Blocks from future steps will be either deferred or rejected depending on how //! far in the future they are. -extern crate parity_codec as codec; -extern crate substrate_client as client; -extern crate substrate_primitives as primitives; -extern crate srml_support as runtime_support; -extern crate sr_io as runtime_io; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_consensus_aura_primitives as aura_primitives; +use std::{sync::Arc, time::Duration, thread}; -extern crate substrate_consensus_common as consensus_common; -extern crate tokio; -extern crate sr_version as runtime_version; -extern crate substrate_network as network; -extern crate futures; -extern crate parking_lot; - -#[macro_use] -extern crate log; - -#[cfg(test)] -extern crate substrate_keyring as keyring; -#[cfg(test)] -extern crate substrate_service as service; -#[cfg(test)] -extern crate substrate_test_client as test_client; -#[cfg(test)] -extern crate env_logger; - -pub use aura_primitives::*; - -use std::sync::Arc; -use std::time::{Duration, Instant}; - -use codec::Encode; -use consensus_common::{Authorities, BlockImport, Environment, Proposer}; +use parity_codec::Encode; +use consensus_common::{ + Authorities, BlockImport, Environment, Proposer, ForkChoiceStrategy +}; +use consensus_common::import_queue::{Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport}; use client::ChainHead; -use client::block_builder::api::BlockBuilder as BlockBuilderApi; +use client::block_builder::api::{BlockBuilder as BlockBuilderApi, self as block_builder_api}; +use client::runtime_api::ApiExt; use consensus_common::{ImportBlock, BlockOrigin}; -use runtime_primitives::{generic, generic::BlockId, Justification, BasicInherentData}; -use runtime_primitives::traits::{Block, Header, Digest, DigestItemFor, ProvideRuntimeApi}; -use network::import_queue::{Verifier, BasicQueue}; -use primitives::{AuthorityId, ed25519}; - -use futures::{Stream, Future, IntoFuture, future::{self, Either}}; -use tokio::timer::{Delay, Timeout}; -use api::AuraApi; - -pub use aura_primitives::AuraConsensusData; +use runtime_primitives::{generic, generic::BlockId, Justification}; +use runtime_primitives::traits::{ + Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi +}; +use primitives::{ed25519, Pair}; +use inherents::{InherentDataProviders, InherentData, RuntimeString}; + +use futures::{Stream, Future, IntoFuture, future}; +use tokio::timer::Timeout; +use log::{warn, debug, info, trace}; + +use srml_aura::{ + InherentType as AuraInherent, AuraInherentData, + timestamp::{TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError} +}; +use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; + +use aura_slots::{CheckedHeader, SlotWorker, SlotInfo, SlotCompatible}; + +pub use aura_slots::SlotDuration; +pub use aura_primitives::*; pub use consensus_common::SyncOracle; +type AuthorityId = ed25519::Public; +type Signature = ed25519::Signature; + /// A handle to the network. This is generally implemented by providing some /// handle to a gossip service or similar. /// @@ -95,9 +83,10 @@ fn slot_author(slot_num: u64, authorities: &[AuthorityId]) -> Option Option { }).ok() } -fn timestamp_and_slot_now(slot_duration: u64) -> Option<(u64, u64)> { - duration_now().map(|s| { - let s = s.as_secs(); - (s, s / slot_duration) - }) -} - /// Get the slot for now. fn slot_now(slot_duration: u64) -> Option { duration_now().map(|s| s.as_secs() / slot_duration) } +fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error { + consensus_common::ErrorKind::InherentData(err.into()).into() +} + /// A digest item which is usable with aura consensus. pub trait CompatibleDigestItem: Sized { /// Construct a digest item which is a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self; + fn aura_seal(slot_number: u64, signature: Signature) -> Self; /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)>; + fn as_aura_seal(&self) -> Option<(u64, Signature)>; } -impl CompatibleDigestItem for generic::DigestItem { +impl CompatibleDigestItem for generic::DigestItem { /// Construct a digest item which is a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self { + fn aura_seal(slot_number: u64, signature: Signature) -> Self { generic::DigestItem::Seal(slot_number, signature) } /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> { + fn as_aura_seal(&self) -> Option<(u64, Signature)> { match self { - generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)), + generic::DigestItem::Seal(slot, ref sig) => Some((*slot, sig.clone().into())), _ => None } } } +struct AuraSlotCompatible; + +impl SlotCompatible for AuraSlotCompatible { + fn extract_timestamp_and_slot( + data: &InherentData + ) -> Result<(TimestampInherent, AuraInherent), consensus_common::Error> { + data.timestamp_inherent_data() + .and_then(|t| data.aura_inherent_data().map(|a| (t, a))) + .map_err(inherent_to_common_error) + } +} + /// Start the aura worker in a separate thread. -pub fn start_aura_thread( +pub fn start_aura_thread( slot_duration: SlotDuration, local_key: Arc, client: Arc, block_import: Arc, env: Arc, sync_oracle: SO, - on_exit: impl Future + Send + 'static, -) where + on_exit: OnExit, + inherent_data_providers: InherentDataProviders, +) -> Result<(), consensus_common::Error> where B: Block + 'static, C: Authorities + ChainHead + Send + Sync + 'static, - E: Environment + Send + Sync + 'static, - E::Proposer: Proposer + 'static, + E: Environment + Send + Sync + 'static, + E::Proposer: Proposer + Send + 'static, + <>::Create as IntoFuture>::Future: Send + 'static, I: BlockImport + Send + Sync + 'static, Error: From + From + 'static, - SO: SyncOracle + Send + Clone + 'static, - DigestItemFor: CompatibleDigestItem + 'static, + SO: SyncOracle + Send + Sync + Clone + 'static, + OnExit: Future + Send + 'static, + DigestItemFor: CompatibleDigestItem + DigestItem + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static, { - use tokio::runtime::current_thread::Runtime; - - ::std::thread::spawn(move || { - let mut runtime = match Runtime::new() { - Ok(r) => r, - Err(e) => { - warn!("Unable to start authorship: {:?}", e); - return; - } - }; + let worker = AuraWorker { + client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + }; - runtime.spawn(start_aura( - slot_duration, - local_key, - client, - block_import, - env, - sync_oracle, - )); - - runtime.block_on(on_exit).expect("Exit future should not fail"); - }); + aura_slots::start_slot_worker_thread::<_, _, _, _, AuraSlotCompatible, _>( + slot_duration, + client, + Arc::new(worker), + sync_oracle, + on_exit, + inherent_data_providers + ) } /// Start the aura worker. The returned future should be run in a tokio runtime. -pub fn start_aura( +pub fn start_aura( slot_duration: SlotDuration, local_key: Arc, client: Arc, block_import: Arc, env: Arc, sync_oracle: SO, -) -> impl Future where + on_exit: OnExit, + inherent_data_providers: InherentDataProviders, +) -> Result, consensus_common::Error> where B: Block, C: Authorities + ChainHead, - E: Environment, - E::Proposer: Proposer, - I: BlockImport, + E: Environment, + E::Proposer: Proposer, + <>::Create as IntoFuture>::Future: Send + 'static, + I: BlockImport + Send + Sync + 'static, Error: From + From, - SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem, + SO: SyncOracle + Send + Sync + Clone, + DigestItemFor: CompatibleDigestItem + DigestItem, Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, + OnExit: Future, { - let make_authorship = move || { - use futures::future; - - let client = client.clone(); - let pair = local_key.clone(); - let block_import = block_import.clone(); - let env = env.clone(); - let sync_oracle = sync_oracle.clone(); - let SlotDuration(slot_duration) = slot_duration; - - fn time_until_next(now: Duration, slot_duration: u64) -> Duration { - let remaining_full_secs = slot_duration - (now.as_secs() % slot_duration) - 1; - let remaining_nanos = 1_000_000_000 - now.subsec_nanos(); - Duration::new(remaining_full_secs, remaining_nanos) - }; - - // rather than use an interval, we schedule our waits ourselves - future::loop_fn((), move |()| { - let next_slot_start = duration_now() - .map(|now| Instant::now() + time_until_next(now, slot_duration)) - .unwrap_or_else(|| Instant::now()); - - let client = client.clone(); - let pair = pair.clone(); - let block_import = block_import.clone(); - let env = env.clone(); - let sync_oracle = sync_oracle.clone(); - let public_key = pair.public(); - - Delay::new(next_slot_start) - .map_err(|e| debug!(target: "aura", "Faulty timer: {:?}", e)) - .and_then(move |_| { - // only propose when we are not syncing. - if sync_oracle.is_major_syncing() { - debug!(target: "aura", "Skipping proposal slot due to sync."); - return Either::B(future::ok(())); - } + let worker = AuraWorker { + client: client.clone(), block_import, env, local_key, inherent_data_providers: inherent_data_providers.clone(), sync_oracle: sync_oracle.clone(), + }; + aura_slots::start_slot_worker::<_, _, _, _, AuraSlotCompatible, _>( + slot_duration, + client, + Arc::new(worker), + sync_oracle, + on_exit, + inherent_data_providers + ) +} - let pair = pair.clone(); - let (timestamp, slot_num) = match timestamp_and_slot_now(slot_duration) { - Some(n) => n, - None => return Either::B(future::err(())), - }; +struct AuraWorker { + client: Arc, + block_import: Arc, + env: Arc, + local_key: Arc, + sync_oracle: SO, + inherent_data_providers: InherentDataProviders, +} - let chain_head = match client.best_block_header() { - Ok(x) => x, - Err(e) => { - warn!(target:"aura", "Unable to author block in slot {}. \ - no best block header: {:?}", slot_num, e); - return Either::B(future::ok(())) - } - }; +impl SlotWorker for AuraWorker where + C: Authorities, + E: Environment, + E::Proposer: Proposer, + <>::Create as IntoFuture>::Future: Send + 'static, + I: BlockImport + Send + Sync + 'static, + Error: From + From, + SO: SyncOracle + Send + Clone, + DigestItemFor: CompatibleDigestItem + DigestItem, + Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, +{ + type OnSlot = Box + Send>; - let authorities = match client.authorities(&BlockId::Hash(chain_head.hash())) { - Ok(authorities) => authorities, - Err(e) => { - warn!("Unable to fetch authorities at\ - block {:?}: {:?}", chain_head.hash(), e); - return Either::B(future::ok(())); - } - }; + fn on_start( + &self, + slot_duration: u64 + ) -> Result<(), consensus_common::Error> { + register_aura_inherent_data_provider(&self.inherent_data_providers, slot_duration) + } - let proposal_work = match slot_author(slot_num, &authorities) { - None => return Either::B(future::ok(())), - Some(author) => if author.0 == public_key.0 { - debug!(target: "aura", "Starting authorship at slot {}; timestamp = {}", - slot_num, timestamp); - - // we are the slot author. make a block and sign it. - let proposer = match env.init(&chain_head, &authorities, pair.clone()) { - Ok(p) => p, - Err(e) => { - warn!("Unable to author block in slot {:?}: {:?}", slot_num, e); - return Either::B(future::ok(())) - } - }; - - let consensus_data = AuraConsensusData { - timestamp, - slot: slot_num, - slot_duration, - }; - - // deadline our production to approx. the end of the - // slot - Timeout::new( - proposer.propose(consensus_data).into_future(), - time_until_next(Duration::from_secs(timestamp), slot_duration), - ) - } else { - return Either::B(future::ok(())); - } - }; + fn on_slot( + &self, + chain_head: B::Header, + slot_info: SlotInfo, + ) -> Self::OnSlot { + let pair = self.local_key.clone(); + let public_key = self.local_key.public(); + let client = self.client.clone(); + let block_import = self.block_import.clone(); + let env = self.env.clone(); + + let (timestamp, slot_num, slot_duration) = + (slot_info.timestamp, slot_info.number, slot_info.duration); + + let authorities = match client.authorities(&BlockId::Hash(chain_head.hash())) { + Ok(authorities) => authorities, + Err(e) => { + warn!( + "Unable to fetch authorities at block {:?}: {:?}", + chain_head.hash(), + e + ); + telemetry!(CONSENSUS_WARN; "aura.unable_fetching_authorities"; + "slot" => ?chain_head.hash(), "err" => ?e + ); + return Box::new(future::ok(())); + } + }; - let block_import = block_import.clone(); - Either::A(proposal_work - .map(move |b| { - // minor hack since we don't have access to the timestamp - // that is actually set by the proposer. - let slot_after_building = slot_now(slot_duration); - if slot_after_building != Some(slot_num) { - info!("Discarding proposal for slot {}; block production took too long", - slot_num); - return - } - - let (header, body) = b.deconstruct(); - let pre_hash = header.hash(); - let parent_hash = header.parent_hash().clone(); - - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let to_sign = (slot_num, pre_hash).encode(); - let signature = pair.sign(&to_sign[..]); - let item = as CompatibleDigestItem>::aura_seal( - slot_num, - signature, - ); - - let import_block = ImportBlock { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![item], - body: Some(body), - finalized: false, - auxiliary: Vec::new(), - }; - - if let Err(e) = block_import.import_block(import_block, None) { - warn!(target: "aura", "Error with block built on {:?}: {:?}", - parent_hash, e); - } - }) - .map_err(|e| warn!("Failed to construct block: {:?}", e)) - ) - }) - .map(|_| future::Loop::Continue(())) - }) - }; + if self.sync_oracle.is_offline() && authorities.len() > 1 { + debug!(target: "aura", "Skipping proposal slot. Waiting for the network."); + telemetry!(CONSENSUS_DEBUG; "aura.skipping_proposal_slot"; + "authorities_len" => authorities.len() + ); + return Box::new(future::ok(())); + } - future::loop_fn((), move |()| { - let authorship_task = ::std::panic::AssertUnwindSafe(make_authorship()); - authorship_task.catch_unwind().then(|res| { - match res { - Ok(Ok(())) => (), - Ok(Err(())) => warn!("Aura authorship task terminated unexpectedly. Restarting"), - Err(e) => { - if let Some(s) = e.downcast_ref::<&'static str>() { - warn!("Aura authorship task panicked at {:?}", s); + let proposal_work = match slot_author(slot_num, &authorities) { + None => return Box::new(future::ok(())), + Some(author) => if author.0 == public_key.0 { + debug!( + target: "aura", "Starting authorship at slot {}; timestamp = {}", + slot_num, + timestamp + ); + telemetry!(CONSENSUS_DEBUG; "aura.starting_authorship"; + "slot_num" => slot_num, "timestamp" => timestamp + ); + + // we are the slot author. make a block and sign it. + let proposer = match env.init(&chain_head, &authorities) { + Ok(p) => p, + Err(e) => { + warn!("Unable to author block in slot {:?}: {:?}", slot_num, e); + telemetry!(CONSENSUS_WARN; "aura.unable_authoring_block"; + "slot" => slot_num, "err" => ?e + ); + return Box::new(future::ok(())) } + }; - warn!("Restarting Aura authorship task"); - } + let remaining_duration = slot_info.remaining_duration(); + // deadline our production to approx. the end of the + // slot + Timeout::new( + proposer.propose(slot_info.inherent_data, remaining_duration).into_future(), + remaining_duration, + ) + } else { + return Box::new(future::ok(())); } + }; - Ok(future::Loop::Continue(())) - }) - }) -} + Box::new( + proposal_work + .map(move |b| { + // minor hack since we don't have access to the timestamp + // that is actually set by the proposer. + let slot_after_building = slot_now(slot_duration); + if slot_after_building != Some(slot_num) { + info!( + "Discarding proposal for slot {}; block production took too long", + slot_num + ); + telemetry!(CONSENSUS_INFO; "aura.discarding_proposal_took_too_long"; + "slot" => slot_num + ); + return + } -// a header which has been checked -enum CheckedHeader { - // a header which has slot in the future. this is the full header (not stripped) - // and the slot in which it should be processed. - Deferred(H, u64), - // a header which is fully checked, including signature. This is the pre-header - // accompanied by the seal components. - Checked(H, u64, ed25519::Signature), + let (header, body) = b.deconstruct(); + let header_num = header.number().clone(); + let pre_hash = header.hash(); + let parent_hash = header.parent_hash().clone(); + + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let to_sign = (slot_num, pre_hash).encode(); + let signature = pair.sign(&to_sign[..]); + let item = as CompatibleDigestItem>::aura_seal( + slot_num, + signature, + ); + + let import_block: ImportBlock = ImportBlock { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![item], + body: Some(body), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }; + + info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + header_num, + import_block.post_header().hash(), + pre_hash + ); + telemetry!(CONSENSUS_INFO; "aura.pre_sealed_block"; + "header_num" => ?header_num, + "hash_now" => ?import_block.post_header().hash(), + "hash_previously" => ?pre_hash + ); + + if let Err(e) = block_import.import_block(import_block, None) { + warn!(target: "aura", "Error with block built on {:?}: {:?}", + parent_hash, e); + telemetry!(CONSENSUS_WARN; "aura.err_with_block_built_on"; + "hash" => ?parent_hash, "err" => ?e + ); + } + }) + .map_err(|e| consensus_common::ErrorKind::ClientImport(format!("{:?}", e)).into()) + ) + } } /// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. /// if it's successful, returns the pre-header, the slot number, and the signat. // -// FIXME: needs misbehavior types - https://github.com/paritytech/substrate/issues/1018 +// FIXME #1018 needs misbehavior types fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId]) - -> Result, String> + -> Result, String> where DigestItemFor: CompatibleDigestItem { let digest_item = match header.digest_mut().pop() { Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; - let (slot_num, &sig) = match digest_item.as_aura_seal() { + let (slot_num, sig) = match digest_item.as_aura_seal() { Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; @@ -415,7 +420,7 @@ fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, a let to_sign = (slot_num, pre_hash).encode(); let public = ed25519::Public(expected_author.0); - if ed25519::verify_strong(&sig, &to_sign[..], public) { + if ed25519::Pair::verify(&sig, &to_sign[..], public) { Ok(CheckedHeader::Checked(header, slot_num, sig)) } else { Err(format!("Bad signature on {:?}", hash)) @@ -437,11 +442,106 @@ pub trait ExtraVerification: Send + Sync { } /// A verifier for Aura blocks. -pub struct AuraVerifier { - slot_duration: SlotDuration, +pub struct AuraVerifier { client: Arc, - make_inherent: MakeInherent, extra: E, + inherent_data_providers: inherents::InherentDataProviders, +} + +impl AuraVerifier +{ + fn check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), String> + where C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + let inherent_res = self.client.runtime_api().check_inherents( + &block_id, + block, + inherent_data, + ).map_err(|e| format!("{:?}", e))?; + + if !inherent_res.ok() { + inherent_res + .into_errors() + .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { + Some(TIError::ValidAtTimestamp(timestamp)) => { + // halt import until timestamp is valid. + // reject when too far ahead. + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err("Rejecting block too far in future".into()); + } + + let diff = timestamp.saturating_sub(timestamp_now); + info!( + target: "aura", + "halting for block {} seconds in the future", + diff + ); + telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block"; + "diff" => ?diff + ); + thread::sleep(Duration::from_secs(diff)); + Ok(()) + }, + Some(TIError::Other(e)) => Err(e.into()), + None => Err(self.inherent_data_providers.error_to_string(&i, &e)), + }) + } else { + Ok(()) + } + } + + #[allow(deprecated)] + fn old_check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), String> + where C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + use block_builder_api::{OldInherentData, OldCheckInherentError}; + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + let (timestamp, slot) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data).map_err(|e| format!("{:?}", e))?; + let inherent_data = OldInherentData::new(timestamp, slot); + + let inherent_res = self.client.runtime_api().check_inherents_before_version_2( + &block_id, + block, + inherent_data, + ).map_err(|e| format!("{:?}", e))?; + + match inherent_res { + Ok(()) => Ok(()), + Err(OldCheckInherentError::ValidAtTimestamp(timestamp)) => { + // halt import until timestamp is valid. + // reject when too far ahead. + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err("Rejecting block too far in future".into()); + } + + let diff = timestamp.saturating_sub(timestamp_now); + info!( + target: "aura", + "halting for block {} seconds in the future", + diff + ); + telemetry!(CONSENSUS_INFO; "aura.halting_for_future_block"; "diff" => ?diff); + thread::sleep(Duration::from_secs(diff)); + Ok(()) + }, + Err(OldCheckInherentError::Other(e)) => Err(e.into()) + } + } } /// No-op extra verification. @@ -456,12 +556,11 @@ impl ExtraVerification for NothingExtra { } } -impl Verifier for AuraVerifier where - C: Authorities + BlockImport + ProvideRuntimeApi + Send + Sync, - C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem, +impl Verifier for AuraVerifier where + C: Authorities + ProvideRuntimeApi + Send + Sync, + C::Api: BlockBuilderApi, + DigestItemFor: CompatibleDigestItem + DigestItem, E: ExtraVerification, - MakeInherent: Fn(u64, u64) -> Inherent + Send + Sync, { fn verify( &self, @@ -470,11 +569,9 @@ impl Verifier for AuraVerifier, mut body: Option>, ) -> Result<(ImportBlock, Option>), String> { - use runtime_primitives::CheckInherentError; - const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; - - let (timestamp_now, slot_now) = timestamp_and_slot_now(self.slot_duration.0) - .ok_or("System time is before UnixTime?".to_owned())?; + let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?; + let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data) + .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; let hash = header.hash(); let parent_hash = *header.parent_hash(); let authorities = self.client.authorities(&BlockId::Hash(parent_hash)) @@ -486,8 +583,7 @@ impl Verifier for AuraVerifier(slot_now + 1, header, hash, &authorities[..])?; match checked_header { CheckedHeader::Checked(pre_header, slot_num, sig) => { @@ -497,29 +593,27 @@ impl Verifier for AuraVerifier {} - Err(CheckInherentError::ValidAtTimestamp(timestamp)) => { - // halt import until timestamp is valid. - // reject when too far ahead. - if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err("Rejecting block too far in future".into()); - } - - let diff = timestamp.saturating_sub(timestamp_now); - info!(target: "aura", "halting for block {} seconds in the future", diff); - ::std::thread::sleep(Duration::from_secs(diff)); - }, - Err(CheckInherentError::Other(s)) => return Err(s.into_owned()), + inherent_data.aura_replace_inherent_data(slot_num); + let block = B::new(pre_header.clone(), inner_body); + + if self.client + .runtime_api() + .has_api_with::, _>(&BlockId::Hash(parent_hash), |v| v < 2) + .map_err(|e| format!("{:?}", e))? + { + self.old_check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now, + )?; + } else { + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now, + )?; } let (_, inner_body) = block.deconstruct(); @@ -527,6 +621,7 @@ impl Verifier for AuraVerifier ?pre_header); extra_verification.into_future().wait()?; @@ -538,86 +633,61 @@ impl Verifier for AuraVerifier { debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); + telemetry!(CONSENSUS_DEBUG; "aura.header_too_far_in_future"; + "hash" => ?hash, "a" => ?a, "b" => ?b + ); Err(format!("Header {:?} rejected: too far in the future", hash)) } } } } -/// A utility for making the basic-inherent data. -pub fn make_basic_inherent(timestamp: u64, slot_now: u64) -> BasicInherentData { - BasicInherentData::new(timestamp, slot_now) -} - -/// A type for a function which produces inherent. -pub type InherentProducingFn = fn(u64, u64) -> I; - /// The Aura import queue type. -pub type AuraImportQueue = BasicQueue>; - -/// A slot duration. Create with `get_or_compute`. -// The internal member should stay private here. -#[derive(Clone, Copy, Debug)] -pub struct SlotDuration(u64); - -impl SlotDuration { - /// Either fetch the slot duration from disk or compute it from the genesis - /// state. - pub fn get_or_compute(client: &C) -> ::client::error::Result where - C: ::client::backend::AuxStore, - C: ProvideRuntimeApi, - C::Api: AuraApi, - { - use codec::Decode; - const SLOT_KEY: &[u8] = b"aura_slot_duration"; - - match client.get_aux(SLOT_KEY)? { - Some(v) => u64::decode(&mut &v[..]) - .map(SlotDuration) - .ok_or_else(|| ::client::error::ErrorKind::Backend( - format!("Aura slot duration kept in invalid format"), - ).into()), - None => { - use runtime_primitives::traits::Zero; - let genesis_slot_duration = client.runtime_api() - .slot_duration(&BlockId::number(Zero::zero()))?; - - info!("Loaded block-time = {:?} seconds from genesis on first-launch", - genesis_slot_duration); - - genesis_slot_duration.using_encoded(|s| { - client.insert_aux(&[(SLOT_KEY, &s[..])], &[]) - })?; - - Ok(SlotDuration(genesis_slot_duration)) - } - } +pub type AuraImportQueue = BasicQueue; + +/// Register the aura inherent data provider, if not registered already. +fn register_aura_inherent_data_provider( + inherent_data_providers: &InherentDataProviders, + slot_duration: u64, +) -> Result<(), consensus_common::Error> { + if !inherent_data_providers.has_provider(&srml_aura::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(srml_aura::InherentDataProvider::new(slot_duration)) + .map_err(inherent_to_common_error) + } else { + Ok(()) } } /// Start an import queue for the Aura consensus algorithm. -pub fn import_queue( +pub fn import_queue( slot_duration: SlotDuration, + block_import: SharedBlockImport, + justification_import: Option>, client: Arc, extra: E, - make_inherent: MakeInherent, -) -> AuraImportQueue where + inherent_data_providers: InherentDataProviders, +) -> Result, consensus_common::Error> where B: Block, - C: Authorities + BlockImport + ProvideRuntimeApi + Send + Sync, - C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem, - E: ExtraVerification, - MakeInherent: Fn(u64, u64) -> Inherent + Send + Sync, + C: 'static + Authorities + ProvideRuntimeApi + Send + Sync, + C::Api: BlockBuilderApi, + DigestItemFor: CompatibleDigestItem + DigestItem, + E: 'static + ExtraVerification, { - let verifier = Arc::new(AuraVerifier { slot_duration, client: client.clone(), extra, make_inherent }); - BasicQueue::new(verifier, client) + register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; + + let verifier = Arc::new( + AuraVerifier { client: client.clone(), extra, inherent_data_providers } + ); + Ok(BasicQueue::new(verifier, block_import, justification_import)) } #[cfg(test)] @@ -630,7 +700,7 @@ mod tests { use network::config::ProtocolConfig; use parking_lot::Mutex; use tokio::runtime::current_thread; - use keyring::Keyring; + use keyring::ed25519::Keyring; use client::BlockchainEvents; use test_client; @@ -641,22 +711,22 @@ mod tests { struct DummyFactory(Arc); struct DummyProposer(u64, Arc); - impl Environment for DummyFactory { + impl Environment for DummyFactory { type Proposer = DummyProposer; type Error = Error; - fn init(&self, parent_header: &::Header, _authorities: &[AuthorityId], _sign_with: Arc) + fn init(&self, parent_header: &::Header, _authorities: &[AuthorityId]) -> Result { Ok(DummyProposer(parent_header.number + 1, self.0.clone())) } } - impl Proposer for DummyProposer { + impl Proposer for DummyProposer { type Error = Error; type Create = Result; - fn propose(&self, _consensus_data: AuraConsensusData) -> Result { + fn propose(&self, _: InherentData, _: Duration) -> Result { self.1.new_block().unwrap().bake().map_err(|e| e.into()) } } @@ -665,51 +735,51 @@ mod tests { const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); pub struct AuraTestNet { - peers: Vec, - >, ()>>>, - started: bool + peers: Vec>>, + started: bool, } impl TestNetFactory for AuraTestNet { - type Verifier = AuraVerifier>; + type Specialization = DummySpecialization; + type Verifier = AuraVerifier; type PeerData = (); /// Create new test network with peers and given config. fn from_config(_config: &ProtocolConfig) -> Self { AuraTestNet { peers: Vec::new(), - started: false + started: false, } } fn make_verifier(&self, client: Arc, _cfg: &ProtocolConfig) -> Arc { - fn make_inherent(_: u64, _: u64) { () } let slot_duration = SlotDuration::get_or_compute(&*client) .expect("slot duration available"); + let inherent_data_providers = InherentDataProviders::new(); + register_aura_inherent_data_provider( + &inherent_data_providers, + slot_duration.get() + ).expect("Registers aura inherent data provider"); - assert_eq!(slot_duration.0, SLOT_DURATION); + assert_eq!(slot_duration.get(), SLOT_DURATION); Arc::new(AuraVerifier { client, - slot_duration, extra: NothingExtra, - make_inherent: make_inherent as _, + inherent_data_providers, }) } - fn peer(&self, i: usize) -> &Peer { + fn peer(&self, i: usize) -> &Peer { &self.peers[i] } - fn peers(&self) -> &Vec>> { + fn peers(&self) -> &Vec>> { &self.peers } - fn mut_peers>>)>(&mut self, closure: F) { + fn mut_peers>>)>(&mut self, closure: F) { closure(&mut self.peers); } @@ -724,7 +794,7 @@ mod tests { #[test] fn authoring_blocks() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = AuraTestNet::new(3); net.start(); @@ -740,19 +810,22 @@ mod tests { let mut runtime = current_thread::Runtime::new().unwrap(); for (peer_id, key) in peers { - let mut client = net.lock().peer(*peer_id).client().clone(); + let client = net.lock().peer(*peer_id).client().clone(); let environ = Arc::new(DummyFactory(client.clone())); import_notifications.push( client.import_notification_stream() - .take_while(|n| { - Ok(!(n.origin != BlockOrigin::Own && n.header.number() < &5)) - }) + .take_while(|n| Ok(!(n.origin != BlockOrigin::Own && n.header.number() < &5))) .for_each(move |_| Ok(())) ); let slot_duration = SlotDuration::get_or_compute(&*client) .expect("slot duration available"); + let inherent_data_providers = InherentDataProviders::new(); + register_aura_inherent_data_provider( + &inherent_data_providers, slot_duration.get() + ).expect("Registers aura inherent data provider"); + let aura = start_aura( slot_duration, Arc::new(key.clone().into()), @@ -760,7 +833,9 @@ mod tests { client, environ.clone(), DummyOracle, - ); + futures::empty(), + inherent_data_providers, + ).expect("Starts aura"); runtime.spawn(aura); } @@ -773,7 +848,7 @@ mod tests { let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL) .for_each(move |_| { net.lock().send_import_notifications(); - net.lock().sync(); + net.lock().route_fast(); Ok(()) }) .map(|_| ()) diff --git a/core/consensus/common/Cargo.toml b/core/consensus/common/Cargo.toml index 08689721a03fcba87158cce42c9fe3b8c14abbbb..2eaf177874c6c4beafbf926ace3a00a2793a02bb 100644 --- a/core/consensus/common/Cargo.toml +++ b/core/consensus/common/Cargo.toml @@ -3,13 +3,20 @@ name = "substrate-consensus-common" version = "0.1.0" authors = ["Parity Technologies "] description = "Common utilities for substrate consensus" +edition = "2018" [dependencies] -substrate-primitives = { path= "../../primitives" } +crossbeam-channel = "0.3.4" +log = "0.4" +primitives = { package = "substrate-primitives", path= "../../primitives" } +inherents = { package = "substrate-inherents", path = "../../inherents" } error-chain = "0.12" futures = "0.1" -sr-version = { path = "../../sr-version" } -sr-primitives = { path = "../../sr-primitives" } +runtime_version = { package = "sr-version", path = "../../sr-version" } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } tokio = "0.1.7" -parity-codec = "2.1" -parity-codec-derive = "2.0" +parity-codec = "3.2" +parity-codec-derive = "3.1" + +[dev-dependencies] +test_client = { package = "substrate-test-client", path = "../../test-client" } diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index 1f7f814a8ea43b3ff64295081c2e242a482b1ce6..06c78d74afd43225fece0045c7e306ea7b8e84c1 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,18 +16,15 @@ //! Block import helpers. -use primitives::AuthorityId; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, DigestItemFor}; +use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor}; use runtime_primitives::Justification; use std::borrow::Cow; /// Block import result. #[derive(Debug, PartialEq, Eq)] pub enum ImportResult { - /// Added to the import queue. - Queued, - /// Already in the import queue. - AlreadyQueued, + /// Block imported. + Imported(ImportedAux), /// Already in the blockchain. AlreadyInChain, /// Block or parent is known to be bad. @@ -36,6 +33,35 @@ pub enum ImportResult { UnknownParent, } +/// Auxiliary data associated with an imported block result. +#[derive(Debug, PartialEq, Eq)] +pub struct ImportedAux { + /// Clear all pending justification requests. + pub clear_justification_requests: bool, + /// Request a justification for the given block. + pub needs_justification: bool, + /// Received a bad justification. + pub bad_justification: bool, +} + +impl Default for ImportedAux { + fn default() -> ImportedAux { + ImportedAux { + clear_justification_requests: false, + needs_justification: false, + bad_justification: false, + } + } +} + +impl ImportResult { + /// Returns default value for `ImportResult::Imported` with both + /// `clear_justification_requests` and `needs_justification` set to false. + pub fn imported() -> ImportResult { + ImportResult::Imported(ImportedAux::default()) + } +} + /// Block data origin. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum BlockOrigin { @@ -53,6 +79,15 @@ pub enum BlockOrigin { File, } +/// Fork choice strategy. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum ForkChoiceStrategy { + /// Longest chain fork choice. + LongestChain, + /// Custom fork choice rule, where true indicates the new block should be the best block. + Custom(bool), +} + /// Data required to import a Block pub struct ImportBlock { /// Origin of the Block @@ -83,6 +118,8 @@ pub struct ImportBlock { /// Contains a list of key-value pairs. If values are `None`, the keys /// will be deleted. pub auxiliary: Vec<(Vec, Option>)>, + /// Fork choice strategy of this import. + pub fork_choice: ForkChoiceStrategy, } impl ImportBlock { @@ -127,14 +164,37 @@ impl ImportBlock { } } - - /// Block import trait. pub trait BlockImport { type Error: ::std::error::Error + Send + 'static; - /// Import a Block alongside the new authorities valid form this block forward - fn import_block(&self, + + /// Check block preconditions. + fn check_block( + &self, + hash: B::Hash, + parent_hash: B::Hash, + ) -> Result; + + /// Import a Block alongside the new authorities valid from this block forward + fn import_block( + &self, block: ImportBlock, - new_authorities: Option> + new_authorities: Option>>, ) -> Result; } + +/// Justification import trait +pub trait JustificationImport { + type Error: ::std::error::Error + Send + 'static; + + /// Called by the import queue when it is started. + fn on_start(&self, _link: &crate::import_queue::Link) { } + + /// Import a Block justification and finalize the given block. + fn import_justification( + &self, + hash: B::Hash, + number: NumberFor, + justification: Justification, + ) -> Result<(), Self::Error>; +} diff --git a/core/consensus/common/src/error.rs b/core/consensus/common/src/error.rs index ccf57adb9f1be04fb4960c69c7380b62520a069c..58362b8e80e2e964da42cdfd03ff2ad55c07eed6 100644 --- a/core/consensus/common/src/error.rs +++ b/core/consensus/common/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,6 +16,9 @@ //! Error types in Consensus use runtime_version::RuntimeVersion; +use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind}; +use primitives::ed25519::{Public, Signature}; error_chain! { errors { @@ -37,6 +40,12 @@ error_chain! { display("Timer error: {}", e), } + /// Error while working with inherent data. + InherentData(e: String) { + description("InherentData error"), + display("InherentData error: {}", e), + } + /// Unable to propose a block. CannotPropose { description("Unable to create block proposal."), @@ -44,13 +53,13 @@ error_chain! { } /// Error checking signature - InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::AuthorityId) { + InvalidSignature(s: Signature, a: Public) { description("Message signature is invalid"), display("Message signature {:?} by {:?} is invalid.", s, a), } /// Account is not an authority. - InvalidAuthority(a: ::primitives::AuthorityId) { + InvalidAuthority(a: Public) { description("Message sender is not a valid authority"), display("Message sender {:?} is not a valid authority.", a), } @@ -84,5 +93,11 @@ error_chain! { description("Other error") display("Other error: {}", e.description()) } + + /// Error from the client while importing + ClientImport(reason: String) { + description("Import failed"), + display("Import failed: {}", reason), + } } } diff --git a/core/consensus/common/src/evaluation.rs b/core/consensus/common/src/evaluation.rs index db35e2f4115c3c7bac0a1ec2db40be1b9d4d989b..48016b1e94c93f0b55e8806d8e28cdcc79e6a6bc 100644 --- a/core/consensus/common/src/evaluation.rs +++ b/core/consensus/common/src/evaluation.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,10 +16,12 @@ //! Block evaluation and evaluation errors. -use super::MAX_TRANSACTIONS_SIZE; +use super::MAX_BLOCK_SIZE; -use codec::Encode; +use parity_codec::Encode; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As}; +use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind, bail}; type BlockNumber = u64; @@ -41,7 +43,7 @@ error_chain! { description("Proposal exceeded the maximum size."), display( "Proposal exceeded the maximum size of {} by {} bytes.", - MAX_TRANSACTIONS_SIZE, size.saturating_sub(MAX_TRANSACTIONS_SIZE) + MAX_BLOCK_SIZE, size.saturating_sub(MAX_BLOCK_SIZE) ), } } @@ -59,12 +61,8 @@ pub fn evaluate_initial( let proposal = Block::decode(&mut &encoded[..]) .ok_or_else(|| ErrorKind::BadProposalFormat)?; - let transactions_size = proposal.extrinsics().iter().fold(0, |a, tx| { - a + Encode::encode(tx).len() - }); - - if transactions_size > MAX_TRANSACTIONS_SIZE { - bail!(ErrorKind::ProposalTooLarge(transactions_size)) + if encoded.len() > MAX_BLOCK_SIZE { + bail!(ErrorKind::ProposalTooLarge(encoded.len())) } if *parent_hash != *proposal.header().parent_hash() { diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs new file mode 100644 index 0000000000000000000000000000000000000000..997b30ed6f6ca49ae5b10e643d5b50277d47e52f --- /dev/null +++ b/core/consensus/common/src/import_queue.rs @@ -0,0 +1,674 @@ +// 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 . + +//! Import Queue primitive: something which can verify and import blocks. +//! +//! This serves as an intermediate and abstracted step between synchronization +//! and import. Each mode of consensus will have its own requirements for block verification. +//! Some algorithms can verify in parallel, while others only sequentially. +//! +//! The `ImportQueue` trait allows such verification strategies to be instantiated. +//! The `BasicQueue` and `BasicVerifier` traits allow serial queues to be +//! instantiated simply. + +use crate::block_import::{ + BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport, +}; +use crossbeam_channel::{self as channel, Receiver, Sender}; + +use std::sync::Arc; +use std::thread; + +use runtime_primitives::traits::{ + AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor +}; +use runtime_primitives::Justification; + +use crate::error::Error as ConsensusError; + +/// Shared block import struct used by the queue. +pub type SharedBlockImport = Arc + Send + Sync>; + +/// Shared justification import struct used by the queue. +pub type SharedJustificationImport = Arc + Send + Sync>; + +/// Maps to the Origin used by the network. +pub type Origin = usize; + +/// Block data used by the queue. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct IncomingBlock { + /// Block header hash. + pub hash: ::Hash, + /// Block header if requested. + pub header: Option<::Header>, + /// Block body if requested. + pub body: Option::Extrinsic>>, + /// Justification if requested. + pub justification: Option, + /// The peer, we received this from + pub origin: Option, +} + +/// Verify a justification of a block +pub trait Verifier: Send + Sync + Sized { + /// Verify the given data and return the ImportBlock and an optional + /// new set of validators to import. If not, err with an Error-Message + /// presented to the User in the logs. + fn verify( + &self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + body: Option>, + ) -> Result<(ImportBlock, Option>>), String>; +} + +/// Blocks import queue API. +pub trait ImportQueue: Send + Sync + ImportQueueClone { + /// Start background work for the queue as necessary. + /// + /// This is called automatically by the network service when synchronization + /// begins. + fn start(&self, _link: Box>) -> Result<(), std::io::Error> { + Ok(()) + } + /// Clears the import queue and stops importing. + fn stop(&self); + /// Import bunch of blocks. + fn import_blocks(&self, origin: BlockOrigin, blocks: Vec>); + /// Import a block justification. + fn import_justification(&self, who: Origin, hash: B::Hash, number: NumberFor, justification: Justification); +} + +pub trait ImportQueueClone { + fn clone_box(&self) -> Box>; +} + +impl Clone for Box> { + fn clone(&self) -> Box> { + self.clone_box() + } +} + +/// Interface to a basic block import queue that is importing blocks sequentially in a separate thread, +/// with pluggable verification. +#[derive(Clone)] +pub struct BasicQueue { + sender: Sender>, +} + +impl ImportQueueClone for BasicQueue { + fn clone_box(&self) -> Box> { + Box::new(self.clone()) + } +} + +/// "BasicQueue" is a wrapper around a channel sender to the "BlockImporter". +/// "BasicQueue" itself does not keep any state or do any importing work, and can therefore be send to other threads. +/// +/// "BasicQueue" implements "ImportQueue" by sending messages to the "BlockImporter", which runs in it's own thread. +/// +/// The "BlockImporter" is responsible for handling incoming requests from the "BasicQueue", +/// some of these requests are handled by the "BlockImporter" itself, such as "is_importing" or "status", +/// and justifications are also imported by the "BlockImporter". +/// +/// The "import block" work will be offloaded to a single "BlockImportWorker", running in another thread. +/// Offloading the work is done via a channel, +/// ensuring blocks in this implementation are imported sequentially and in order(as received by the "BlockImporter") +/// +/// As long as the "BasicQueue" is not dropped, the "BlockImporter" will keep running. +/// The "BlockImporter" owns a sender to the "BlockImportWorker", ensuring that the worker is kept alive until that sender is dropped. +impl BasicQueue { + /// Instantiate a new basic queue, with given verifier. + pub fn new>( + verifier: Arc, + block_import: SharedBlockImport, + justification_import: Option> + ) -> Self { + let (result_sender, result_port) = channel::unbounded(); + let worker_sender = BlockImportWorker::new(result_sender, verifier, block_import); + let importer_sender = BlockImporter::new(result_port, worker_sender, justification_import); + + Self { + sender: importer_sender, + } + } +} + +impl ImportQueue for BasicQueue { + fn start(&self, link: Box>) -> Result<(), std::io::Error> { + let (sender, port) = channel::unbounded(); + let _ = self + .sender + .send(BlockImportMsg::Start(link, sender)) + .expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed"); + port.recv().expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed") + } + + fn stop(&self) { + let _ = self + .sender + .send(BlockImportMsg::Stop) + .expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed"); + } + + fn import_blocks(&self, origin: BlockOrigin, blocks: Vec>) { + if blocks.is_empty() { + return; + } + let _ = self + .sender + .send(BlockImportMsg::ImportBlocks(origin, blocks)) + .expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed"); + } + + fn import_justification(&self, who: Origin, hash: B::Hash, number: NumberFor, justification: Justification) { + let _ = self + .sender + .send(BlockImportMsg::ImportJustification(who, hash, number, justification)) + .expect("1. self is holding a sender to the Importer, 2. Importer should handle messages while there are senders around; qed"); + } +} + +pub enum BlockImportMsg { + ImportBlocks(BlockOrigin, Vec>), + ImportJustification(Origin, B::Hash, NumberFor, Justification), + Start(Box>, Sender>), + Stop, +} + +pub enum BlockImportWorkerMsg { + ImportBlocks(BlockOrigin, Vec>), + Imported( + Vec<( + Result>, BlockImportError>, + B::Hash, + )>, + ), +} + +enum ImportMsgType { + FromWorker(BlockImportWorkerMsg), + FromNetwork(BlockImportMsg), +} + +struct BlockImporter { + port: Receiver>, + result_port: Receiver>, + worker_sender: Sender>, + link: Option>>, + justification_import: Option>, +} + +impl BlockImporter { + fn new( + result_port: Receiver>, + worker_sender: Sender>, + justification_import: Option>, + ) -> Sender> { + let (sender, port) = channel::bounded(4); + let _ = thread::Builder::new() + .name("ImportQueue".into()) + .spawn(move || { + let mut importer = BlockImporter { + port, + result_port, + worker_sender, + link: None, + justification_import, + }; + while importer.run() { + // Importing until all senders have been dropped... + } + }) + .expect("ImportQueue thread spawning failed"); + sender + } + + fn run(&mut self) -> bool { + let msg = select! { + recv(self.port) -> msg => { + match msg { + // Our sender has been dropped, quitting. + Err(_) => return false, + Ok(msg) => ImportMsgType::FromNetwork(msg) + } + }, + recv(self.result_port) -> msg => { + match msg { + Err(_) => unreachable!("1. We hold a sender to the Worker, 2. it should not quit until that sender is dropped; qed"), + Ok(msg) => ImportMsgType::FromWorker(msg), + } + } + }; + match msg { + ImportMsgType::FromNetwork(msg) => self.handle_network_msg(msg), + ImportMsgType::FromWorker(msg) => self.handle_worker_msg(msg), + } + } + + fn handle_network_msg(&mut self, msg: BlockImportMsg) -> bool { + match msg { + BlockImportMsg::ImportBlocks(origin, incoming_blocks) => { + self.handle_import_blocks(origin, incoming_blocks) + }, + BlockImportMsg::ImportJustification(who, hash, number, justification) => { + self.handle_import_justification(who, hash, number, justification) + }, + BlockImportMsg::Start(link, sender) => { + if let Some(justification_import) = self.justification_import.as_ref() { + justification_import.on_start(&*link); + } + self.link = Some(link); + let _ = sender.send(Ok(())); + }, + BlockImportMsg::Stop => return false, + } + true + } + + fn handle_worker_msg(&mut self, msg: BlockImportWorkerMsg) -> bool { + let results = match msg { + BlockImportWorkerMsg::Imported(results) => (results), + _ => unreachable!("Import Worker does not send ImportBlocks message; qed"), + }; + let mut has_error = false; + let mut hashes = vec![]; + for (result, hash) in results { + hashes.push(hash); + + if has_error { + continue; + } + + if result.is_err() { + has_error = true; + } + + let link = match self.link.as_ref() { + Some(link) => link, + None => { + trace!(target: "sync", "Received import result for {} while import-queue has no link", hash); + return true; + }, + }; + + match result { + Ok(BlockImportResult::ImportedKnown(number)) => link.block_imported(&hash, number), + Ok(BlockImportResult::ImportedUnknown(number, aux, who)) => { + link.block_imported(&hash, number); + + if aux.clear_justification_requests { + trace!(target: "sync", "Block imported clears all pending justification requests {}: {:?}", number, hash); + link.clear_justification_requests(); + } + + if aux.needs_justification { + trace!(target: "sync", "Block imported but requires justification {}: {:?}", number, hash); + link.request_justification(&hash, number); + } + + if aux.bad_justification { + if let Some(peer) = who { + link.useless_peer(peer, "Sent block with bad justification to import"); + } + } + }, + Err(BlockImportError::IncompleteHeader(who)) => { + if let Some(peer) = who { + link.note_useless_and_restart_sync(peer, "Sent block with incomplete header to import"); + } + }, + Err(BlockImportError::VerificationFailed(who, e)) => { + if let Some(peer) = who { + link.note_useless_and_restart_sync(peer, &format!("Verification failed: {}", e)); + } + }, + Err(BlockImportError::BadBlock(who)) => { + if let Some(peer) = who { + link.note_useless_and_restart_sync(peer, "Sent us a bad block"); + } + }, + Err(BlockImportError::UnknownParent) | Err(BlockImportError::Error) => { + link.restart(); + }, + }; + } + if let Some(link) = self.link.as_ref() { + link.blocks_processed(hashes, has_error); + } + true + } + + fn handle_import_justification(&self, who: Origin, hash: B::Hash, number: NumberFor, justification: Justification) { + let success = self.justification_import.as_ref().map(|justification_import| { + justification_import.import_justification(hash, number, justification) + .map_err(|e| { + debug!("Justification import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}", e, hash, number, who); + e + }).is_ok() + }).unwrap_or(false); + if let Some(link) = self.link.as_ref() { + link.justification_imported(who, &hash, number, success); + } + } + + fn handle_import_blocks(&mut self, origin: BlockOrigin, blocks: Vec>) { + trace!(target:"sync", "Scheduling {} blocks for import", blocks.len()); + self.worker_sender + .send(BlockImportWorkerMsg::ImportBlocks(origin, blocks)) + .expect("1. This is holding a sender to the worker, 2. the worker should not quit while a sender is still held; qed"); + } +} + +struct BlockImportWorker> { + result_sender: Sender>, + block_import: SharedBlockImport, + verifier: Arc, +} + +impl> BlockImportWorker { + pub fn new( + result_sender: Sender>, + verifier: Arc, + block_import: SharedBlockImport, + ) -> Sender> { + let (sender, port) = channel::bounded(4); + let _ = thread::Builder::new() + .name("ImportQueueWorker".into()) + .spawn(move || { + let worker = BlockImportWorker { + result_sender, + verifier, + block_import, + }; + for msg in port.iter() { + // Working until all senders have been dropped... + match msg { + BlockImportWorkerMsg::ImportBlocks(origin, blocks) => { + worker.import_a_batch_of_blocks(origin, blocks) + } + _ => unreachable!("Import Worker does not receive the Imported message; qed"), + } + } + }) + .expect("ImportQueueWorker thread spawning failed"); + sender + } + + fn import_a_batch_of_blocks(&self, origin: BlockOrigin, blocks: Vec>) { + let count = blocks.len(); + let mut imported = 0; + + let blocks_range = match ( + blocks.first().and_then(|b| b.header.as_ref().map(|h| h.number())), + blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())), + ) { + (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), + (Some(first), Some(_)) => format!(" ({})", first), + _ => Default::default(), + }; + + trace!(target:"sync", "Starting import of {} blocks {}", count, blocks_range); + + let mut results = vec![]; + + let mut has_error = false; + + // Blocks in the response/drain should be in ascending order. + for block in blocks { + let import_result = if has_error { + Err(BlockImportError::Error) + } else { + import_single_block( + &*self.block_import, + origin.clone(), + block.clone(), + self.verifier.clone(), + ) + }; + let was_ok = import_result.is_ok(); + results.push((import_result, block.hash)); + if was_ok { + imported += 1; + } else { + has_error = true; + } + } + + let _ = self + .result_sender + .send(BlockImportWorkerMsg::Imported(results)); + + trace!(target: "sync", "Imported {} of {}", imported, count); + } +} + +/// Hooks that the verification queue can use to influence the synchronization +/// algorithm. +pub trait Link: Send { + /// Block imported. + fn block_imported(&self, _hash: &B::Hash, _number: NumberFor) {} + /// Batch of blocks imported, with or without error. + fn blocks_processed(&self, _processed_blocks: Vec, _has_error: bool) {} + /// Justification import result. + fn justification_imported(&self, _who: Origin, _hash: &B::Hash, _number: NumberFor, _success: bool) {} + /// Clear all pending justification requests. + fn clear_justification_requests(&self) {} + /// Request a justification for the given block. + fn request_justification(&self, _hash: &B::Hash, _number: NumberFor) {} + /// Disconnect from peer. + fn useless_peer(&self, _who: Origin, _reason: &str) {} + /// Disconnect from peer and restart sync. + fn note_useless_and_restart_sync(&self, _who: Origin, _reason: &str) {} + /// Restart sync. + fn restart(&self) {} +} + +/// Block import successful result. +#[derive(Debug, PartialEq)] +pub enum BlockImportResult { + /// Imported known block. + ImportedKnown(N), + /// Imported unknown block. + ImportedUnknown(N, ImportedAux, Option), +} + +/// Block import error. +#[derive(Debug, PartialEq)] +pub enum BlockImportError { + /// Block missed header, can't be imported + IncompleteHeader(Option), + /// Block verification failed, can't be imported + VerificationFailed(Option, String), + /// Block is known to be Bad + BadBlock(Option), + /// Block has an unknown parent + UnknownParent, + /// Other Error. + Error, +} + +/// Single block import function. +pub fn import_single_block>( + import_handle: &BlockImport, + block_origin: BlockOrigin, + block: IncomingBlock, + verifier: Arc, +) -> Result>, BlockImportError> { + let peer = block.origin; + + let (header, justification) = match (block.header, block.justification) { + (Some(header), justification) => (header, justification), + (None, _) => { + if let Some(peer) = peer { + debug!(target: "sync", "Header {} was not provided by {} ", block.hash, peer); + } else { + debug!(target: "sync", "Header {} was not provided ", block.hash); + } + return Err(BlockImportError::IncompleteHeader(peer)) + }, + }; + + let number = header.number().clone(); + let hash = header.hash(); + let parent = header.parent_hash().clone(); + + let import_error = |e| { + match e { + Ok(ImportResult::AlreadyInChain) => { + trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); + Ok(BlockImportResult::ImportedKnown(number)) + }, + Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer)), + Ok(ImportResult::UnknownParent) => { + debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); + Err(BlockImportError::UnknownParent) + }, + Ok(ImportResult::KnownBad) => { + debug!(target: "sync", "Peer gave us a bad block {}: {:?}", number, hash); + Err(BlockImportError::BadBlock(peer)) + }, + Err(e) => { + debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); + Err(BlockImportError::Error) + } + } + }; + + match import_error(import_handle.check_block(hash, parent))? { + BlockImportResult::ImportedUnknown { .. } => (), + r @ _ => return Ok(r), // Any other successfull result means that the block is already imported. + } + + let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body) + .map_err(|msg| { + if let Some(peer) = peer { + trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg); + } else { + trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); + } + BlockImportError::VerificationFailed(peer, msg) + })?; + + import_error(import_handle.import_block(import_block, new_authorities)) +} + +#[cfg(test)] +mod tests { + use super::*; + use test_client::runtime::{Block, Hash}; + + #[derive(Debug, PartialEq)] + enum LinkMsg { + BlockImported, + Disconnected, + Restarted, + } + + #[derive(Clone)] + struct TestLink { + sender: Sender, + } + + impl TestLink { + fn new(sender: Sender) -> TestLink { + TestLink { + sender, + } + } + } + + impl Link for TestLink { + fn block_imported(&self, _hash: &Hash, _number: NumberFor) { + let _ = self.sender.send(LinkMsg::BlockImported); + } + fn useless_peer(&self, _: Origin, _: &str) { + let _ = self.sender.send(LinkMsg::Disconnected); + } + fn note_useless_and_restart_sync(&self, id: Origin, r: &str) { + self.useless_peer(id, r); + self.restart(); + } + fn restart(&self) { + let _ = self.sender.send(LinkMsg::Restarted); + } + } + + #[test] + fn process_import_result_works() { + let (result_sender, result_port) = channel::unbounded(); + let (worker_sender, _) = channel::unbounded(); + let (link_sender, link_port) = channel::unbounded(); + let importer_sender = BlockImporter::::new(result_port, worker_sender, None); + let link = TestLink::new(link_sender); + let (ack_sender, start_ack_port) = channel::bounded(4); + let _ = importer_sender.send(BlockImportMsg::Start(Box::new(link.clone()), ack_sender)); + + // Ensure the importer handles Start before any result messages. + let _ = start_ack_port.recv(); + + // Send a known + let results = vec![(Ok(BlockImportResult::ImportedKnown(Default::default())), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + + // Send a second known + let results = vec![(Ok(BlockImportResult::ImportedKnown(Default::default())), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + + // Send an unknown + let results = vec![(Ok(BlockImportResult::ImportedUnknown(Default::default(), Default::default(), None)), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + + // Send an unknown with peer and bad justification + let results = vec![(Ok(BlockImportResult::ImportedUnknown(Default::default(), + ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: true }, + Some(0))), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::BlockImported)); + assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); + + // Send an incomplete header + let results = vec![(Err(BlockImportError::IncompleteHeader(Some(Default::default()))), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); + assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); + + // Send an unknown parent + let results = vec![(Err(BlockImportError::UnknownParent), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); + + // Send a verification failed + let results = vec![(Err(BlockImportError::VerificationFailed(Some(0), String::new())), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::Disconnected)); + assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); + + // Send an error + let results = vec![(Err(BlockImportError::Error), Default::default())]; + let _ = result_sender.send(BlockImportWorkerMsg::Imported(results)).ok().unwrap(); + assert_eq!(link_port.recv(), Ok(LinkMsg::Restarted)); + + // Drop the importer sender first, ensuring graceful shutdown. + drop(importer_sender); + } +} + diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index 76c370effddb006d91d63bf5428ec1599cebc88f..73315ed7aa9c676ec1564662055676ac106903a6 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate Consensus Common. // Substrate Demo is free software: you can redistribute it and/or modify @@ -14,7 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Substrate Consensus Common. If not, see . -//! Tracks offline validators. +//! Common utilities for building and using consensus engines in substrate. +//! +//! Much of this crate is _unstable_ and thus the API is likely to undergo +//! change. Implementors of traits should not rely on the interfaces to remain +//! the same. // This provides "unused" building blocks to other crates #![allow(dead_code)] @@ -22,53 +26,47 @@ // our error-chain could potentially blow up otherwise #![recursion_limit="128"] -extern crate substrate_primitives as primitives; -extern crate futures; -extern crate sr_version as runtime_version; -extern crate sr_primitives as runtime_primitives; -extern crate tokio; - -extern crate parity_codec as codec; -extern crate parity_codec_derive; - -#[macro_use] -extern crate error_chain; +#[macro_use] extern crate crossbeam_channel; +#[macro_use] extern crate log; use std::sync::Arc; +use std::time::Duration; -use primitives::{ed25519, AuthorityId}; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::Block; +use runtime_primitives::traits::{AuthorityIdFor, Block}; use futures::prelude::*; +pub use inherents::InherentData; pub mod offline_tracker; pub mod error; mod block_import; +pub mod import_queue; pub mod evaluation; // block size limit. -const MAX_TRANSACTIONS_SIZE: usize = 4 * 1024 * 1024; +const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; pub use self::error::{Error, ErrorKind}; -pub use block_import::{BlockImport, ImportBlock, BlockOrigin, ImportResult}; +pub use block_import::{ + BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, ImportBlock, ImportResult, JustificationImport, +}; /// Trait for getting the authorities at a given block. pub trait Authorities { type Error: ::std::error::Error + Send + 'static; /// Get the authorities at the given block. - fn authorities(&self, at: &BlockId) -> Result, Self::Error>; + fn authorities(&self, at: &BlockId) -> Result>, Self::Error>; } /// Environment producer for a Consensus instance. Creates proposer instance and communication streams. -pub trait Environment { +pub trait Environment { /// The proposer type this creates. - type Proposer: Proposer; + type Proposer: Proposer; /// Error which can occur upon creation. type Error: From; /// Initialize the proposal logic on top of a specific header. Provide - /// the authorities at that header, and a local key to sign any additional - /// consensus messages with as well. - fn init(&self, parent_header: &B::Header, authorities: &[AuthorityId], sign_with: Arc) + /// the authorities at that header. + fn init(&self, parent_header: &B::Header, authorities: &[AuthorityIdFor]) -> Result; } @@ -78,13 +76,13 @@ pub trait Environment { /// block. /// /// Proposers are generic over bits of "consensus data" which are engine-specific. -pub trait Proposer { +pub trait Proposer { /// Error type which can occur when proposing or evaluating. type Error: From + ::std::fmt::Debug + 'static; /// Future that resolves to a committed proposal. - type Create: IntoFuture; + type Create: IntoFuture; /// Create a proposal. - fn propose(&self, consensus_data: ConsensusData) -> Self::Create; + fn propose(&self, inherent_data: InherentData, max_duration: Duration) -> Self::Create; } /// An oracle for when major synchronization work is being undertaken. @@ -95,6 +93,9 @@ pub trait SyncOracle { /// Whether the synchronization service is undergoing major sync. /// Returns true if so. fn is_major_syncing(&self) -> bool; + /// Whether the synchronization service is offline. + /// Returns true if so. + fn is_offline(&self) -> bool; } /// A synchronization oracle for when there is no network. @@ -103,10 +104,14 @@ pub struct NoNetwork; impl SyncOracle for NoNetwork { fn is_major_syncing(&self) -> bool { false } + fn is_offline(&self) -> bool { false } } impl SyncOracle for Arc { fn is_major_syncing(&self) -> bool { T::is_major_syncing(&*self) } + fn is_offline(&self) -> bool { + T::is_offline(&*self) + } } diff --git a/core/consensus/common/src/offline_tracker.rs b/core/consensus/common/src/offline_tracker.rs index bd8eab8b1bb51f60a85d543e2d047cd55235cdf1..3c6755d9411d7230bc2aaaa575737a208a13953d 100644 --- a/core/consensus/common/src/offline_tracker.rs +++ b/core/consensus/common/src/offline_tracker.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,6 @@ //! Tracks offline validators. -use primitives::AuthorityId; - use std::collections::HashMap; use std::time::{Instant, Duration}; @@ -55,11 +53,11 @@ impl Observed { } /// Tracks offline validators and can issue a report for those offline. -pub struct OfflineTracker { +pub struct OfflineTracker { observed: HashMap, } -impl OfflineTracker { +impl OfflineTracker { /// Create a new tracker. pub fn new() -> Self { OfflineTracker { observed: HashMap::new() } @@ -114,24 +112,25 @@ impl OfflineTracker { #[cfg(test)] mod tests { use super::*; + use primitives::ed25519::Public as AuthorityId; #[test] fn validator_offline() { - let mut tracker = OfflineTracker::new(); - let v = [0; 32].into(); - let v2 = [1; 32].into(); - let v3 = [2; 32].into(); - tracker.note_round_end(v, true); - tracker.note_round_end(v2, true); - tracker.note_round_end(v3, true); + let mut tracker = OfflineTracker::::new(); + let v = AuthorityId::from_raw([0; 32]); + let v2 = AuthorityId::from_raw([1; 32]); + let v3 = AuthorityId::from_raw([2; 32]); + tracker.note_round_end(v.clone(), true); + tracker.note_round_end(v2.clone(), true); + tracker.note_round_end(v3.clone(), true); let slash_time = REPORT_TIME + Duration::from_secs(5); tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time; tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time; - assert_eq!(tracker.reports(&[v, v2, v3]), vec![0, 1]); + assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]); - tracker.note_new_block(&[v, v3]); + tracker.note_new_block(&[v.clone(), v3.clone()]); assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); } } diff --git a/core/consensus/rhd/Cargo.toml b/core/consensus/rhd/Cargo.toml index dce6a6d7f445abd16193672ea726cdf266f2f339..71b45cf41b6749f419a9b9d9093fbee2b93b412d 100644 --- a/core/consensus/rhd/Cargo.toml +++ b/core/consensus/rhd/Cargo.toml @@ -3,38 +3,36 @@ name = "substrate-consensus-rhd" version = "0.1.0" authors = ["Parity Technologies "] description = "Rhododendron Round-Based consensus-algorithm for substrate" +edition = "2018" [dependencies] futures = "0.1.17" -parity-codec = { version = "2.1" } -parity-codec-derive = { version = "2.0" } -substrate-primitives = { path = "../../primitives" } -substrate-consensus-common = { path = "../common" } -substrate-client = { path = "../../client" } -substrate-transaction-pool = { path = "../../transaction-pool" } -srml-support = { path = "../../../srml/support" } +codec = { package = "parity-codec", version = "3.2", features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../../primitives" } +consensus = { package = "substrate-consensus-common", path = "../common" } +client = { package = "substrate-client", path = "../../client" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../transaction-pool" } +runtime_support = { package = "srml-support", path = "../../../srml/support" } srml-system = { path = "../../../srml/system" } srml-consensus = { path = "../../../srml/consensus" } -sr-primitives = { path = "../../sr-primitives" } -sr-version = { path = "../../sr-version" } -sr-io = { path = "../../sr-io" } +runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } +runtime_version = { package = "sr-version", path = "../../sr-version" } +runtime_io = { package = "sr-io", path = "../../sr-io" } tokio = "0.1.7" -parking_lot = "0.4" +parking_lot = "0.7.1" error-chain = "0.12" log = "0.4" -rhododendron = { version = "0.4.0", features = ["codec"] } +rhododendron = { version = "0.5.0", features = ["codec"] } exit-future = "0.1" - [dev-dependencies] -substrate-keyring = { path = "../../keyring" } -substrate-executor = { path = "../../executor" } +keyring = { package = "substrate-keyring", path = "../../keyring" } [features] default = ["std"] std = [ - "substrate-primitives/std", - "srml-support/std", - "sr-primitives/std", - "sr-version/std", + "primitives/std", + "runtime_support/std", + "runtime_primitives/std", + "runtime_version/std", ] diff --git a/core/consensus/rhd/src/error.rs b/core/consensus/rhd/src/error.rs index c18c36f679c830d20e623af83bc6f7b059349171..38081109754555b73c02c48f2c51bb1404425cf7 100644 --- a/core/consensus/rhd/src/error.rs +++ b/core/consensus/rhd/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,6 +18,8 @@ use consensus::error::{Error as CommonError, ErrorKind as CommonErrorKind}; use primitives::AuthorityId; use client; +use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind}; error_chain! { links { @@ -54,4 +56,4 @@ impl From for Error { fn from(e: CommonErrorKind) -> Self { CommonError::from(e).into() } -} \ No newline at end of file +} diff --git a/core/consensus/rhd/src/lib.rs b/core/consensus/rhd/src/lib.rs index 6441fb4e34a2f6e3ec30a2a494dc936eb33532a0..e42083a40b30952e128542823be5729c902a1688 100644 --- a/core/consensus/rhd/src/lib.rs +++ b/core/consensus/rhd/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -31,42 +31,13 @@ //! set for this block height. #![cfg(feature="rhd")] -// FIXME: doesn't compile - https://github.com/paritytech/substrate/issues/1020 - -extern crate parity_codec as codec; -extern crate substrate_primitives as primitives; -extern crate substrate_client as client; -extern crate substrate_consensus_common as consensus; -extern crate substrate_transaction_pool as transaction_pool; -extern crate srml_system; -extern crate srml_support as runtime_support; -extern crate sr_primitives as runtime_primitives; -extern crate sr_version as runtime_version; -extern crate sr_io as runtime_io; - -extern crate parking_lot; -extern crate rhododendron; -extern crate futures; -extern crate exit_future; -extern crate tokio; - -#[macro_use] -extern crate log; - -#[macro_use] -extern crate error_chain; - -#[macro_use] -extern crate parity_codec_derive; - -#[cfg(test)] -extern crate substrate_keyring; +// FIXME #1020 doesn't compile use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{self, Instant, Duration}; -use codec::{Decode, Encode}; +use parity_codec::{Decode, Encode}; use consensus::offline_tracker::OfflineTracker; use consensus::error::{ErrorKind as CommonErrorKind}; use consensus::{Authorities, BlockImport, Environment, Proposer as BaseProposer}; @@ -460,7 +431,6 @@ impl Drop for BftFuture OutSink: Sink, SinkError=Error>, { fn drop(&mut self) { - // TODO: have a trait member to pass misbehavior reports into. let misbehavior = self.inner.drain_misbehavior().collect::>(); self.inner.context().proposer.import_misbehavior(misbehavior); } @@ -494,7 +464,7 @@ pub struct BftService { live_agreement: Mutex>, round_cache: Arc>>, round_timeout_multiplier: u64, - key: Arc, // TODO: key changing over time. + key: Arc, factory: P, } @@ -516,14 +486,13 @@ impl BftService start_round: 0, })), round_timeout_multiplier: 10, - key: key, // TODO: key changing over time. + key: key, factory, } } /// Get the local Authority ID. pub fn local_id(&self) -> AuthorityId { - // TODO: based on a header and some keystore. self.key.public().into() } @@ -793,7 +762,7 @@ fn check_justification_signed_message( let auth_id = sig.signer.clone().into(); if !authorities.contains(&auth_id) { return None } - if ed25519::verify_strong(&sig.signature, message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, message, &sig.signer) { Some(sig.signer.0) } else { None @@ -869,7 +838,7 @@ pub fn check_vote( fn check_action(action: Action, parent_hash: &B::Hash, sig: &LocalizedSignature) -> Result<(), Error> { let message = localized_encode(*parent_hash, action); - if ed25519::verify_strong(&sig.signature, &message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, &message, &sig.signer) { Ok(()) } else { Err(CommonErrorKind::InvalidSignature(sig.signature.into(), sig.signer.clone().into()).into()) @@ -1112,7 +1081,6 @@ impl BaseProposer<::Block> for Proposer where self.transaction_pool.ready(|pending_iterator| { let mut pending_size = 0; for pending in pending_iterator { - // TODO [ToDr] Probably get rid of it, and validate in runtime. let encoded_size = pending.data.encode().len(); if pending_size + encoded_size >= MAX_TRANSACTIONS_SIZE { break } @@ -1347,9 +1315,7 @@ mod tests { use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader}; use primitives::H256; - use self::keyring::Keyring; - - extern crate substrate_keyring as keyring; + use keyring::AuthorityKeyring; type TestBlock = GenericTestBlock<()>; @@ -1454,7 +1420,7 @@ mod tests { start_round: 0, })), round_timeout_multiplier: 10, - key: Arc::new(Keyring::One.into()), + key: Arc::new(AuthorityKeyring::One.into()), factory: DummyFactory } } @@ -1480,10 +1446,10 @@ mod tests { fn future_gets_preempted() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1527,17 +1493,17 @@ mod tests { let hash = [0xff; 32].into(); let authorities = vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let authorities_keys = vec![ - Keyring::One.into(), - Keyring::Two.into(), - Keyring::Alice.into(), - Keyring::Eve.into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { @@ -1588,8 +1554,8 @@ mod tests { let parent_hash = Default::default(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let block = TestBlock { @@ -1597,7 +1563,7 @@ mod tests { extrinsics: Default::default() }; - let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; + let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &AuthorityKeyring::Alice.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_ok()); let mut invalid_round = proposal.clone(); @@ -1611,7 +1577,7 @@ mod tests { } // Not an authority - let proposal = sign_message::(rhododendron::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);; + let proposal = sign_message::(rhododendron::Message::Propose(1, block), &AuthorityKeyring::Bob.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); } else { @@ -1625,8 +1591,8 @@ mod tests { let hash: H256 = [0xff; 32].into(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let vote = sign_message::(rhododendron::Message::Vote(rhododendron::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; @@ -1652,10 +1618,10 @@ mod tests { fn drop_bft_future_does_not_deadlock() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1677,10 +1643,10 @@ mod tests { fn bft_can_build_though_skipped() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; diff --git a/core/consensus/rhd/src/misbehaviour_check.rs b/core/consensus/rhd/src/misbehaviour_check.rs index be8e25ccc9e2984bdc51323e25c095a51ccc139e..58b36542f692bfe16dda219a1d5fd53cb83bf160 100644 --- a/core/consensus/rhd/src/misbehaviour_check.rs +++ b/core/consensus/rhd/src/misbehaviour_check.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -74,8 +74,7 @@ pub fn evaluate_misbehavior( mod tests { use super::*; - use keyring::ed25519; - use keyring::Keyring; + use keyring::AuthorityKeyring; use rhododendron; use runtime_primitives::testing::{H256, Block as RawBlock}; @@ -110,7 +109,7 @@ mod tests { #[test] fn evaluates_double_prepare() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -127,7 +126,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_prepare(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( @@ -135,23 +134,23 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, sign_prepare(&key, 1, hash_1, parent_hash), sign_prepare(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } #[test] fn evaluates_double_commit() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -168,7 +167,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_commit(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( @@ -176,17 +175,17 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, sign_commit(&key, 1, hash_1, parent_hash), sign_commit(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } } diff --git a/core/consensus/rhd/src/service.rs b/core/consensus/rhd/src/service.rs index 34efc942d4dae2a4e77b58d023ea5405be30e0e9..e2858f767a8c08d3977803a68ce6bab46188cb60 100644 --- a/core/consensus/rhd/src/service.rs +++ b/core/consensus/rhd/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/executor/Cargo.toml b/core/executor/Cargo.toml index dcea860163e714e74992ba5c81da62a143e3bfa7..f34bfbbe916414b58b3a1a81cc0e3c143559d9d0 100644 --- a/core/executor/Cargo.toml +++ b/core/executor/Cargo.toml @@ -2,27 +2,31 @@ name = "substrate-executor" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] error-chain = "0.12" -parity-codec = "2.1" -sr-io = { path = "../sr-io" } -substrate-primitives = { path = "../primitives" } -substrate-trie = { path = "../trie" } -substrate-serializer = { path = "../serializer" } -substrate-state-machine = { path = "../state-machine" } -sr-version = { path = "../sr-version" } +parity-codec = "3.2" +runtime_io = { package = "sr-io", path = "../sr-io" } +primitives = { package = "substrate-primitives", path = "../primitives" } +trie = { package = "substrate-trie", path = "../trie" } +serializer = { package = "substrate-serializer", path = "../serializer" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +runtime_version = { package = "sr-version", path = "../sr-version" } +panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } serde = "1.0" serde_derive = "1.0" -wasmi = { version = "0.4.2" } +wasmi = { version = "0.4.3" } byteorder = "1.1" lazy_static = "1.0" -parking_lot = "*" +parking_lot = "0.7.1" log = "0.4" +libsecp256k1 = "0.2.1" +tiny-keccak = "1.4.2" [dev-dependencies] assert_matches = "1.1" -wabt = "0.7" +wabt = "~0.7.4" hex-literal = "0.1.0" [features] diff --git a/core/executor/src/allocator.rs b/core/executor/src/allocator.rs new file mode 100644 index 0000000000000000000000000000000000000000..4b3f7d32193cffd8d26f80404d5a4954e95b58f7 --- /dev/null +++ b/core/executor/src/allocator.rs @@ -0,0 +1,506 @@ +// 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 . + +//! This module implements a freeing-bump allocator. +//! See more details at https://github.com/paritytech/substrate/issues/1615. + +use crate::wasm_utils::UserError; +use log::trace; +use wasmi::Error; +use wasmi::MemoryRef; +use wasmi::memory_units::Bytes; + +// The pointers need to be aligned to 8 bytes. +const ALIGNMENT: u32 = 8; + +// The pointer returned by `allocate()` needs to fulfill the alignment +// requirement. In our case a pointer will always be a multiple of +// 8, as long as the first pointer is aligned to 8 bytes. +// This is because all pointers will contain a 8 byte prefix (the list +// index) and then a subsequent item of 2^x bytes, where x = [3..24]. +const N: usize = 22; +const MAX_POSSIBLE_ALLOCATION: u32 = 16777216; // 2^24 bytes + +pub const OUT_OF_SPACE: &str = "Requested allocation size does not fit into remaining heap space"; +pub const REQUESTED_SIZE_TOO_LARGE: &str = "Requested size to allocate is too large"; + +pub struct FreeingBumpHeapAllocator { + bumper: u32, + heads: [u32; N], + heap: MemoryRef, + max_heap_size: u32, + ptr_offset: u32, + total_size: u32, +} + +impl FreeingBumpHeapAllocator { + + /// Creates a new allocation heap which follows a freeing-bump strategy. + /// The maximum size which can be allocated at once is 16 MiB. + /// + /// # Arguments + /// + /// * `ptr_offset` - The pointers returned by `allocate()` start from this + /// offset on. The pointer offset needs to be aligned to a multiple of 8, + /// hence a padding might be added to align `ptr_offset` properly. + /// + /// * `heap_size` - The size available to this heap instance (in bytes) for + /// allocating memory. + /// + /// * `heap` - A `MemoryRef` to the available `MemoryInstance` which is + /// used as the heap. + /// + pub fn new(mem: MemoryRef) -> Self { + let current_size: Bytes = mem.current_size().into(); + let current_size = current_size.0 as u32; + let used_size = mem.used_size().0 as u32; + let heap_size = current_size - used_size; + + let mut ptr_offset = used_size; + let padding = ptr_offset % ALIGNMENT; + if padding != 0 { + ptr_offset += ALIGNMENT - padding; + } + + FreeingBumpHeapAllocator { + bumper: 0, + heads: [0; N], + heap: mem, + max_heap_size: heap_size, + ptr_offset: ptr_offset, + total_size: 0, + } + } + + /// Gets requested number of bytes to allocate and returns a pointer. + /// The maximum size which can be allocated at once is 16 MiB. + pub fn allocate(&mut self, size: u32) -> Result { + if size > MAX_POSSIBLE_ALLOCATION { + return Err(UserError(REQUESTED_SIZE_TOO_LARGE)); + } + + let size = size.max(8); + let item_size = size.next_power_of_two(); + if item_size + 8 + self.total_size > self.max_heap_size { + return Err(UserError(OUT_OF_SPACE)); + } + + let list_index = (item_size.trailing_zeros() - 3) as usize; + let ptr: u32 = if self.heads[list_index] != 0 { + // Something from the free list + let item = self.heads[list_index]; + let four_bytes = self.get_heap_4bytes(item) + .map_err(|_| UserError("Unable to get bytes at pointer taken from list of free items"))?; + self.heads[list_index] = FreeingBumpHeapAllocator::le_bytes_to_u32(four_bytes); + item + 8 + } else { + // Nothing to be freed. Bump. + self.bump(item_size + 8) + 8 + }; + + for i in 1..8 { + self.set_heap(ptr - i, 255) + .map_err(|_| UserError("Unable to successively write bytes into heap at pointer prefix"))?; + } + + self.set_heap(ptr - 8, list_index as u8) + .map_err(|_| UserError("Unable to write byte into heap at pointer prefix"))?; + + self.total_size = self.total_size + item_size + 8; + trace!(target: "wasm-heap", "Heap size is {} bytes after allocation", self.total_size); + + Ok(self.ptr_offset + ptr) + } + + /// Deallocates the space which was allocated for a pointer. + pub fn deallocate(&mut self, ptr: u32) -> Result<(), UserError> { + let ptr = ptr - self.ptr_offset; + if ptr < 8 { + return Err(UserError("Invalid pointer for deallocation")); + } + + let list_index = self.get_heap_byte(ptr - 8) + .map_err(|_| UserError("Unable to access pointer prefix"))? as usize; + for i in 1..8 { + let heap_byte = self.get_heap_byte(ptr - i) + .map_err(|_| UserError("Unable to write single bytes into heap at pointer"))?; + debug_assert!(heap_byte == 255) + } + let tail = self.heads[list_index]; + self.heads[list_index] = ptr - 8; + + let mut slice = self.get_heap_4bytes(ptr - 8) + .map_err(|_| UserError("Unable to get 4 bytes from heap at pointer prefix"))?; + FreeingBumpHeapAllocator::write_u32_into_le_bytes(tail, &mut slice); + self.set_heap_4bytes(ptr - 8, slice) + .map_err(|_| UserError("Unable to write 4 bytes into heap at pointer prefix"))?; + + let item_size = FreeingBumpHeapAllocator::get_item_size_from_index(list_index); + self.total_size = self.total_size.checked_sub(item_size as u32 + 8) + .ok_or_else(|| UserError("Unable to subtract from total heap size without overflow"))?; + trace!(target: "wasm-heap", "Heap size is {} bytes after deallocation", self.total_size); + + Ok(()) + } + + fn bump(&mut self, n: u32) -> u32 { + let res = self.bumper; + self.bumper += n; + res + } + + fn le_bytes_to_u32(arr: [u8; 4]) -> u32 { + let bytes = [arr[0], arr[1], arr[2], arr[3]]; + unsafe { std::mem::transmute::<[u8; 4], u32>(bytes) }.to_le() + } + + fn write_u32_into_le_bytes(bytes: u32, slice: &mut [u8]) { + let bytes: [u8; 4] = unsafe { std::mem::transmute::(bytes.to_le()) }; + for i in 0..4 { slice[i] = bytes[i]; } + } + + fn get_item_size_from_index(index: usize) -> usize { + // we shift 1 by three places, since the first possible item size is 8 + 1 << 3 << index + } + + fn get_heap_4bytes(&mut self, ptr: u32) -> Result<[u8; 4], Error> { + let mut arr = [0u8; 4]; + self.heap.get_into(self.ptr_offset + ptr, &mut arr)?; + Ok(arr) + } + + fn get_heap_byte(&mut self, ptr: u32) -> Result { + let mut arr = [0u8; 1]; + self.heap.get_into(self.ptr_offset + ptr, &mut arr)?; + Ok(arr[0]) + } + + fn set_heap(&mut self, ptr: u32, value: u8) -> Result<(), Error> { + self.heap.set(self.ptr_offset + ptr, &[value]) + } + + fn set_heap_4bytes(&mut self, ptr: u32, value: [u8; 4]) -> Result<(), Error> { + self.heap.set(self.ptr_offset + ptr, &value) + } + +} + +#[cfg(test)] +mod tests { + use super::*; + use wasmi::MemoryInstance; + use wasmi::memory_units::*; + + const PAGE_SIZE: u32 = 65536; + + fn set_offset(mem: MemoryRef, offset: usize) { + let offset: Vec = vec![255; offset]; + mem.set(0, &offset).unwrap(); + } + + #[test] + fn should_allocate_properly() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(1).unwrap(); + + // then + assert_eq!(ptr, 8); + } + + #[test] + fn should_always_align_pointers_to_multiples_of_8() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + set_offset(mem.clone(), 13); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(1).unwrap(); + + // then + // the pointer must start at the next multiple of 8 from 13 + // + the prefix of 8 bytes. + assert_eq!(ptr, 24); + } + + #[test] + fn should_increment_pointers_properly() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr1 = heap.allocate(1).unwrap(); + let ptr2 = heap.allocate(9).unwrap(); + let ptr3 = heap.allocate(1).unwrap(); + + // then + // a prefix of 8 bytes is prepended to each pointer + assert_eq!(ptr1, 8); + + // the prefix of 8 bytes + the content of ptr1 padded to the lowest possible + // item size of 8 bytes + the prefix of ptr1 + assert_eq!(ptr2, 24); + + // ptr2 + its content of 16 bytes + the prefix of 8 bytes + assert_eq!(ptr3, 24 + 16 + 8); + } + + #[test] + fn should_free_properly() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + let ptr1 = heap.allocate(1).unwrap(); + // the prefix of 8 bytes is prepended to the pointer + assert_eq!(ptr1, 8); + + let ptr2 = heap.allocate(1).unwrap(); + // the prefix of 8 bytes + the content of ptr 1 is prepended to the pointer + assert_eq!(ptr2, 24); + + // when + heap.deallocate(ptr2).unwrap(); + + // then + // then the heads table should contain a pointer to the + // prefix of ptr2 in the leftmost entry + assert_eq!(heap.heads[0], ptr2 - 8); + } + + #[test] + fn should_deallocate_and_reallocate_properly() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + set_offset(mem.clone(), 13); + let padded_offset = 16; + let mut heap = FreeingBumpHeapAllocator::new(mem); + + let ptr1 = heap.allocate(1).unwrap(); + // the prefix of 8 bytes is prepended to the pointer + assert_eq!(ptr1, padded_offset + 8); + + let ptr2 = heap.allocate(9).unwrap(); + // the padded_offset + the previously allocated ptr (8 bytes prefix + + // 8 bytes content) + the prefix of 8 bytes which is prepended to the + // current pointer + assert_eq!(ptr2, padded_offset + 16 + 8); + + // when + heap.deallocate(ptr2).unwrap(); + let ptr3 = heap.allocate(9).unwrap(); + + // then + // should have re-allocated + assert_eq!(ptr3, padded_offset + 16 + 8); + assert_eq!(heap.heads, [0; N]); + } + + #[test] + fn should_build_linked_list_of_free_areas_properly() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + let ptr1 = heap.allocate(8).unwrap(); + let ptr2 = heap.allocate(8).unwrap(); + let ptr3 = heap.allocate(8).unwrap(); + + // when + heap.deallocate(ptr1).unwrap(); + heap.deallocate(ptr2).unwrap(); + heap.deallocate(ptr3).unwrap(); + + // then + let mut expected = [0; N]; + expected[0] = ptr3 - 8; + assert_eq!(heap.heads, expected); + + let ptr4 = heap.allocate(8).unwrap(); + assert_eq!(ptr4, ptr3); + + expected[0] = ptr2 - 8; + assert_eq!(heap.heads, expected); + } + + #[test] + fn should_not_allocate_if_too_large() { + // given + let mem = MemoryInstance::alloc(Pages(1), Some(Pages(1))).unwrap(); + set_offset(mem.clone(), 13); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(PAGE_SIZE - 13); + + // then + assert_eq!(ptr.is_err(), true); + if let Err(err) = ptr { + assert_eq!(err, UserError(OUT_OF_SPACE)); + } + } + + #[test] + fn should_not_allocate_if_full() { + // given + let mem = MemoryInstance::alloc(Pages(1), Some(Pages(1))).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + let ptr1 = heap.allocate((PAGE_SIZE / 2) - 8).unwrap(); + assert_eq!(ptr1, 8); + + // when + let ptr2 = heap.allocate(PAGE_SIZE / 2); + + // then + // there is no room for another half page incl. its 8 byte prefix + assert_eq!(ptr2.is_err(), true); + if let Err(err) = ptr2 { + assert_eq!(err, UserError(OUT_OF_SPACE)); + } + } + + #[test] + fn should_allocate_max_possible_allocation_size() { + // given + let pages_needed = (MAX_POSSIBLE_ALLOCATION as usize / PAGE_SIZE as usize) + 1; + let mem = MemoryInstance::alloc(Pages(pages_needed), Some(Pages(pages_needed))).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(MAX_POSSIBLE_ALLOCATION).unwrap(); + + // then + assert_eq!(ptr, 8); + } + + #[test] + fn should_not_allocate_if_requested_size_too_large() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(MAX_POSSIBLE_ALLOCATION + 1); + + // then + assert_eq!(ptr.is_err(), true); + if let Err(err) = ptr { + assert_eq!(err, UserError(REQUESTED_SIZE_TOO_LARGE)); + } + } + + #[test] + fn should_include_prefixes_in_total_heap_size() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + set_offset(mem.clone(), 1); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + // an item size of 16 must be used then + heap.allocate(9).unwrap(); + + // then + assert_eq!(heap.total_size, 8 + 16); + } + + #[test] + fn should_calculate_total_heap_size_to_zero() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + set_offset(mem.clone(), 13); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + let ptr = heap.allocate(42).unwrap(); + assert_eq!(ptr, 16 + 8); + heap.deallocate(ptr).unwrap(); + + // then + assert_eq!(heap.total_size, 0); + } + + #[test] + fn should_calculate_total_size_of_zero() { + // given + let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + set_offset(mem.clone(), 19); + let mut heap = FreeingBumpHeapAllocator::new(mem); + + // when + for _ in 1..10 { + let ptr = heap.allocate(42).unwrap(); + heap.deallocate(ptr).unwrap(); + } + + // then + assert_eq!(heap.total_size, 0); + } + + #[test] + fn should_write_u32_correctly_into_le() { + // given + let mut heap = vec![0; 5]; + + // when + FreeingBumpHeapAllocator::write_u32_into_le_bytes(1, &mut heap[0..4]); + + // then + assert_eq!(heap, [1, 0, 0, 0, 0]); + } + + #[test] + fn should_write_u32_max_correctly_into_le() { + // given + let mut heap = vec![0; 5]; + + // when + FreeingBumpHeapAllocator::write_u32_into_le_bytes(u32::max_value(), &mut heap[0..4]); + + // then + assert_eq!(heap, [255, 255, 255, 255, 0]); + } + + #[test] + fn should_get_item_size_from_index() { + // given + let index = 0; + + // when + let item_size = FreeingBumpHeapAllocator::get_item_size_from_index(index); + + // then + assert_eq!(item_size, 8); + } + + #[test] + fn should_get_max_item_size_from_index() { + // given + let index = 21; + + // when + let item_size = FreeingBumpHeapAllocator::get_item_size_from_index(index); + + // then + assert_eq!(item_size as u32, MAX_POSSIBLE_ALLOCATION); + } + +} diff --git a/core/executor/src/error.rs b/core/executor/src/error.rs index 330eef90283962e5100181535323d380e06ff24c..b27ccf01bf4cef520c3e22d0d9ce8923f7456f5c 100644 --- a/core/executor/src/error.rs +++ b/core/executor/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,17 @@ //! Rust executor possible errors. +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/substrate/issues/1547 +#![allow(deprecated)] + use state_machine; use serializer; use wasmi; +use error_chain::{ + error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind +}; error_chain! { foreign_links { diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index 5f05b33f5385208b3ae5cc202e6d41669282ad47..fa7cc71eea6d6273866f9ac53244cf548629c6cf 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,52 +28,23 @@ #![warn(missing_docs)] #![recursion_limit="128"] -extern crate parity_codec as codec; -extern crate sr_io as runtime_io; -#[cfg_attr(test, macro_use)] -extern crate substrate_primitives as primitives; -extern crate substrate_serializer as serializer; -extern crate substrate_state_machine as state_machine; -extern crate sr_version as runtime_version; -extern crate substrate_trie as trie; - -extern crate wasmi; -extern crate byteorder; -extern crate parking_lot; - -#[macro_use] -extern crate log; - -#[macro_use] -extern crate lazy_static; - -#[macro_use] -extern crate error_chain; - -#[cfg(test)] -extern crate assert_matches; - -#[cfg(test)] -extern crate wabt; - -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - #[macro_use] mod wasm_utils; mod wasm_executor; #[macro_use] mod native_executor; mod sandbox; +mod allocator; pub mod error; +pub use wasmi; pub use wasm_executor::WasmExecutor; pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; pub use state_machine::Externalities; pub use runtime_version::{RuntimeVersion, NativeVersion}; -pub use codec::Codec; -use primitives::Blake2Hasher; +pub use parity_codec::Codec; +#[doc(hidden)] +pub use primitives::Blake2Hasher; /// Provides runtime information. pub trait RuntimeInfo { @@ -84,7 +55,5 @@ pub trait RuntimeInfo { fn runtime_version> ( &self, ext: &mut E, - heap_pages: usize, - code: &[u8] ) -> Option; } diff --git a/core/executor/src/native_executor.rs b/core/executor/src/native_executor.rs index 15cc8abac3edc52bbf2a06d87a1addfb1ae5e760..0944cbdbbdd608007486921673533100641fa4a0 100644 --- a/core/executor/src/native_executor.rs +++ b/core/executor/src/native_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,38 +14,34 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use error::{Error, ErrorKind, Result}; +use std::{borrow::BorrowMut, result, cell::{RefMut, RefCell}}; +use crate::error::{Error, ErrorKind, Result}; use state_machine::{CodeExecutor, Externalities}; -use wasm_executor::WasmExecutor; -use wasmi::Module as WasmModule; +use crate::wasm_executor::WasmExecutor; +use wasmi::{Module as WasmModule, ModuleRef as WasmModuleInstanceRef}; use runtime_version::{NativeVersion, RuntimeVersion}; -use std::collections::HashMap; -use codec::Decode; -use primitives::hashing::blake2_256; -use parking_lot::{Mutex, MutexGuard}; -use RuntimeInfo; -use primitives::Blake2Hasher; +use std::{collections::HashMap, panic::UnwindSafe}; +use parity_codec::{Decode, Encode}; +use crate::RuntimeInfo; +use primitives::{Blake2Hasher, NativeOrEncoded}; +use primitives::storage::well_known_keys; +use log::trace; + +/// Default num of pages for the heap +const DEFAULT_HEAP_PAGES: u64 = 1024; // For the internal Runtime Cache: // Is it compatible enough to run this natively or do we need to fall back on the WasmModule enum RuntimePreproc { InvalidCode, - ValidCode(WasmModule, Option), + ValidCode(WasmModuleInstanceRef, Option), } type CacheType = HashMap<[u8; 32], RuntimePreproc>; -lazy_static! { - static ref RUNTIMES_CACHE: Mutex = Mutex::new(HashMap::new()); -} - -// helper function to generate low-over-head caching_keys -// it is asserted that part of the audit process that any potential on-chain code change -// will have done is to ensure that the two-x hash is different to that of any other -// :code value from the same chain -fn gen_cache_key(code: &[u8]) -> [u8; 32] { - blake2_256(code) +thread_local! { + static RUNTIMES_CACHE: RefCell = RefCell::new(HashMap::new()); } /// fetch a runtime version from the cache or if there is no cached version yet, create @@ -53,45 +49,65 @@ fn gen_cache_key(code: &[u8]) -> [u8; 32] { /// can be used by comparing returned RuntimeVersion to `ref_version` fn fetch_cached_runtime_version<'a, E: Externalities>( wasm_executor: &WasmExecutor, - cache: &'a mut MutexGuard, + cache: &'a mut RefMut, ext: &mut E, - heap_pages: usize, - code: &[u8] -) -> Result<(&'a WasmModule, &'a Option)> { - let maybe_runtime_preproc = cache.entry(gen_cache_key(code)) - .or_insert_with(|| match WasmModule::from_buffer(code) { - Ok(module) => { - let version = wasm_executor.call_in_wasm_module(ext, heap_pages, &module, "Core_version", &[]) - .ok() - .and_then(|v| RuntimeVersion::decode(&mut v.as_slice())); - RuntimePreproc::ValidCode(module, version) - } - Err(e) => { - trace!(target: "executor", "Invalid code presented to executor ({:?})", e); - RuntimePreproc::InvalidCode + default_heap_pages: Option, +) -> Result<(&'a WasmModuleInstanceRef, &'a Option)> { + + let code_hash = match ext.storage_hash(well_known_keys::CODE) { + Some(code_hash) => code_hash, + None => return Err(ErrorKind::InvalidCode(vec![]).into()), + }; + let maybe_runtime_preproc = cache.borrow_mut().entry(code_hash.into()) + .or_insert_with(|| { + let code = match ext.storage(well_known_keys::CODE) { + Some(code) => code, + None => return RuntimePreproc::InvalidCode, + }; + let heap_pages = ext.storage(well_known_keys::HEAP_PAGES) + .and_then(|pages| u64::decode(&mut &pages[..])) + .or(default_heap_pages) + .unwrap_or(DEFAULT_HEAP_PAGES); + match WasmModule::from_buffer(code) + .map_err(|_| ErrorKind::InvalidCode(vec![]).into()) + .and_then(|module| wasm_executor.prepare_module(ext, heap_pages as usize, &module)) + { + Ok(module) => { + let version = wasm_executor.call_in_wasm_module(ext, &module, "Core_version", &[]) + .ok() + .and_then(|v| RuntimeVersion::decode(&mut v.as_slice())); + RuntimePreproc::ValidCode(module, version) + } + Err(e) => { + trace!(target: "executor", "Invalid code presented to executor ({:?})", e); + RuntimePreproc::InvalidCode + } } }); match maybe_runtime_preproc { - RuntimePreproc::InvalidCode => Err(ErrorKind::InvalidCode(code.into()).into()), - RuntimePreproc::ValidCode(m, v) => Ok((m, v)), + RuntimePreproc::InvalidCode => { + let code = ext.storage(well_known_keys::CODE).unwrap_or(vec![]); + Err(ErrorKind::InvalidCode(code).into()) + }, + RuntimePreproc::ValidCode(m, v) => { + Ok((m, v)) + } } } fn safe_call(f: F) -> Result - where F: ::std::panic::UnwindSafe + FnOnce() -> U + where F: UnwindSafe + FnOnce() -> U { - // Substrate uses custom panic hook that terminates process on panic. Disable it for the native call. - let hook = ::std::panic::take_hook(); - let result = ::std::panic::catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()); - ::std::panic::set_hook(hook); - result + // Substrate uses custom panic hook that terminates process on panic. Disable termination for the native call. + let _guard = panic_handler::AbortGuard::new(false); + ::std::panic::catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()) } /// Set up the externalities and safe calling environment to execute calls to a native runtime. /// /// If the inner closure panics, it will be caught and return an error. pub fn with_native_environment(ext: &mut Externalities, f: F) -> Result -where F: ::std::panic::UnwindSafe + FnOnce() -> U + where F: UnwindSafe + FnOnce() -> U { ::runtime_io::with_externalities(ext, move || safe_call(f)) } @@ -110,7 +126,7 @@ pub trait NativeExecutionDispatch: Send + Sync { fn native_version() -> NativeVersion; /// Construct corresponding `NativeExecutor` - fn new() -> NativeExecutor where Self: Sized; + fn new(default_heap_pages: Option) -> NativeExecutor where Self: Sized; } /// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence @@ -123,15 +139,18 @@ pub struct NativeExecutor { fallback: WasmExecutor, /// Native runtime version info. native_version: NativeVersion, + /// The default number of 64KB pages to allocate for Wasm execution. + default_heap_pages: Option, } impl NativeExecutor { /// Create new instance. - pub fn new() -> Self { + pub fn new(default_heap_pages: Option) -> Self { NativeExecutor { _dummy: Default::default(), fallback: WasmExecutor::new(), native_version: D::native_version(), + default_heap_pages, } } } @@ -142,6 +161,7 @@ impl Clone for NativeExecutor { _dummy: Default::default(), fallback: self.fallback.clone(), native_version: D::native_version(), + default_heap_pages: self.default_heap_pages, } } } @@ -154,43 +174,94 @@ impl RuntimeInfo for NativeExecutor { fn runtime_version>( &self, ext: &mut E, - heap_pages: usize, - code: &[u8], ) -> Option { - fetch_cached_runtime_version(&self.fallback, &mut RUNTIMES_CACHE.lock(), ext, heap_pages, code).ok()?.1.clone() + RUNTIMES_CACHE.with(|c| + fetch_cached_runtime_version(&self.fallback, &mut c.borrow_mut(), ext, self.default_heap_pages) + .ok()?.1.clone() + ) } } impl CodeExecutor for NativeExecutor { type Error = Error; - fn call>( + fn call + < + E: Externalities, + R:Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe + >( &self, ext: &mut E, - heap_pages: usize, - code: &[u8], method: &str, data: &[u8], use_native: bool, - ) -> (Result>, bool) { - let mut c = RUNTIMES_CACHE.lock(); - let (module, onchain_version) = match fetch_cached_runtime_version(&self.fallback, &mut c, ext, heap_pages, code) { - Ok((module, onchain_version)) => (module, onchain_version), - Err(_) => return (Err(ErrorKind::InvalidCode(code.into()).into()), false), - }; - match (use_native, onchain_version.as_ref().map_or(false, |v| v.can_call_with(&self.native_version.runtime_version))) { - (_, false) => { - trace!(target: "executor", "Request for native execution failed (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"".into(), |v| format!("{}", v))); - (self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false) - } - (false, _) => { - (self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false) + native_call: Option, + ) -> (Result>, bool) { + RUNTIMES_CACHE.with(|c| { + let mut c = c.borrow_mut(); + let (module, onchain_version) = match fetch_cached_runtime_version( + &self.fallback, &mut c, ext, self.default_heap_pages) { + Ok((module, onchain_version)) => (module, onchain_version), + Err(e) => return (Err(e), false), + }; + match ( + use_native, + onchain_version + .as_ref() + .map_or(false, |v| v.can_call_with(&self.native_version.runtime_version)), + native_call, + ) { + (_, false, _) => { + trace!( + target: "executor", + "Request for native execution failed (native: {}, chain: {})", + self.native_version.runtime_version, + onchain_version + .as_ref() + .map_or_else(||"".into(), |v| format!("{}", v)) + ); + ( + self.fallback + .call_in_wasm_module(ext, module, method, data) + .map(NativeOrEncoded::Encoded), + false + ) + } + (false, _, _) => { + ( + self.fallback + .call_in_wasm_module(ext, module, method, data) + .map(NativeOrEncoded::Encoded), + false + ) + } + (true, true, Some(call)) => { + trace!( + target: "executor", + "Request for native execution with native call succeeded (native: {}, chain: {}).", + self.native_version.runtime_version, + onchain_version + .as_ref() + .map_or_else(||"".into(), |v| format!("{}", v)) + ); + ( + with_native_environment(ext, move || (call)()) + .and_then(|r| r.map(NativeOrEncoded::Native).map_err(Into::into)), + true + ) + } + _ => { + trace!( + target: "executor", + "Request for native execution succeeded (native: {}, chain: {})", + self.native_version.runtime_version, + onchain_version.as_ref().map_or_else(||"".into(), |v| format!("{}", v)) + ); + (D::dispatch(ext, method, data).map(NativeOrEncoded::Encoded), true) + } } - _ => { - trace!(target: "executor", "Request for native execution succeeded (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"".into(), |v| format!("{}", v))); - (D::dispatch(ext, method, data), true) - } - } + }) } } @@ -202,15 +273,13 @@ macro_rules! native_executor_instance { native_executor_instance!(IMPL $name, $dispatcher, $version, $code); }; (IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => { - // TODO: this is not so great – I think I should go back to have dispatch take a type param and modify this macro to accept a type param and then pass it in from the test-client instead - use primitives::Blake2Hasher as _Blake2Hasher; impl $crate::NativeExecutionDispatch for $name { fn native_equivalent() -> &'static [u8] { // WARNING!!! This assumes that the runtime was built *before* the main project. Until we // get a proper build script, this must be strictly adhered to or things will go wrong. $code } - fn dispatch(ext: &mut $crate::Externalities<_Blake2Hasher>, method: &str, data: &[u8]) -> $crate::error::Result> { + fn dispatch(ext: &mut $crate::Externalities<$crate::Blake2Hasher>, method: &str, data: &[u8]) -> $crate::error::Result> { $crate::with_native_environment(ext, move || $dispatcher(method, data))? .ok_or_else(|| $crate::error::ErrorKind::MethodNotFound(method.to_owned()).into()) } @@ -219,8 +288,8 @@ macro_rules! native_executor_instance { $version() } - fn new() -> $crate::NativeExecutor<$name> { - $crate::NativeExecutor::new() + fn new(default_heap_pages: Option) -> $crate::NativeExecutor<$name> { + $crate::NativeExecutor::new(default_heap_pages) } } } diff --git a/core/executor/src/sandbox.rs b/core/executor/src/sandbox.rs index 87fb4083b38becb404080fb70b6a83f89cafc0ff..cc21d762bec11fd13645a5a971640e5ddedd155b 100644 --- a/core/executor/src/sandbox.rs +++ b/core/executor/src/sandbox.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,9 +20,9 @@ use std::collections::HashMap; use std::rc::Rc; -use codec::{Decode, Encode}; +use parity_codec::{Decode, Encode}; use primitives::sandbox as sandbox_primitives; -use wasm_utils::UserError; +use crate::wasm_utils::UserError; use wasmi; use wasmi::memory_units::Pages; use wasmi::{ @@ -148,13 +148,21 @@ pub trait SandboxCapabilities { /// Allocate space of the specified length in the supervisor memory. /// + /// # Errors + /// + /// Returns `Err` if allocation not possible or errors during heap management. + /// /// Returns pointer to the allocated block. - fn allocate(&mut self, len: u32) -> u32; + fn allocate(&mut self, len: u32) -> Result; /// Deallocate space specified by the pointer that was previously returned by [`allocate`]. /// + /// # Errors + /// + /// Returns `Err` if deallocation not possible or because of errors in heap management. + /// /// [`allocate`]: #tymethod.allocate - fn deallocate(&mut self, ptr: u32); + fn deallocate(&mut self, ptr: u32) -> Result<(), UserError>; /// Write `data` into the supervisor memory at offset specified by `ptr`. /// @@ -232,7 +240,7 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< // Move serialized arguments inside the memory and invoke dispatch thunk and // then free allocated memory. let invoke_args_ptr = self.supervisor_externals - .allocate(invoke_args_data.len() as u32); + .allocate(invoke_args_data.len() as u32)?; self.supervisor_externals .write_memory(invoke_args_ptr, &invoke_args_data)?; let result = ::wasmi::FuncInstance::invoke( @@ -245,7 +253,7 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< ], self.supervisor_externals, ); - self.supervisor_externals.deallocate(invoke_args_ptr); + self.supervisor_externals.deallocate(invoke_args_ptr)?; // dispatch_thunk returns pointer to serialized arguments. let (serialized_result_val_ptr, serialized_result_val_len) = match result { @@ -264,7 +272,7 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< let serialized_result_val = self.supervisor_externals .read_memory(serialized_result_val_ptr, serialized_result_val_len)?; self.supervisor_externals - .deallocate(serialized_result_val_ptr); + .deallocate(serialized_result_val_ptr)?; // We do not have to check the signature here, because it's automatically // checked by wasmi. @@ -558,7 +566,9 @@ impl Store { #[cfg(test)] mod tests { use primitives::{Blake2Hasher}; - use wasm_executor::WasmExecutor; + use crate::allocator; + use crate::sandbox::trap; + use crate::wasm_executor::WasmExecutor; use state_machine::TestExternalities; use wabt; @@ -615,6 +625,32 @@ mod tests { ); } + #[test] + fn sandbox_should_trap_when_heap_exhausted() { + let mut ext = TestExternalities::::default(); + let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (func (export "call") + i32.const 0 + call $assert + ) + ) + "#).unwrap(); + + let res = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_exhaust_heap", &code); + assert_eq!(res.is_err(), true); + if let Err(err) = res { + let inner_err = err.iter().next().unwrap(); + assert_eq!( + format!("{}", inner_err), + format!("{}", wasmi::Error::Trap(trap(allocator::OUT_OF_SPACE))) + ); + } + } + #[test] fn start_called() { let mut ext = TestExternalities::::default(); diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs index 7480b6195014a881cdd4cf68e611ef50e1b6ace8..7e6833bb7839f0d0e4f18d8e6f44cd71908cb363 100644 --- a/core/executor/src/wasm_executor.rs +++ b/core/executor/src/wasm_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,52 +17,25 @@ //! Rust implementation of Substrate contracts. use std::collections::HashMap; +use tiny_keccak; +use secp256k1; use wasmi::{ - Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder + Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, }; -use wasmi::RuntimeValue::{I32, I64}; -use wasmi::memory_units::{Pages, Bytes}; +use wasmi::RuntimeValue::{I32, I64, self}; +use wasmi::memory_units::{Pages}; use state_machine::Externalities; -use error::{Error, ErrorKind, Result}; -use wasm_utils::UserError; -use primitives::{blake2_256, twox_128, twox_256, ed25519}; +use crate::error::{Error, ErrorKind, Result}; +use crate::wasm_utils::UserError; +use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519, Pair}; use primitives::hexdisplay::HexDisplay; use primitives::sandbox as sandbox_primitives; use primitives::{H256, Blake2Hasher}; use trie::ordered_trie_root; -use sandbox; - - -struct Heap { - end: u32, -} - -impl Heap { - /// Construct new `Heap` struct with a given number of pages. - /// - /// Returns `Err` if the heap couldn't allocate required - /// number of pages. - /// - /// This could mean that wasm binary specifies memory - /// limit and we are trying to allocate beyond that limit. - fn new(memory: &MemoryRef, pages: usize) -> Result { - let prev_page_count = memory.initial(); - memory.grow(Pages(pages)).map_err(|_| Error::from(ErrorKind::Runtime))?; - Ok(Heap { - end: Bytes::from(prev_page_count).0 as u32, - }) - } - - fn allocate(&mut self, size: u32) -> u32 { - let r = self.end; - self.end += size; - r - } - - fn deallocate(&mut self, _offset: u32) { - } -} +use crate::sandbox; +use crate::allocator; +use log::trace; #[cfg(feature="wasm-extern-trace")] macro_rules! debug_trace { @@ -75,7 +48,7 @@ macro_rules! debug_trace { struct FunctionExecutor<'e, E: Externalities + 'e> { sandbox_store: sandbox::Store, - heap: Heap, + heap: allocator::FreeingBumpHeapAllocator, memory: MemoryRef, table: Option, ext: &'e mut E, @@ -83,10 +56,10 @@ struct FunctionExecutor<'e, E: Externalities + 'e> { } impl<'e, E: Externalities> FunctionExecutor<'e, E> { - fn new(m: MemoryRef, heap_pages: usize, t: Option, e: &'e mut E) -> Result { + fn new(m: MemoryRef, t: Option, e: &'e mut E) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), - heap: Heap::new(&m, heap_pages)?, + heap: allocator::FreeingBumpHeapAllocator::new(m.clone()), memory: m, table: t, ext: e, @@ -102,10 +75,10 @@ impl<'e, E: Externalities> sandbox::SandboxCapabilities for Functi fn store_mut(&mut self) -> &mut sandbox::Store { &mut self.sandbox_store } - fn allocate(&mut self, len: u32) -> u32 { + fn allocate(&mut self, len: u32) -> ::std::result::Result { self.heap.allocate(len) } - fn deallocate(&mut self, ptr: u32) { + fn deallocate(&mut self, ptr: u32) -> ::std::result::Result<(), UserError> { self.heap.deallocate(ptr) } fn write_memory(&mut self, ptr: u32, data: &[u8]) -> ::std::result::Result<(), UserError> { @@ -140,7 +113,6 @@ impl ReadPrimitive for MemoryInstance { } } -// TODO: this macro does not support `where` clauses and that seems somewhat tricky to add impl_function_executor!(this: FunctionExecutor<'e, E>, ext_print_utf8(utf8_data: *const u8, utf8_len: u32) => { if let Ok(utf8) = this.memory.get(utf8_data, utf8_len as usize) { @@ -161,12 +133,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_malloc(size: usize) -> *mut u8 => { - let r = this.heap.allocate(size); + let r = this.heap.allocate(size)?; debug_trace!(target: "sr-io", "malloc {} bytes at {}", size, r); Ok(r) }, ext_free(addr: *mut u8) => { - this.heap.deallocate(addr); + this.heap.deallocate(addr)?; debug_trace!(target: "sr-io", "free {}", addr); Ok(()) }, @@ -280,7 +252,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ); if let Some(value) = maybe_value { - let offset = this.heap.allocate(value.len() as u32) as u32; + let offset = this.heap.allocate(value.len() as u32)? as u32; this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_storage"))?; @@ -319,7 +291,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ); if let Some(value) = maybe_value { - let offset = this.heap.allocate(value.len() as u32) as u32; + let offset = this.heap.allocate(value.len() as u32)? as u32; this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_child_storage"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_child_storage"))?; @@ -401,7 +373,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?; let r = this.ext.child_storage_root(&storage_key); if let Some(value) = r { - let offset = this.heap.allocate(value.len() as u32) as u32; + let offset = this.heap.allocate(value.len() as u32)? as u32; this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_child_storage_root"))?; @@ -421,10 +393,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, .map_err(|_| UserError("Invalid attempt to get parent_hash in ext_storage_changes_root"))?; parent_hash.as_mut().copy_from_slice(&raw_parent_hash[..]); let r = this.ext.storage_changes_root(parent_hash, parent_number); - if let Some(ref r) = r { + if let Some(r) = r { this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?; + Ok(1) + } else { + Ok(0) } - Ok(if r.is_some() { 1u32 } else { 0u32 }) }, ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => { let values = (0..lens_len) @@ -445,7 +419,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(this.ext.chain_id()) }, ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { - let result = if len == 0 { + let result: [u8; 16] = if len == 0 { let hashed = twox_128(&[0u8; 0]); debug_trace!(target: "xxhash", "XXhash: '' -> {}", HexDisplay::from(&hashed)); this.hash_lookup.insert(hashed.to_vec(), vec![]); @@ -469,7 +443,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { - let result = if len == 0 { + let result: [u8; 32] = if len == 0 { twox_256(&[0u8; 0]) } else { twox_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?) @@ -478,7 +452,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { - let result = if len == 0 { + let result: [u8; 32] = if len == 0 { blake2_256(&[0u8; 0]) } else { blake2_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?) @@ -486,6 +460,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?; Ok(()) }, + ext_keccak_256(data: *const u8, len: u32, out: *mut u8) => { + let result: [u8; 32] = if len == 0 { + tiny_keccak::keccak256(&[0u8; 0]) + } else { + tiny_keccak::keccak256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_keccak_256"))?) + }; + this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_keccak_256"))?; + Ok(()) + }, ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { let mut sig = [0u8; 64]; this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?; @@ -493,12 +476,50 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; - Ok(if ed25519::verify(&sig, &msg, &pubkey) { + Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { + 0 + } else { + 5 + }) + }, + ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { + let mut sig = [0u8; 64]; + this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_sr25519_verify"))?; + let mut pubkey = [0u8; 32]; + this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?; + let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?; + + Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 } else { 5 }) }, + ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32 => { + let mut sig = [0u8; 65]; + this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_secp256k1_ecdsa_recover"))?; + let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { + Ok(rs) => rs, + _ => return Ok(1), + }; + let v = match secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) { + Ok(v) => v, + _ => return Ok(2), + }; + + + let mut msg = [0u8; 32]; + this.memory.get_into(msg_data, &mut msg[..]).map_err(|_| UserError("Invalid attempt to get message in ext_secp256k1_ecdsa_recover"))?; + + let pubkey = match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { + Ok(pk) => pk, + _ => return Ok(3), + }; + + this.memory.set(pubkey_data, &pubkey.serialize()[1..65]).map_err(|_| UserError("Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover"))?; + + Ok(0) + }, ext_sandbox_instantiate( dispatch_thunk_idx: usize, wasm_ptr: *const u8, @@ -536,7 +557,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, args_ptr: *const u8, args_len: usize, return_val_ptr: *const u8, return_val_len: usize, state: usize) -> u32 => { - use codec::{Decode, Encode}; + use parity_codec::{Decode, Encode}; trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_idx); let export = this.memory.get(export_ptr, export_len as usize) @@ -618,17 +639,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, /// /// Executes the provided code in a sandboxed wasm runtime. #[derive(Debug, Clone)] -pub struct WasmExecutor { -} +pub struct WasmExecutor; impl WasmExecutor { /// Create a new instance. pub fn new() -> Self { - WasmExecutor{} + WasmExecutor } /// Call a given method in the given code. + /// + /// Signature of this method needs to be `(I32, I32) -> I64`. + /// /// This should be used for tests only. pub fn call>( &self, @@ -637,75 +660,154 @@ impl WasmExecutor { code: &[u8], method: &str, data: &[u8], - ) -> Result> { - let module = ::wasmi::Module::from_buffer(code).expect("all modules compiled with rustc are valid wasm code; qed"); - self.call_in_wasm_module(ext, heap_pages, &module, method, data) + ) -> Result> { + let module = ::wasmi::Module::from_buffer(code)?; + let module = self.prepare_module(ext, heap_pages, &module)?; + self.call_in_wasm_module(ext, &module, method, data) + } + + /// Call a given method with a custom signature in the given code. + /// + /// This should be used for tests only. + pub fn call_with_custom_signature< + E: Externalities, + F: FnOnce(&mut FnMut(&[u8]) -> Result) -> Result>, + FR: FnOnce(Option, &MemoryRef) -> Result>, + R, + >( + &self, + ext: &mut E, + heap_pages: usize, + code: &[u8], + method: &str, + create_parameters: F, + filter_result: FR, + ) -> Result { + let module = wasmi::Module::from_buffer(code)?; + let module = self.prepare_module(ext, heap_pages, &module)?; + self.call_in_wasm_module_with_custom_signature(ext, &module, method, create_parameters, filter_result) + } + + fn get_mem_instance(module: &ModuleRef) -> Result { + Ok(module + .export_by_name("memory") + .ok_or_else(|| Error::from(ErrorKind::InvalidMemoryReference))? + .as_memory() + .ok_or_else(|| Error::from(ErrorKind::InvalidMemoryReference))? + .clone()) } /// Call a given method in the given wasm-module runtime. pub fn call_in_wasm_module>( &self, ext: &mut E, - heap_pages: usize, - module: &Module, + module_instance: &ModuleRef, method: &str, data: &[u8], ) -> Result> { - // start module instantiation. Don't run 'start' function yet. - let intermediate_instance = ModuleInstance::new( - module, - &ImportsBuilder::new() - .with_resolver("env", FunctionExecutor::::resolver()) - )?; + self.call_in_wasm_module_with_custom_signature( + ext, + module_instance, + method, + |alloc| { + let offset = alloc(data)?; + Ok(vec![I32(offset as i32), I32(data.len() as i32)]) + }, + |res, memory| { + if let Some(I64(r)) = res { + let offset = r as u32; + let length = (r as u64 >> 32) as usize; + memory.get(offset, length).map_err(|_| ErrorKind::Runtime.into()).map(Some) + } else { + Ok(None) + } + } + ) + } + /// Call a given method in the given wasm-module runtime. + fn call_in_wasm_module_with_custom_signature< + E: Externalities, + F: FnOnce(&mut FnMut(&[u8]) -> Result) -> Result>, + FR: FnOnce(Option, &MemoryRef) -> Result>, + R, + >( + &self, + ext: &mut E, + module_instance: &ModuleRef, + method: &str, + create_parameters: F, + filter_result: FR, + ) -> Result { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. - let memory = intermediate_instance - .not_started_instance() - .export_by_name("memory") - // TODO: with code coming from the blockchain it isn't strictly been compiled with rustc anymore. - // these assumptions are probably not true anymore - .expect("all modules compiled with rustc should have an export named 'memory'; qed") - .as_memory() - .expect("in module generated by rustc export named 'memory' should be a memory; qed") - .clone(); - let table: Option = intermediate_instance - .not_started_instance() + let memory = Self::get_mem_instance(module_instance)?; + let table: Option = module_instance .export_by_name("__indirect_function_table") .and_then(|e| e.as_table().cloned()); - let mut fec = FunctionExecutor::new(memory.clone(), heap_pages, table, ext)?; - - // finish instantiation by running 'start' function (if any). - let instance = intermediate_instance.run_start(&mut fec)?; - let size = data.len() as u32; - let offset = fec.heap.allocate(size); - memory.set(offset, &data)?; + let low = memory.lowest_used(); + let used_mem = memory.used_size(); + let mut fec = FunctionExecutor::new(memory.clone(), table, ext)?; + let parameters = create_parameters(&mut |data: &[u8]| { + let offset = fec.heap.allocate(data.len() as u32).map_err(|_| ErrorKind::Runtime)?; + memory.set(offset, &data)?; + Ok(offset) + })?; - let result = instance.invoke_export( + let result = module_instance.invoke_export( method, - &[ - I32(offset as i32), - I32(size as i32) - ], + ¶meters, &mut fec ); - let returned = match result { - Ok(x) => x, + let result = match result { + Ok(val) => match filter_result(val, &memory)? { + Some(val) => Ok(val), + None => Err(ErrorKind::InvalidReturn.into()), + }, Err(e) => { - trace!(target: "wasm-executor", "Failed to execute code with {} pages", heap_pages); - return Err(e.into()) + trace!(target: "wasm-executor", "Failed to execute code with {} pages", memory.current_size().0); + Err(e.into()) }, }; - if let Some(I64(r)) = returned { - let offset = r as u32; - let length = (r >> 32) as u32 as usize; - memory.get(offset, length) - .map_err(|_| ErrorKind::Runtime.into()) - } else { - Err(ErrorKind::InvalidReturn.into()) + // cleanup module instance for next use + let new_low = memory.lowest_used(); + if new_low < low { + memory.zero(new_low as usize, (low - new_low) as usize)?; + memory.reset_lowest_used(low); } + memory.with_direct_access_mut(|buf| buf.resize(used_mem.0, 0)); + result + } + + /// Prepare module instance + pub fn prepare_module>( + &self, + ext: &mut E, + heap_pages: usize, + module: &Module, + ) -> Result + { + // start module instantiation. Don't run 'start' function yet. + let intermediate_instance = ModuleInstance::new( + module, + &ImportsBuilder::new() + .with_resolver("env", FunctionExecutor::::resolver()) + )?; + + // extract a reference to a linear memory, optional reference to a table + // and then initialize FunctionExecutor. + let memory = Self::get_mem_instance(intermediate_instance.not_started_instance())?; + memory.grow(Pages(heap_pages)).map_err(|_| Error::from(ErrorKind::Runtime))?; + let table: Option = intermediate_instance + .not_started_instance() + .export_by_name("__indirect_function_table") + .and_then(|e| e.as_table().cloned()); + let mut fec = FunctionExecutor::new(memory.clone(), table, ext)?; + + // finish instantiation by running 'start' function (if any). + Ok(intermediate_instance.run_start(&mut fec)?) } } @@ -713,8 +815,12 @@ impl WasmExecutor { #[cfg(test)] mod tests { use super::*; - use codec::Encode; + + use parity_codec::Encode; + use state_machine::TestExternalities; + use hex_literal::{hex, hex_impl}; + use primitives::map; #[test] fn returning_should_work() { @@ -733,6 +839,9 @@ mod tests { let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_panic", &[]); assert!(output.is_err()); + let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[]); + assert_eq!(output.unwrap(), vec![0u8; 0]); + let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[2]); assert!(output.is_err()); } @@ -824,7 +933,7 @@ mod tests { fn ed25519_verify_should_work() { let mut ext = TestExternalities::::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = ed25519::Pair::from_seed(&blake2_256(b"test")); + let key = ed25519::Pair::from_seed(blake2_256(b"test")); let sig = key.sign(b"all ok!"); let mut calldata = vec![]; calldata.extend_from_slice(key.public().as_ref()); @@ -846,6 +955,32 @@ mod tests { ); } + #[test] + fn sr25519_verify_should_work() { + let mut ext = TestExternalities::::default(); + let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + let key = sr25519::Pair::from_seed(blake2_256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + + assert_eq!( + WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata).unwrap(), + vec![1] + ); + + let other_sig = key.sign(b"all is not ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(other_sig.as_ref()); + + assert_eq!( + WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata).unwrap(), + vec![0] + ); + } + #[test] fn enumerated_trie_root_should_work() { let mut ext = TestExternalities::::default(); @@ -855,6 +990,4 @@ mod tests { ordered_trie_root::(vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()].iter()).as_fixed_bytes().encode() ); } - - } diff --git a/core/executor/src/wasm_utils.rs b/core/executor/src/wasm_utils.rs index 99af25cb164d1ef0fd9e44a20d4c647d78b53230..4ad9541dbd0d99baa3831c86b4f92c641bb933df 100644 --- a/core/executor/src/wasm_utils.rs +++ b/core/executor/src/wasm_utils.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ use wasmi::{ValueType, RuntimeValue, HostError}; use wasmi::nan_preserving_float::{F32, F64}; use std::fmt; -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct UserError(pub &'static str); impl fmt::Display for UserError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/core/executor/wasm/Cargo.lock b/core/executor/wasm/Cargo.lock index d5f2b2cacb54ed5cced30c55ba0f831fd4df24e5..8fa99afc3bf46ffe2660fc0de5a16e395b9a8c85 100644 --- a/core/executor/wasm/Cargo.lock +++ b/core/executor/wasm/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "arrayvec" version = "0.4.7" @@ -11,11 +13,6 @@ name = "byteorder" version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crunchy" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crunchy" version = "0.2.1" @@ -31,15 +28,23 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#e61df32342920f602a9d8d71caa5117c779d3ff1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#e61df32342920f602a9d8d71caa5117c779d3ff1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -49,20 +54,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "parity-codec" -version = "2.1.5" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-codec-derive" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "primitive-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -125,8 +150,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "sr-io" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -136,7 +161,7 @@ dependencies = [ name = "sr-sandbox" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -159,21 +184,17 @@ name = "substrate-primitives" version = "0.1.0" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", - "uint 0.5.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.14.9" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -181,9 +202,17 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "uint" -version = "0.5.0-beta.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -199,14 +228,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" -"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" -"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" -"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" +"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" @@ -215,6 +246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum uint 0.5.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4630460173a57c0af94b8306091e018025d988473f641a4af754b6cde980e1e3" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/core/executor/wasm/Cargo.toml b/core/executor/wasm/Cargo.toml index 091945e30644e08cd50288bc14358443f423f1d4..9683cd764eebbc4daaf05e670be8271a9b9d1b4a 100644 --- a/core/executor/wasm/Cargo.toml +++ b/core/executor/wasm/Cargo.toml @@ -2,13 +2,14 @@ name = "runtime-test" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [lib] crate-type = ["cdylib"] [dependencies] -sr-io = { path = "../../sr-io", version = "0.1", default-features = false } -sr-sandbox = { path = "../../sr-sandbox", version = "0.1", default-features = false } +runtime_io = { package = "sr-io", path = "../../sr-io", version = "0.1", default-features = false } +sandbox = { package = "sr-sandbox", path = "../../sr-sandbox", version = "0.1", default-features = false } substrate-primitives = { path = "../../primitives", default-features = false } [profile.release] diff --git a/core/executor/wasm/build.sh b/core/executor/wasm/build.sh index ecd7b675408738aaf7aa1bdabef322b243140cbd..c23ac076e210aa3d00c5550e18e40b4c9d90d09c 100755 --- a/core/executor/wasm/build.sh +++ b/core/executor/wasm/build.sh @@ -6,7 +6,7 @@ if cargo --version | grep -q "nightly"; then else CARGO_CMD="cargo +nightly" fi -$CARGO_CMD build --target=wasm32-unknown-unknown --release +CARGO_INCREMENTAL=0 RUSTFLAGS="-C link-arg=--export-table" $CARGO_CMD build --target=wasm32-unknown-unknown --release for i in test do wasm-gc target/wasm32-unknown-unknown/release/runtime_$i.wasm target/wasm32-unknown-unknown/release/runtime_$i.compact.wasm diff --git a/core/executor/wasm/src/lib.rs b/core/executor/wasm/src/lib.rs index b85ecafa5a8d13dcd79814927bd7d0d24a94c08f..dda9c617333a835e35169b6c1f1888e4018c9c91 100644 --- a/core/executor/wasm/src/lib.rs +++ b/core/executor/wasm/src/lib.rs @@ -6,13 +6,9 @@ extern crate alloc; use alloc::vec::Vec; use alloc::slice; -extern crate sr_io as runtime_io; -extern crate sr_sandbox as sandbox; -extern crate substrate_primitives; - use runtime_io::{ set_storage, storage, clear_prefix, print, blake2_256, - twox_128, twox_256, ed25519_verify, enumerated_trie_root + twox_128, twox_256, ed25519_verify, sr25519_verify, enumerated_trie_root }; macro_rules! impl_stubs { @@ -63,6 +59,7 @@ impl_stubs!( b"all ok!".to_vec() }, test_empty_return => |_| Vec::new(), + test_exhaust_heap => |_| Vec::with_capacity(16777216), test_panic => |_| panic!("test panic"), test_conditional_panic => |input: &[u8]| { if input.len() > 0 { @@ -83,6 +80,16 @@ impl_stubs!( let msg = b"all ok!"; [ed25519_verify(&sig, &msg[..], &pubkey) as u8].to_vec() }, + test_sr25519_verify => |input: &[u8]| { + let mut pubkey = [0; 32]; + let mut sig = [0; 64]; + + pubkey.copy_from_slice(&input[0..32]); + sig.copy_from_slice(&input[32..96]); + + let msg = b"all ok!"; + [sr25519_verify(&sig, &msg[..], &pubkey) as u8].to_vec() + }, test_enumerated_trie_root => |_| { enumerated_trie_root::(&[&b"zero"[..], &b"one"[..], &b"two"[..]]).to_vec() }, diff --git a/core/finality-grandpa/Cargo.toml b/core/finality-grandpa/Cargo.toml index 017eca9449c36ff0952c308c7db831095255aedb..070b073b99774ab0c4755e5c98de6890c5f23586 100644 --- a/core/finality-grandpa/Cargo.toml +++ b/core/finality-grandpa/Cargo.toml @@ -2,33 +2,34 @@ name = "substrate-finality-grandpa" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] +fork-tree = { path = "../../core/util/fork-tree" } futures = "0.1" -parity-codec = "2.1" -parity-codec-derive = "2.0" -sr-primitives = { path = "../sr-primitives" } -substrate-consensus-common = { path = "../consensus/common" } -substrate-primitives = { path = "../primitives" } -substrate-client = { path = "../client" } -substrate-network = { path = "../network" } -substrate-service = { path = "../service", optional = true } log = "0.4" -parking_lot = "0.4" +parking_lot = "0.7.1" tokio = "0.1.7" -substrate-finality-grandpa-primitives = { path = "primitives" } rand = "0.6" - -[dependencies.finality-grandpa] -version = "0.5.1" -features = ["derive-codec"] +parity-codec = { version = "3.2", features = ["derive"] } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } +consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } +substrate-primitives = { path = "../primitives" } +substrate-telemetry = { path = "../telemetry" } +client = { package = "substrate-client", path = "../client" } +inherents = { package = "substrate-inherents", path = "../../core/inherents" } +network = { package = "substrate-network", path = "../network" } +service = { package = "substrate-service", path = "../service", optional = true } +srml-finality-tracker = { path = "../../srml/finality-tracker" } +fg_primitives = { package = "substrate-finality-grandpa-primitives", path = "primitives" } +grandpa = { package = "finality-grandpa", version = "0.6.0", features = ["derive-codec"] } [dev-dependencies] -substrate-network = { path = "../network", features = ["test-helpers"] } -substrate-keyring = { path = "../keyring" } -substrate-test-client = { path = "../test-client"} -env_logger = "0.5" +network = { package = "substrate-network", path = "../network", features = ["test-helpers"] } +keyring = { package = "substrate-keyring", path = "../keyring" } +test_client = { package = "substrate-test-client", path = "../test-client"} +env_logger = "0.6" [features] default = ["service-integration"] -service-integration = ["substrate-service"] +service-integration = ["service"] diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml index 0ddb489af77cec4edb0021e32bf5b128046e7e69..a0bd36eb9a43df5e292a0f4bf42dba177cfa3580 100644 --- a/core/finality-grandpa/primitives/Cargo.toml +++ b/core/finality-grandpa/primitives/Cargo.toml @@ -2,22 +2,21 @@ name = "substrate-finality-grandpa-primitives" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -substrate-client = { path = "../../client", default-features = false } +client = { package = "substrate-client", path = "../../client", default-features = false } substrate-primitives = { path = "../../primitives", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } sr-primitives = { path = "../../sr-primitives", default-features = false } -sr-std = { path = "../../sr-std", default-features = false } +rstd = { package = "sr-std", path = "../../sr-std", default-features = false } [features] default = ["std"] std = [ "substrate-primitives/std", - "substrate-client/std", + "client/std", "parity-codec/std", - "parity-codec-derive/std", "sr-primitives/std", - "sr-std/std", + "rstd/std", ] diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index df224fa9d4ad1a1e522f35a9f15cb3f7904268db..92bd0e4584c83863afa4ec7fa01f5aea4d551276 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,22 +22,14 @@ #[cfg(not(feature = "std"))] extern crate alloc; -extern crate substrate_primitives; -extern crate sr_primitives; -extern crate parity_codec; - -#[macro_use] -extern crate parity_codec_derive; - -#[macro_use] -extern crate substrate_client as client; - -extern crate sr_std as rstd; - -use substrate_primitives::AuthorityId; +use parity_codec::{Encode, Decode}; +use substrate_primitives::ed25519; use sr_primitives::traits::{DigestFor, NumberFor}; +use client::decl_runtime_apis; use rstd::vec::Vec; +use ed25519::Public as AuthorityId; + /// A scheduled change of authority set. #[cfg_attr(feature = "std", derive(Debug, PartialEq))] #[derive(Clone, Encode, Decode)] @@ -53,14 +45,6 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change"; /// WASM function call to get current GRANDPA authorities. pub const AUTHORITIES_CALL: &str = "grandpa_authorities"; -/// The ApiIds for GRANDPA API. -pub mod id { - use client::runtime_api::ApiId; - - /// ApiId for the GrandpaApi trait. - pub const GRANDPA_API: ApiId = *b"fgrandpa"; -} - /// Well-known storage keys for GRANDPA. pub mod well_known_keys { /// The key for the authorities and weights vector in storage. @@ -79,6 +63,7 @@ decl_runtime_apis! { /// applied in the runtime after those N blocks have passed. /// /// The consensus protocol will coordinate the handoff externally. + #[api_version(2)] pub trait GrandpaApi { /// Check a digest for pending changes. /// Return `None` if there are no pending changes. @@ -92,11 +77,37 @@ decl_runtime_apis! { /// This should be a pure function: i.e. as long as the runtime can interpret /// the digest type it should return the same result regardless of the current /// state. - fn grandpa_pending_change(digest: DigestFor) + fn grandpa_pending_change(digest: &DigestFor) -> Option>>; + /// Check a digest for forced changes. + /// Return `None` if there are no forced changes. Otherwise, return a + /// tuple containing the pending change and the median last finalized + /// block number at the time the change was signalled. + /// + /// Added in version 2. + /// + /// Forced changes are applied after a delay of _imported_ blocks, + /// while pending changes are applied after a delay of _finalized_ blocks. + /// + /// Precedence towards earlier or later digest items can be given + /// based on the rules of the chain. + /// + /// No change should be scheduled if one is already and the delay has not + /// passed completely. + /// + /// This should be a pure function: i.e. as long as the runtime can interpret + /// the digest type it should return the same result regardless of the current + /// state. + fn grandpa_forced_change(digest: &DigestFor) + -> Option<(NumberFor, ScheduledChange>)>; + /// Get the current GRANDPA authorities and weights. This should not change except /// for when changes are scheduled and the corresponding delay has passed. + /// + /// When called at block B, it will return the set of authorities that should be + /// used to finalize descendants of this block (B+1, B+2, ...). The block B itself + /// is finalized by the authorities from block B-1. fn grandpa_authorities() -> Vec<(AuthorityId, u64)>; } } diff --git a/core/finality-grandpa/src/authorities.rs b/core/finality-grandpa/src/authorities.rs index 64e9f3690634b7ad92caa23f74796c33500c8f20..38bcec2347599279ee38549b610a6a5f25750555 100644 --- a/core/finality-grandpa/src/authorities.rs +++ b/core/finality-grandpa/src/authorities.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,15 +16,21 @@ //! Utilities for dealing with authorities, authority sets, and handoffs. +use fork_tree::ForkTree; use parking_lot::RwLock; -use substrate_primitives::AuthorityId; +use substrate_primitives::ed25519; +use grandpa::VoterSet; +use parity_codec::{Encode, Decode}; +use log::{debug, info}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use std::cmp::Ord; -use std::collections::HashMap; use std::fmt::Debug; use std::ops::Add; use std::sync::Arc; +use ed25519::Public as AuthorityId; + /// A shared authority set. pub(crate) struct SharedAuthoritySet { inner: Arc>>, @@ -37,13 +43,6 @@ impl Clone for SharedAuthoritySet { } impl SharedAuthoritySet { - /// The genesis authority set. - pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { - SharedAuthoritySet { - inner: Arc::new(RwLock::new(AuthoritySet::genesis(initial))) - } - } - /// Acquire a reference to the inner read-write lock. pub(crate) fn inner(&self) -> &RwLock> { &*self.inner @@ -51,9 +50,8 @@ impl SharedAuthoritySet { } impl SharedAuthoritySet -where - N: Add + Ord + Clone + Debug, - H: Debug +where N: Add + Ord + Clone + Debug, + H: Clone + Debug { /// Get the earliest limit-block number, if any. pub(crate) fn current_limit(&self) -> Option { @@ -66,7 +64,7 @@ where } /// Get the current authorities and their weights (for the current set ID). - pub(crate) fn current_authorities(&self) -> HashMap { + pub(crate) fn current_authorities(&self) -> VoterSet { self.inner.read().current_authorities.iter().cloned().collect() } } @@ -78,6 +76,7 @@ impl From> for SharedAuthoritySet { } /// Status of the set after changes were applied. +#[derive(Debug)] pub(crate) struct Status { /// Whether internal changes were made. pub(crate) changed: bool, @@ -87,20 +86,31 @@ pub(crate) struct Status { } /// A set of authorities. -#[derive(Debug, Clone, Encode, Decode)] +#[derive(Debug, Clone, Encode, Decode, PartialEq)] pub(crate) struct AuthoritySet { - current_authorities: Vec<(AuthorityId, u64)>, - set_id: u64, - pending_changes: Vec>, + pub(crate) current_authorities: Vec<(AuthorityId, u64)>, + pub(crate) set_id: u64, + // Tree of pending standard changes across forks. Standard changes are + // enacted on finality and must be enacted (i.e. finalized) in-order across + // a given branch + pub(crate) pending_standard_changes: ForkTree>, + // Pending forced changes across different forks (at most one per fork). + // Forced changes are enacted on block depth (not finality), for this reason + // only one forced change should exist per fork. + pub(crate) pending_forced_changes: Vec>, } -impl AuthoritySet { +impl AuthoritySet +where H: PartialEq, + N: Ord, +{ /// Get a genesis set with given authorities. pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { AuthoritySet { current_authorities: initial, set_id: 0, - pending_changes: Vec::new(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), } } @@ -113,156 +123,306 @@ impl AuthoritySet { impl AuthoritySet where N: Add + Ord + Clone + Debug, - H: Debug + H: Clone + Debug { - /// Note an upcoming pending transition. This makes sure that there isn't - /// already any pending change for the same chain. Multiple pending changes - /// are allowed but they must be signalled in different forks. The closure - /// should return an error if the pending change block is equal to or a - /// descendent of the given block. - pub(crate) fn add_pending_change( + fn add_standard_change( + &mut self, + pending: PendingChange, + is_descendent_of: &F, + ) -> Result<(), fork_tree::Error> where + F: Fn(&H, &H) -> Result, + E: std::error::Error, + { + let hash = pending.canon_hash.clone(); + let number = pending.canon_height.clone(); + + debug!(target: "afg", "Inserting potential standard set change signalled at block {:?} \ + (delayed by {:?} blocks).", + (&number, &hash), pending.delay); + + self.pending_standard_changes.import( + hash.clone(), + number.clone(), + pending, + is_descendent_of, + )?; + + debug!(target: "afg", "There are now {} alternatives for the next pending standard change (roots), \ + and a total of {} pending standard changes (across all forks).", + self.pending_standard_changes.roots().count(), + self.pending_standard_changes.iter().count(), + ); + + Ok(()) + } + + fn add_forced_change( &mut self, pending: PendingChange, - is_equal_or_descendent_of: F, - ) -> Result<(), E> where - F: Fn(&H) -> Result<(), E>, + is_descendent_of: &F, + ) -> Result<(), fork_tree::Error> where + F: Fn(&H, &H) -> Result, + E: std::error::Error, { - for change in self.pending_changes.iter() { - is_equal_or_descendent_of(&change.canon_hash)?; + for change in self.pending_forced_changes.iter() { + if change.canon_hash == pending.canon_hash || + is_descendent_of(&change.canon_hash, &pending.canon_hash)? + { + return Err(fork_tree::Error::UnfinalizedAncestor); + } } // ordered first by effective number and then by signal-block number. let key = (pending.effective_number(), pending.canon_height.clone()); - let idx = self.pending_changes + let idx = self.pending_forced_changes .binary_search_by_key(&key, |change| ( change.effective_number(), change.canon_height.clone(), )) .unwrap_or_else(|i| i); - self.pending_changes.insert(idx, pending); + debug!(target: "afg", "Inserting potential forced set change at block {:?} \ + (delayed by {:?} blocks).", + (&pending.canon_height, &pending.canon_hash), pending.delay); + + self.pending_forced_changes.insert(idx, pending); + + debug!(target: "afg", "There are now {} pending forced changes.", self.pending_forced_changes.len()); Ok(()) } - /// Inspect pending changes. - #[cfg(test)] - pub(crate) fn pending_changes(&self) -> &[PendingChange] { - &self.pending_changes + /// Note an upcoming pending transition. Multiple pending standard changes + /// on the same branch can be added as long as they don't overlap. Forced + /// changes are restricted to one per fork. This method assumes that changes + /// on the same branch will be added in-order. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + pub(crate) fn add_pending_change( + &mut self, + pending: PendingChange, + is_descendent_of: &F, + ) -> Result<(), fork_tree::Error> where + F: Fn(&H, &H) -> Result, + E: std::error::Error, + { + match pending.delay_kind { + DelayKind::Best { .. } => { + self.add_forced_change(pending, is_descendent_of) + }, + DelayKind::Finalized => { + self.add_standard_change(pending, is_descendent_of) + }, + } } - /// Get the earliest limit-block number, if any. + /// Inspect pending changes. Standard pending changes are iterated first, + /// and the changes in the tree are traversed in pre-order, afterwards all + /// forced changes are iterated. + pub(crate) fn pending_changes(&self) -> impl Iterator> { + self.pending_standard_changes.iter().map(|(_, _, c)| c) + .chain(self.pending_forced_changes.iter()) + } + + /// Get the earliest limit-block number, if any. If there are pending changes across + /// different forks, this method will return the earliest effective number (across the + /// different branches). Only standard changes are taken into account for the current + /// limit, since any existing forced change should preclude the voter from voting. pub(crate) fn current_limit(&self) -> Option { - self.pending_changes.get(0).map(|change| change.effective_number().clone()) + self.pending_standard_changes.roots() + .min_by_key(|&(_, _, c)| c.effective_number()) + .map(|(_, _, c)| c.effective_number()) } - /// Apply or prune any pending transitions. Provide a closure that can be used to check for the - /// finalized block with given number. + /// Apply or prune any pending transitions based on a best-block trigger. /// - /// When the set has changed, the return value will be `Ok(Some((H, N)))` which is the canonical - /// block where the set last changed. - pub(crate) fn apply_changes(&mut self, just_finalized: N, mut canonical: F) - -> Result, E> - where F: FnMut(N) -> Result, E> + /// Returns `Ok((median, new_set))` when a forced change has occurred. The + /// median represents the median last finalized block at the time the change + /// was signaled, and it should be used as the canon block when starting the + /// new grandpa voter. Only alters the internal state in this case. + /// + /// These transitions are always forced and do not lead to justifications + /// which light clients can follow. + pub(crate) fn apply_forced_changes( + &self, + best_hash: H, + best_number: N, + is_descendent_of: &F, + ) -> Result, E> + where F: Fn(&H, &H) -> Result, + { + let mut new_set = None; + + for change in self.pending_forced_changes.iter() + .take_while(|c| c.effective_number() <= best_number) // to prevent iterating too far + .filter(|c| c.effective_number() == best_number) + { + // check if the given best block is in the same branch as the block that signalled the change. + if is_descendent_of(&change.canon_hash, &best_hash)? { + // apply this change: make the set canonical + info!(target: "finality", "Applying authority set change forced at block #{:?}", + change.canon_height); + telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; + "block" => ?change.canon_height + ); + + let median_last_finalized = match change.delay_kind { + DelayKind::Best { ref median_last_finalized } => median_last_finalized.clone(), + _ => unreachable!("pending_forced_changes only contains forced changes; forced changes have delay kind Best; qed."), + }; + + new_set = Some((median_last_finalized, AuthoritySet { + current_authorities: change.next_authorities.clone(), + set_id: self.set_id + 1, + pending_standard_changes: ForkTree::new(), // new set, new changes. + pending_forced_changes: Vec::new(), + })); + + break; + } + + // we don't wipe forced changes until another change is + // applied + } + + Ok(new_set) + } + + /// Apply or prune any pending transitions based on a finality trigger. This + /// method ensures that if there are multiple changes in the same branch, + /// finalizing this block won't finalize past multiple transitions (i.e. + /// transitions must be finalized in-order). The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + /// + /// When the set has changed, the return value will be `Ok(Some((H, N)))` + /// which is the canonical block where the set last changed (i.e. the given + /// hash and number). + pub(crate) fn apply_standard_changes( + &mut self, + finalized_hash: H, + finalized_number: N, + is_descendent_of: &F, + ) -> Result, fork_tree::Error> + where F: Fn(&H, &H) -> Result, + E: std::error::Error, { let mut status = Status { changed: false, new_set_block: None, }; - loop { - let remove_up_to = match self.pending_changes.first() { - None => break, - Some(change) => { - let effective_number = change.effective_number(); - if effective_number > just_finalized { break } - - // check if the block that signalled the change is canonical in - // our chain. - let canonical_hash = canonical(change.canon_height.clone())?; - let effective_hash = canonical(effective_number.clone())?; - - debug!(target: "afg", "Evaluating potential set change at block {:?}. Our canonical hash is {:?}", - (&change.canon_height, &change.canon_hash), canonical_hash); - - match (canonical_hash, effective_hash) { - (Some(canonical_hash), Some(effective_hash)) => { - if canonical_hash == change.canon_hash { - // apply this change: make the set canonical - info!(target: "finality", "Applying authority set change scheduled at block #{:?}", - change.canon_height); - - self.current_authorities = change.next_authorities.clone(); - self.set_id += 1; - - status.new_set_block = Some(( - effective_hash, - effective_number.clone(), - )); - - // discard all signalled changes since they're - // necessarily from other forks - self.pending_changes.len() - } else { - 1 // prune out this entry; it's no longer relevant. - } - }, - _ => 1, // prune out this entry; it's no longer relevant. - } - } - }; - let remove_up_to = ::std::cmp::min(remove_up_to, self.pending_changes.len()); - self.pending_changes.drain(..remove_up_to); - status.changed = true; // always changed because we strip at least the first change. + match self.pending_standard_changes.finalize_with_descendent_if( + &finalized_hash, + finalized_number.clone(), + is_descendent_of, + |change| change.effective_number() <= finalized_number + )? { + fork_tree::FinalizationResult::Changed(change) => { + status.changed = true; + + // if we are able to finalize any standard change then we can + // discard all pending forced changes (on different forks) + self.pending_forced_changes.clear(); + + if let Some(change) = change { + info!(target: "finality", "Applying authority set change scheduled at block #{:?}", + change.canon_height); + telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; + "block" => ?change.canon_height + ); + + self.current_authorities = change.next_authorities; + self.set_id += 1; + + status.new_set_block = Some(( + finalized_hash, + finalized_number, + )); + } + }, + fork_tree::FinalizationResult::Unchanged => {}, } Ok(status) } - /// Check whether the given finalized block number enacts any authority set - /// change (without triggering it). Provide a closure that can be used to - /// check for the canonical block with a given number. - pub fn enacts_change(&self, just_finalized: N, mut canonical: F) - -> Result - where F: FnMut(N) -> Result, E> + /// Check whether the given finalized block number enacts any standard + /// authority set change (without triggering it), ensuring that if there are + /// multiple changes in the same branch, finalizing this block won't + /// finalize past multiple transitions (i.e. transitions must be finalized + /// in-order). The given function `is_descendent_of` should return `true` if + /// the second hash (target) is a descendent of the first hash (base). + pub fn enacts_standard_change( + &self, + finalized_hash: H, + finalized_number: N, + is_descendent_of: &F, + ) -> Result> + where F: Fn(&H, &H) -> Result, + E: std::error::Error, { - for change in self.pending_changes.iter() { - if change.effective_number() > just_finalized { break }; - - // check if the block that signalled the change is canonical in - // our chain. - match canonical(change.canon_height.clone())? { - Some(ref canonical_hash) if *canonical_hash == change.canon_hash => - return Ok(true), - _ => (), - } - } - - Ok(false) + self.pending_standard_changes.finalizes_any_with_descendent_if( + &finalized_hash, + finalized_number.clone(), + is_descendent_of, + |change| change.effective_number() == finalized_number + ) } } +/// Kinds of delays for pending changes. +#[derive(Debug, Clone, Encode, Decode, PartialEq)] +pub(crate) enum DelayKind { + /// Depth in finalized chain. + Finalized, + /// Depth in best chain. The median last finalized block is calculated at the time the + /// change was signalled. + Best { median_last_finalized: N }, +} + /// A pending change to the authority set. /// /// This will be applied when the announcing block is at some depth within -/// the finalized chain. -#[derive(Debug, Clone, Encode, Decode, PartialEq)] +/// the finalized or unfinalized chain. +#[derive(Debug, Clone, Encode, PartialEq)] pub(crate) struct PendingChange { /// The new authorities and weights to apply. pub(crate) next_authorities: Vec<(AuthorityId, u64)>, - /// How deep in the finalized chain the announcing block must be + /// How deep in the chain the announcing block must be /// before the change is applied. - pub(crate) finalization_depth: N, + pub(crate) delay: N, /// The announcing block's height. pub(crate) canon_height: N, /// The announcing block's hash. pub(crate) canon_hash: H, + /// The delay kind. + pub(crate) delay_kind: DelayKind, +} + +impl Decode for PendingChange { + fn decode(value: &mut I) -> Option { + let next_authorities = Decode::decode(value)?; + let delay = Decode::decode(value)?; + let canon_height = Decode::decode(value)?; + let canon_hash = Decode::decode(value)?; + + let delay_kind = DelayKind::decode(value).unwrap_or(DelayKind::Finalized); + + Some(PendingChange { + next_authorities, + delay, + canon_height, + canon_hash, + delay_kind, + }) + } } impl + Clone> PendingChange { /// Returns the effective number this change will be applied at. - fn effective_number(&self) -> N { - self.canon_height.clone() + self.finalization_depth.clone() + pub fn effective_number(&self) -> N { + self.canon_height.clone() + self.delay.clone() } } @@ -270,44 +430,83 @@ impl + Clone> PendingChange { mod tests { use super::*; - fn ignore_existing_changes(_a: &A) -> Result<(), ::Error> { - Ok(()) + fn static_is_descendent_of(value: bool) + -> impl Fn(&A, &A) -> Result + { + move |_, _| Ok(value) + } + + fn is_descendent_of(f: F) -> impl Fn(&A, &A) -> Result + where F: Fn(&A, &A) -> bool + { + move |base, hash| Ok(f(base, hash)) } #[test] - fn changes_sorted_in_correct_order() { + fn changes_iterated_in_pre_order() { let mut authorities = AuthoritySet { current_authorities: Vec::new(), set_id: 0, - pending_changes: Vec::new(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), }; let change_a = PendingChange { next_authorities: Vec::new(), - finalization_depth: 10, + delay: 10, canon_height: 5, canon_hash: "hash_a", + delay_kind: DelayKind::Finalized, }; let change_b = PendingChange { next_authorities: Vec::new(), - finalization_depth: 0, - canon_height: 16, + delay: 0, + canon_height: 5, canon_hash: "hash_b", + delay_kind: DelayKind::Finalized, }; let change_c = PendingChange { next_authorities: Vec::new(), - finalization_depth: 5, + delay: 5, canon_height: 10, canon_hash: "hash_c", + delay_kind: DelayKind::Finalized, + }; + + authorities.add_pending_change(change_a.clone(), &static_is_descendent_of(false)).unwrap(); + authorities.add_pending_change(change_b.clone(), &static_is_descendent_of(false)).unwrap(); + authorities.add_pending_change(change_c.clone(), &is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_c") => true, + ("hash_b", "hash_c") => false, + _ => unreachable!(), + })).unwrap(); + + // forced changes are iterated last + let change_d = PendingChange { + next_authorities: Vec::new(), + delay: 2, + canon_height: 1, + canon_hash: "hash_d", + delay_kind: DelayKind::Best { median_last_finalized: 0 }, + }; + + let change_e = PendingChange { + next_authorities: Vec::new(), + delay: 2, + canon_height: 0, + canon_hash: "hash_e", + delay_kind: DelayKind::Best { median_last_finalized: 0 }, }; - authorities.add_pending_change(change_a.clone(), ignore_existing_changes).unwrap(); - authorities.add_pending_change(change_b.clone(), ignore_existing_changes).unwrap(); - authorities.add_pending_change(change_c.clone(), ignore_existing_changes).unwrap(); + authorities.add_pending_change(change_d.clone(), &static_is_descendent_of(false)).unwrap(); + authorities.add_pending_change(change_e.clone(), &static_is_descendent_of(false)).unwrap(); - assert_eq!(authorities.pending_changes, vec![change_a, change_c, change_b]); + assert_eq!( + authorities.pending_changes().collect::>(), + vec![&change_b, &change_a, &change_c, &change_e, &change_d], + ); } #[test] @@ -315,120 +514,238 @@ mod tests { let mut authorities = AuthoritySet { current_authorities: Vec::new(), set_id: 0, - pending_changes: Vec::new(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; + // two competing changes at the same height on different forks let change_a = PendingChange { next_authorities: set_a.clone(), - finalization_depth: 10, + delay: 10, canon_height: 5, canon_hash: "hash_a", + delay_kind: DelayKind::Finalized, }; let change_b = PendingChange { next_authorities: set_b.clone(), - finalization_depth: 10, + delay: 10, canon_height: 5, canon_hash: "hash_b", + delay_kind: DelayKind::Finalized, }; - authorities.add_pending_change(change_a.clone(), ignore_existing_changes).unwrap(); - authorities.add_pending_change(change_b.clone(), ignore_existing_changes).unwrap(); + authorities.add_pending_change(change_a.clone(), &static_is_descendent_of(true)).unwrap(); + authorities.add_pending_change(change_b.clone(), &static_is_descendent_of(true)).unwrap(); - authorities.apply_changes(10, |_| Err(())).unwrap(); - assert!(authorities.current_authorities.is_empty()); + assert_eq!( + authorities.pending_changes().collect::>(), + vec![&change_b, &change_a], + ); - authorities.apply_changes(15, |n| match n { - 5 => Ok(Some("hash_a")), - 15 => Ok(Some("hash_15_canon")), - _ => Err(()), - }).unwrap(); + // finalizing "hash_c" won't enact the change signalled at "hash_a" but it will prune out "hash_b" + let status = authorities.apply_standard_changes("hash_c", 11, &is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_c") => true, + ("hash_b", "hash_c") => false, + _ => unreachable!(), + })).unwrap(); + + assert!(status.changed); + assert_eq!(status.new_set_block, None); + assert_eq!( + authorities.pending_changes().collect::>(), + vec![&change_a], + ); + + // finalizing "hash_d" will enact the change signalled at "hash_a" + let status = authorities.apply_standard_changes("hash_d", 15, &is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_d") => true, + _ => unreachable!(), + })).unwrap(); + + assert!(status.changed); + assert_eq!(status.new_set_block, Some(("hash_d", 15))); assert_eq!(authorities.current_authorities, set_a); assert_eq!(authorities.set_id, 1); - assert!(authorities.pending_changes.is_empty()); + assert_eq!(authorities.pending_changes().count(), 0); } #[test] - fn disallow_multiple_changes_on_same_fork() { + fn disallow_multiple_changes_being_finalized_at_once() { let mut authorities = AuthoritySet { current_authorities: Vec::new(), set_id: 0, - pending_changes: Vec::new(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; - let set_c = vec![([3; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_c = vec![(AuthorityId([2; 32]), 5)]; + // two competing changes at the same height on different forks let change_a = PendingChange { next_authorities: set_a.clone(), - finalization_depth: 10, + delay: 10, canon_height: 5, canon_hash: "hash_a", - }; - - let change_b = PendingChange { - next_authorities: set_b.clone(), - finalization_depth: 10, - canon_height: 16, - canon_hash: "hash_b", + delay_kind: DelayKind::Finalized, }; let change_c = PendingChange { next_authorities: set_c.clone(), - finalization_depth: 10, - canon_height: 16, + delay: 10, + canon_height: 30, canon_hash: "hash_c", + delay_kind: DelayKind::Finalized, }; - let is_equal_or_descendent_of = |base, block| -> Result<(), ()> { - match (base, block) { - ("hash_a", "hash_b") => return Err(()), - ("hash_a", "hash_c") => return Ok(()), - ("hash_c", "hash_b") => return Ok(()), - _ => unreachable!(), - } - }; + authorities.add_pending_change(change_a.clone(), &static_is_descendent_of(true)).unwrap(); + authorities.add_pending_change(change_c.clone(), &static_is_descendent_of(true)).unwrap(); - authorities.add_pending_change( - change_a.clone(), - |base| is_equal_or_descendent_of(base, change_a.canon_hash), - ).unwrap(); - - // change b is on the same chain has the unfinalized change a so it should error - assert!( - authorities.add_pending_change( - change_b.clone(), - |base| is_equal_or_descendent_of(base, change_b.canon_hash), - ).is_err() - ); + let is_descendent_of = is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_b") => true, + ("hash_a", "hash_c") => true, + ("hash_a", "hash_d") => true, + + ("hash_c", "hash_b") => false, + ("hash_c", "hash_d") => true, + + ("hash_b", "hash_c") => true, + _ => unreachable!(), + }); - // change c is accepted because it's on a different fork - authorities.add_pending_change( - change_c.clone(), - |base| is_equal_or_descendent_of(base, change_c.canon_hash) - ).unwrap(); + // trying to finalize past `change_c` without finalizing `change_a` first + match authorities.apply_standard_changes("hash_d", 40, &is_descendent_of) { + Err(fork_tree::Error::UnfinalizedAncestor) => {}, + _ => unreachable!(), + } - authorities.apply_changes(15, |n| match n { - 5 => Ok(Some("hash_a")), - 15 => Ok(Some("hash_a15")), - _ => Err(()), - }).unwrap(); + let status = authorities.apply_standard_changes("hash_b", 15, &is_descendent_of).unwrap(); + assert!(status.changed); + assert_eq!(status.new_set_block, Some(("hash_b", 15))); assert_eq!(authorities.current_authorities, set_a); + assert_eq!(authorities.set_id, 1); + + // after finalizing `change_a` it should be possible to finalize `change_c` + let status = authorities.apply_standard_changes("hash_d", 40, &is_descendent_of).unwrap(); + assert!(status.changed); + assert_eq!(status.new_set_block, Some(("hash_d", 40))); + + assert_eq!(authorities.current_authorities, set_c); + assert_eq!(authorities.set_id, 2); + } + + #[test] + fn enacts_standard_change_works() { + let mut authorities = AuthoritySet { + current_authorities: Vec::new(), + set_id: 0, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + }; + + let set_a = vec![(AuthorityId([1; 32]), 5)]; + + let change_a = PendingChange { + next_authorities: set_a.clone(), + delay: 10, + canon_height: 5, + canon_hash: "hash_a", + delay_kind: DelayKind::Finalized, + }; + + authorities.add_pending_change(change_a.clone(), &static_is_descendent_of(false)).unwrap(); + + let is_descendent_of = is_descendent_of(|base, hash| match (*base, *hash) { + ("hash_a", "hash_b") => true, + ("hash_a", "hash_c") => false, + _ => unreachable!(), + }); - // pending change c has been removed since it was on a different fork - // and can no longer be enacted - assert!(authorities.pending_changes.is_empty()); + // "hash_c" won't finalize the existing change since it isn't a descendent + assert!(!authorities.enacts_standard_change("hash_c", 15, &is_descendent_of).unwrap()); + // "hash_b" at depth 14 won't work either + assert!(!authorities.enacts_standard_change("hash_b", 14, &is_descendent_of).unwrap()); - // pending change b can now be added - authorities.add_pending_change( - change_b.clone(), - |base| is_equal_or_descendent_of(base, change_b.canon_hash), - ).unwrap(); + // but it should work at depth 15 (change height + depth) + assert!(authorities.enacts_standard_change("hash_b", 15, &is_descendent_of).unwrap()); + } + + #[test] + fn forced_changes() { + let mut authorities = AuthoritySet { + current_authorities: Vec::new(), + set_id: 0, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + }; + + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; + + let change_a = PendingChange { + next_authorities: set_a.clone(), + delay: 10, + canon_height: 5, + canon_hash: "hash_a", + delay_kind: DelayKind::Best { median_last_finalized: 42 }, + }; + + let change_b = PendingChange { + next_authorities: set_b.clone(), + delay: 10, + canon_height: 5, + canon_hash: "hash_b", + delay_kind: DelayKind::Best { median_last_finalized: 0 }, + }; + + authorities.add_pending_change(change_a, &static_is_descendent_of(false)).unwrap(); + authorities.add_pending_change(change_b, &static_is_descendent_of(false)).unwrap(); + + // there's an effective change triggered at block 15 but not a standard one. + // so this should do nothing. + assert!(!authorities.enacts_standard_change("hash_c", 15, &static_is_descendent_of(true)).unwrap()); + + // throw a standard change into the mix to prove that it's discarded + // for being on the same fork. + // + // NOTE: after https://github.com/paritytech/substrate/issues/1861 + // this should still be rejected based on the "span" rule -- it overlaps + // with another change on the same fork. + let change_c = PendingChange { + next_authorities: set_b.clone(), + delay: 3, + canon_height: 8, + canon_hash: "hash_a8", + delay_kind: DelayKind::Best { median_last_finalized: 0 }, + }; + + let is_descendent_of_a = is_descendent_of(|base: &&str, _| { + base.starts_with("hash_a") + }); + + assert!(authorities.add_pending_change(change_c, &is_descendent_of_a).is_err()); + + // too early. + assert!(authorities.apply_forced_changes("hash_a10", 10, &static_is_descendent_of(true)).unwrap().is_none()); + + // too late. + assert!(authorities.apply_forced_changes("hash_a16", 16, &static_is_descendent_of(true)).unwrap().is_none()); + + // on time -- chooses the right change. + assert_eq!( + authorities.apply_forced_changes("hash_a15", 15, &is_descendent_of_a).unwrap().unwrap(), + (42, AuthoritySet { + current_authorities: set_a, + set_id: 1, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + }) + ); } } diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs new file mode 100644 index 0000000000000000000000000000000000000000..eb187d877bf266eff0d76f3f9514c092bc3eb51c --- /dev/null +++ b/core/finality-grandpa/src/aux_schema.rs @@ -0,0 +1,275 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Schema for stuff in the aux-db. + +use std::fmt::Debug; +use std::sync::Arc; +use parity_codec::{Encode, Decode}; +use client::backend::AuxStore; +use client::error::{Result as ClientResult, Error as ClientError, ErrorKind as ClientErrorKind}; +use fork_tree::ForkTree; +use grandpa::round::State as RoundState; +use log::{info, warn}; + +use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; +use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; +use crate::NewAuthoritySet; + +use substrate_primitives::ed25519::Public as AuthorityId; + +const VERSION_KEY: &[u8] = b"grandpa_schema_version"; +const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; +const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; +const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; + +const CURRENT_VERSION: u32 = 1; + +/// The voter set state. +#[derive(Clone, Encode, Decode)] +pub enum VoterSetState { + /// The voter set state, currently paused. + Paused(u64, RoundState), + /// The voter set state, currently live. + Live(u64, RoundState), +} + +impl VoterSetState { + /// Yields the current state. + pub(crate) fn round(&self) -> (u64, RoundState) { + match *self { + VoterSetState::Paused(n, ref s) => (n, s.clone()), + VoterSetState::Live(n, ref s) => (n, s.clone()), + } + } +} + +type V0VoterSetState = (u64, RoundState); + +#[derive(Debug, Clone, Encode, Decode, PartialEq)] +struct V0PendingChange { + next_authorities: Vec<(AuthorityId, u64)>, + delay: N, + canon_height: N, + canon_hash: H, +} + +#[derive(Debug, Clone, Encode, Decode, PartialEq)] +struct V0AuthoritySet { + current_authorities: Vec<(AuthorityId, u64)>, + set_id: u64, + pending_changes: Vec>, +} + +impl Into> for V0AuthoritySet +where H: Clone + Debug + PartialEq, + N: Clone + Debug + Ord, +{ + fn into(self) -> AuthoritySet { + let mut pending_standard_changes = ForkTree::new(); + + for old_change in self.pending_changes { + let new_change = PendingChange { + next_authorities: old_change.next_authorities, + delay: old_change.delay, + canon_height: old_change.canon_height, + canon_hash: old_change.canon_hash, + delay_kind: DelayKind::Finalized, + }; + + if let Err(err) = pending_standard_changes.import::<_, ClientError>( + new_change.canon_hash.clone(), + new_change.canon_height.clone(), + new_change, + // previously we only supported at most one pending change per fork + &|_, _| Ok(false), + ) { + warn!(target: "afg", "Error migrating pending authority set change: {:?}.", err); + warn!(target: "afg", "Node is in a potentially inconsistent state."); + } + } + + AuthoritySet { + current_authorities: self.current_authorities, + set_id: self.set_id, + pending_forced_changes: Vec::new(), + pending_standard_changes + } + } +} + +fn load_decode(backend: &B, key: &[u8]) -> ClientResult> { + match backend.get_aux(key)? { + None => Ok(None), + Some(t) => T::decode(&mut &t[..]) + .ok_or_else( + || ClientErrorKind::Backend(format!("GRANDPA DB is corrupted.")).into(), + ) + .map(Some) + } +} + +/// Persistent data kept between runs. +pub(crate) struct PersistentData { + pub(crate) authority_set: SharedAuthoritySet, + pub(crate) consensus_changes: SharedConsensusChanges, + pub(crate) set_state: VoterSetState, +} + +/// Load or initialize persistent data from backend. +pub(crate) fn load_persistent( + backend: &B, + genesis_hash: H, + genesis_number: N, + genesis_authorities: G, +) + -> ClientResult> + where + B: AuxStore, + H: Debug + Decode + Encode + Clone + PartialEq, + N: Debug + Decode + Encode + Clone + Ord, + G: FnOnce() -> ClientResult> +{ + let version: Option = load_decode(backend, VERSION_KEY)?; + let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)? + .unwrap_or_else(ConsensusChanges::::empty); + + let make_genesis_round = move || RoundState::genesis((genesis_hash, genesis_number)); + + match version { + None => { + CURRENT_VERSION.using_encoded(|s| + backend.insert_aux(&[(VERSION_KEY, s)], &[]) + )?; + + if let Some(old_set) = load_decode::<_, V0AuthoritySet>(backend, AUTHORITY_SET_KEY)? { + let new_set: AuthoritySet = old_set.into(); + backend.insert_aux(&[(AUTHORITY_SET_KEY, new_set.encode().as_slice())], &[])?; + + let set_state = match load_decode::<_, V0VoterSetState>(backend, SET_STATE_KEY)? { + Some((number, state)) => VoterSetState::Live(number, state), + None => VoterSetState::Live(0, make_genesis_round()), + }; + + return Ok(PersistentData { + authority_set: new_set.into(), + consensus_changes: Arc::new(consensus_changes.into()), + set_state, + }); + } + } + Some(1) => { + if let Some(set) = load_decode::<_, AuthoritySet>(backend, AUTHORITY_SET_KEY)? { + let set_state = match load_decode::<_, VoterSetState>(backend, SET_STATE_KEY)? { + Some(state) => state, + None => VoterSetState::Live(0, make_genesis_round()), + }; + + return Ok(PersistentData { + authority_set: set.into(), + consensus_changes: Arc::new(consensus_changes.into()), + set_state, + }); + } + } + Some(other) => return Err(ClientErrorKind::Backend( + format!("Unsupported GRANDPA DB version: {:?}", other) + ).into()), + } + + // genesis. + info!(target: "afg", "Loading GRANDPA authority set \ + from genesis on what appears to be first startup."); + + let genesis_set = AuthoritySet::genesis(genesis_authorities()?); + let genesis_state = VoterSetState::Live(0, make_genesis_round()); + backend.insert_aux( + &[ + (AUTHORITY_SET_KEY, genesis_set.encode().as_slice()), + (SET_STATE_KEY, genesis_state.encode().as_slice()), + ], + &[], + )?; + + Ok(PersistentData { + authority_set: genesis_set.into(), + set_state: genesis_state, + consensus_changes: Arc::new(consensus_changes.into()), + }) +} + +/// Update the authority set on disk after a change. +pub(crate) fn update_authority_set( + set: &AuthoritySet, + new_set: Option<&NewAuthoritySet>, + write_aux: F +) -> R where + H: Encode + Clone, + N: Encode + Clone, + F: FnOnce(&[(&'static [u8], &[u8])]) -> R, +{ + // write new authority set state to disk. + let encoded_set = set.encode(); + + if let Some(new_set) = new_set { + // we also overwrite the "last completed round" entry with a blank slate + // because from the perspective of the finality gadget, the chain has + // reset. + let round_state = RoundState::genesis(( + new_set.canon_hash.clone(), + new_set.canon_number.clone(), + )); + let set_state = VoterSetState::Live(0, round_state); + let encoded = set_state.encode(); + + write_aux(&[ + (AUTHORITY_SET_KEY, &encoded_set[..]), + (SET_STATE_KEY, &encoded[..]), + ]) + } else { + write_aux(&[(AUTHORITY_SET_KEY, &encoded_set[..])]) + } +} + +/// Write voter set state. +pub(crate) fn write_voter_set_state(backend: &B, state: &VoterSetState) + -> ClientResult<()> + where B: AuxStore, H: Encode, N: Encode +{ + backend.insert_aux( + &[(SET_STATE_KEY, state.encode().as_slice())], + &[] + ) +} + +/// Update the consensus changes. +pub(crate) fn update_consensus_changes( + set: &ConsensusChanges, + write_aux: F +) -> R where + H: Encode + Clone, + N: Encode + Clone, + F: FnOnce(&[(&'static [u8], &[u8])]) -> R, +{ + write_aux(&[(CONSENSUS_CHANGES_KEY, set.encode().as_slice())]) +} + +#[cfg(test)] +pub(crate) fn load_authorities(backend: &B) + -> Option> { + load_decode::<_, AuthoritySet>(backend, AUTHORITY_SET_KEY) + .expect("backend error") +} diff --git a/core/finality-grandpa/src/communication.rs b/core/finality-grandpa/src/communication.rs index 02a079b9094484ba1bb90b0223f10ccd02c75b33..1a8ff9ebab8f74538180a24993b37f21f2491a62 100644 --- a/core/finality-grandpa/src/communication.rs +++ b/core/finality-grandpa/src/communication.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,31 +17,242 @@ //! Incoming message streams that verify signatures, and outgoing message streams //! that sign or re-shape. +use std::collections::HashMap; +use std::sync::Arc; + +use grandpa::VoterSet; +use grandpa::Message::{Prevote, Precommit}; use futures::prelude::*; use futures::sync::mpsc; -use codec::{Encode, Decode}; -use substrate_primitives::{ed25519, AuthorityId}; +use log::{debug, trace}; +use parity_codec::{Encode, Decode}; +use substrate_primitives::{ed25519, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use runtime_primitives::traits::Block as BlockT; -use {Error, Network, Message, SignedMessage, Commit, CompactCommit}; - -use std::collections::HashMap; -use std::sync::Arc; +use tokio::timer::Interval; +use crate::{Error, Network, Message, SignedMessage, Commit, + CompactCommit, GossipMessage, FullCommitMessage, VoteOrPrecommitMessage}; +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; fn localized_payload(round: u64, set_id: u64, message: &E) -> Vec { (message, round, set_id).encode() } +#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord)] +struct Round(u64); +#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord)] +struct SetId(u64); + +enum Broadcast { + // round, set id, encoded commit. + Commit(Round, SetId, Vec), + // round, set id, encoded signed message. + Message(Round, SetId, Vec), + // round, set id, announcement of block hash that should be downloaded + Announcement(Round, SetId, Block::Hash), + // round, set id being dropped. + DropRound(Round, SetId), + // set_id being dropped. + DropSet(SetId), +} + +impl Broadcast { + fn set_id(&self) -> SetId { + match *self { + Broadcast::Commit(_, s, _) => s, + Broadcast::Message(_, s, _) => s, + Broadcast::Announcement(_, s, _) => s, + Broadcast::DropRound(_, s) => s, + Broadcast::DropSet(s) => s, + } + } +} + +/// Produces a future that should be run in the background and proxies +/// and rebroadcasts messages. +pub(crate) fn rebroadcasting_network>(network: N) -> (BroadcastWorker, BroadcastHandle) { + use std::time::Duration; + const REBROADCAST_PERIOD: Duration = Duration::from_secs(60); + + let (tx, rx) = mpsc::unbounded(); + + ( + BroadcastWorker { + interval: Interval::new_interval(REBROADCAST_PERIOD), + set_id: SetId(0), // will be overwritten on first item to broadcast. + last_commit: None, + round_messages: (Round(0), Vec::new()), + announcements: HashMap::new(), + network: network.clone(), + incoming_broadcast: rx, + }, + BroadcastHandle { + relay: tx, + network, + }, + ) +} + +// A worker which broadcasts messages to the background, potentially +// rebroadcasting. +#[must_use = "network rebroadcast future must be driven to completion"] +pub(crate) struct BroadcastWorker> { + interval: Interval, + set_id: SetId, + last_commit: Option<(Round, Vec)>, + round_messages: (Round, Vec>), + announcements: HashMap, + network: N, + incoming_broadcast: mpsc::UnboundedReceiver>, +} + +/// A handle used by communication work to broadcast to network. +#[derive(Clone)] +pub(crate) struct BroadcastHandle { + relay: mpsc::UnboundedSender>, + network: N, +} + +impl> Future for BroadcastWorker { + type Item = (); + type Error = Error; + + fn poll(&mut self) -> Poll<(), Error> { + { + let mut rebroadcast = false; + loop { + match self.interval.poll().map_err(Error::Timer)? { + Async::NotReady => break, + Async::Ready(_) => { rebroadcast = true; } + } + } + + if rebroadcast { + let SetId(set_id) = self.set_id; + if let Some((Round(c_round), ref c_commit)) = self.last_commit { + self.network.send_commit(c_round, set_id, c_commit.clone()); + } + + let Round(round) = self.round_messages.0; + for message in self.round_messages.1.iter().cloned() { + self.network.send_message(round, set_id, message); + } + + for (&announce_hash, &Round(round)) in &self.announcements { + self.network.announce(round, set_id, announce_hash); + } + } + } + loop { + match self.incoming_broadcast.poll().expect("UnboundedReceiver does not yield errors; qed") { + Async::NotReady => return Ok(Async::NotReady), + Async::Ready(None) => return Err(Error::Network( + "all broadcast handles dropped, connection to network severed".into() + )), + Async::Ready(Some(item)) => { + if item.set_id() > self.set_id { + self.set_id = item.set_id(); + self.last_commit = None; + self.round_messages = (Round(0), Vec::new()); + self.announcements.clear(); + } + + match item { + Broadcast::Commit(round, set_id, commit) => { + if self.set_id == set_id { + if round >= self.last_commit.as_ref() + .map_or(Round(0), |&(r, _)| r) + { + self.last_commit = Some((round, commit.clone())); + } + } + + // always send out to network. + self.network.send_commit(round.0, self.set_id.0, commit); + } + Broadcast::Message(round, set_id, message) => { + if self.set_id == set_id { + if round > self.round_messages.0 { + self.round_messages = (round, vec![message.clone()]); + } else if round == self.round_messages.0 { + self.round_messages.1.push(message.clone()); + }; + + // ignore messages from earlier rounds. + } + + // always send out to network. + self.network.send_message(round.0, set_id.0, message); + } + Broadcast::Announcement(round, set_id, hash) => { + if self.set_id == set_id { + self.announcements.insert(hash, round); + } + + // always send out. + self.network.announce(round.0, set_id.0, hash); + } + Broadcast::DropRound(round, set_id) => { + // stop making announcements for any dead rounds. + self.announcements.retain(|_, &mut r| r > round); + self.network.drop_round_messages(round.0, set_id.0); + } + Broadcast::DropSet(set_id) => { + // stop making announcements for any dead rounds. + self.network.drop_set_messages(set_id.0); + } + } + } + } + } + } +} + +impl> Network for BroadcastHandle { + type In = N::In; + + fn messages_for(&self, round: u64, set_id: u64) -> Self::In { + self.network.messages_for(round, set_id) + } + + fn send_message(&self, round: u64, set_id: u64, message: Vec) { + let _ = self.relay.unbounded_send(Broadcast::Message(Round(round), SetId(set_id), message)); + } + + fn drop_round_messages(&self, round: u64, set_id: u64) { + let _ = self.relay.unbounded_send(Broadcast::DropRound(Round(round), SetId(set_id))); + } + + fn drop_set_messages(&self, set_id: u64) { + let _ = self.relay.unbounded_send(Broadcast::DropSet(SetId(set_id))); + } + + fn commit_messages(&self, set_id: u64) -> Self::In { + self.network.commit_messages(set_id) + } + + fn send_commit(&self, round: u64, set_id: u64, message: Vec) { + let _ = self.relay.unbounded_send(Broadcast::Commit(Round(round), SetId(set_id), message)); + } + + fn announce(&self, round: u64, set_id: u64, block: B::Hash) { + let _ = self.relay.unbounded_send( + Broadcast::Announcement(Round(round), SetId(set_id), block) + ); + } +} + // check a message. pub(crate) fn check_message_sig( message: &Message, id: &AuthorityId, - signature: &ed25519::Signature, + signature: &AuthoritySignature, round: u64, set_id: u64, ) -> Result<(), ()> { - let as_public = ::ed25519::Public::from_raw(id.0); + let as_public = AuthorityId::from_raw(id.0); let encoded_raw = localized_payload(round, set_id, message); - if ::ed25519::verify_strong(signature, &encoded_raw, as_public) { + if ed25519::Pair::verify(signature, &encoded_raw, as_public) { Ok(()) } else { debug!(target: "afg", "Bad signature on message from {:?}", id); @@ -52,44 +263,59 @@ pub(crate) fn check_message_sig( /// converts a message stream into a stream of signed messages. /// the output stream checks signatures also. pub(crate) fn checked_message_stream( - round: u64, - set_id: u64, inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream,Error=Error> where S: Stream,Error=()> { inner .filter_map(|raw| { - let decoded = SignedMessage::::decode(&mut &raw[..]); + let decoded = GossipMessage::::decode(&mut &raw[..]); if decoded.is_none() { debug!(target: "afg", "Skipping malformed message {:?}", raw); } decoded }) .and_then(move |msg| { - // check signature. - if !voters.contains_key(&msg.id) { - debug!(target: "afg", "Skipping message from unknown voter {}", msg.id); - return Ok(None); + match msg { + GossipMessage::VoteOrPrecommit(msg) => { + // check signature. + if !voters.contains_key(&msg.message.id) { + debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); + return Ok(None); + } + + match &msg.message.message { + Prevote(prevote) => { + telemetry!(CONSENSUS_INFO; "afg.received_prevote"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?prevote.target_number, + "target_hash" => ?prevote.target_hash, + ); + }, + Precommit(precommit) => { + telemetry!(CONSENSUS_INFO; "afg.received_precommit"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?precommit.target_number, + "target_hash" => ?precommit.target_hash, + ); + }, + }; + + Ok(Some(msg.message)) + } + _ => { + debug!(target: "afg", "Skipping unknown message type"); + return Ok(None); + } } - - // we ignore messages where the signature doesn't check out. - let res = check_message_sig::( - &msg.message, - &msg.id, - &msg.signature, - round, - set_id - ); - Ok(res.map(move |()| msg).ok()) }) .filter_map(|x| x) .map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream"))) } -struct OutgoingMessages { +pub(crate) struct OutgoingMessages> { round: u64, set_id: u64, locals: Option<(Arc, AuthorityId)>, @@ -97,23 +323,36 @@ struct OutgoingMessages { network: N, } -impl Sink for OutgoingMessages { +impl> Sink for OutgoingMessages +{ type SinkItem = Message; type SinkError = Error; fn start_send(&mut self, msg: Message) -> StartSend, Error> { // when locals exist, sign messages on import - if let Some((ref pair, local_id)) = self.locals { + if let Some((ref pair, ref local_id)) = self.locals { let encoded = localized_payload(self.round, self.set_id, &msg); let signature = pair.sign(&encoded[..]); + + let target_hash = msg.target().0.clone(); let signed = SignedMessage:: { message: msg, signature, - id: local_id, + id: local_id.clone(), }; - // forward to network and to inner sender. - self.network.send_message(self.round, self.set_id, signed.encode()); + let message = GossipMessage::VoteOrPrecommit(VoteOrPrecommitMessage:: { + message: signed.clone(), + round: self.round, + set_id: self.set_id, + }); + + // announce our block hash to peers and propagate the + // message. + self.network.announce(self.round, self.set_id, target_hash); + self.network.send_message(self.round, self.set_id, message.encode()); + + // forward the message to the inner sender. let _ = self.sender.unbounded_send(signed); } @@ -128,9 +367,9 @@ impl Sink for OutgoingMessages { } } -impl Drop for OutgoingMessages { +impl> Drop for OutgoingMessages { fn drop(&mut self) { - self.network.drop_messages(self.round, self.set_id); + self.network.drop_round_messages(self.round, self.set_id); } } @@ -139,15 +378,15 @@ impl Drop for OutgoingMessages { /// /// A future can push unsigned messages into the sink. They will be automatically /// broadcast to the network. The returned stream should be combined with other input. -pub(crate) fn outgoing_messages( +pub(crate) fn outgoing_messages>( round: u64, set_id: u64, local_key: Option>, - voters: Arc>, + voters: Arc>, network: N, ) -> ( impl Stream,Error=Error>, - impl Sink,SinkError=Error>, + OutgoingMessages, ) { let locals = local_key.and_then(|pair| { let public = pair.public(); @@ -177,35 +416,19 @@ pub(crate) fn outgoing_messages( fn check_compact_commit( msg: CompactCommit, - voters: &HashMap, - round: u64, - set_id: u64, + voters: &VoterSet, ) -> Option> { - use grandpa::Message as GrandpaMessage; if msg.precommits.len() != msg.auth_data.len() || msg.precommits.is_empty() { debug!(target: "afg", "Skipping malformed compact commit"); return None; } // check signatures on all contained precommits. - for (precommit, &(ref sig, ref id)) in msg.precommits.iter().zip(&msg.auth_data) { + for (_, ref id) in &msg.auth_data { if !voters.contains_key(id) { debug!(target: "afg", "Skipping commit containing unknown voter {}", id); return None; } - - let res = check_message_sig::( - &GrandpaMessage::Precommit(precommit.clone()), - id, - sig, - round, - set_id, - ); - - if let Err(()) = res { - debug!(target: "afg", "Skipping commit containing bad message"); - return None; - } } Some(msg) @@ -214,9 +437,8 @@ fn check_compact_commit( /// A stream for incoming commit messages. This checks all the signatures on the /// messages. pub(crate) fn checked_commit_stream( - set_id: u64, inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream),Error=Error> where S: Stream,Error=()> @@ -224,42 +446,69 @@ pub(crate) fn checked_commit_stream( inner .filter_map(|raw| { // this could be optimized by decoding piecewise. - let decoded = <(u64, CompactCommit)>::decode(&mut &raw[..]); + let decoded = GossipMessage::::decode(&mut &raw[..]); if decoded.is_none() { trace!(target: "afg", "Skipping malformed commit message {:?}", raw); } decoded }) - .filter_map(move |(round, msg)| { - check_compact_commit::(msg, &*voters, round, set_id).map(move |c| (round, c)) + .filter_map(move |msg| { + match msg { + GossipMessage::Commit(msg) => { + let round = msg.round; + let precommits_signed_by: Vec = + msg.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.received_commit"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "target_number" => ?msg.message.target_number, + "target_hash" => ?msg.message.target_hash, + ); + check_compact_commit::(msg.message, &*voters).map(move |c| (round, c)) + }, + _ => { + debug!(target: "afg", "Skipping unknown message type"); + return None; + } + } }) .map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream"))) } /// An output sink for commit messages. -pub(crate) struct CommitsOut { +pub(crate) struct CommitsOut> { network: N, set_id: u64, _marker: ::std::marker::PhantomData, + is_voter: bool, } -impl CommitsOut { +impl> CommitsOut { /// Create a new commit output stream. - pub(crate) fn new(network: N, set_id: u64) -> Self { + pub(crate) fn new(network: N, set_id: u64, is_voter: bool) -> Self { CommitsOut { network, set_id, + is_voter, _marker: Default::default(), } } } -impl Sink for CommitsOut { +impl> Sink for CommitsOut { type SinkItem = (u64, Commit); type SinkError = Error; fn start_send(&mut self, input: (u64, Commit)) -> StartSend { + if !self.is_voter { + return Ok(AsyncSink::Ready); + } + let (round, commit) = input; + telemetry!(CONSENSUS_INFO; "afg.commit_issued"; + "target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash, + ); let (precommits, auth_data) = commit.precommits.into_iter() .map(|signed| (signed.precommit, (signed.signature, signed.id))) .unzip(); @@ -271,7 +520,13 @@ impl Sink for CommitsOut { auth_data }; - self.network.send_commit(self.set_id, Encode::encode(&(round, compact_commit))); + let message = GossipMessage::Commit(FullCommitMessage:: { + round: round, + set_id: self.set_id, + message: compact_commit, + }); + + self.network.send_commit(round, self.set_id, Encode::encode(&message)); Ok(AsyncSink::Ready) } @@ -279,3 +534,9 @@ impl Sink for CommitsOut { fn close(&mut self) -> Poll<(), Error> { Ok(Async::Ready(())) } fn poll_complete(&mut self) -> Poll<(), Error> { Ok(Async::Ready(())) } } + +impl> Drop for CommitsOut { + fn drop(&mut self) { + self.network.drop_set_messages(self.set_id); + } +} diff --git a/core/finality-grandpa/src/consensus_changes.rs b/core/finality-grandpa/src/consensus_changes.rs new file mode 100644 index 0000000000000000000000000000000000000000..cbd7b30f8e7a5ebcb2883baf4ea0be20683357d6 --- /dev/null +++ b/core/finality-grandpa/src/consensus_changes.rs @@ -0,0 +1,73 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::sync::Arc; +use parity_codec::{Encode, Decode}; + +/// Consensus-related data changes tracker. +#[derive(Clone, Debug, Encode, Decode)] +pub(crate) struct ConsensusChanges { + pending_changes: Vec<(N, H)>, +} + +impl ConsensusChanges { + /// Create empty consensus changes. + pub(crate) fn empty() -> Self { + ConsensusChanges { pending_changes: Vec::new(), } + } +} + +impl ConsensusChanges { + + /// Note unfinalized change of consensus-related data. + pub(crate) fn note_change(&mut self, at: (N, H)) { + let idx = self.pending_changes + .binary_search_by_key(&at.0, |change| change.0) + .unwrap_or_else(|i| i); + self.pending_changes.insert(idx, at); + } + + /// Finalize all pending consensus changes that are finalized by given block. + /// Returns true if there any changes were finalized. + pub(crate) fn finalize ::client::error::Result>>( + &mut self, + block: (N, H), + canonical_at_height: F, + ) -> ::client::error::Result<(bool, bool)> { + let (split_idx, has_finalized_changes) = self.pending_changes.iter() + .enumerate() + .take_while(|(_, &(at_height, _))| at_height <= block.0) + .fold((None, Ok(false)), |(_, has_finalized_changes), (idx, ref at)| + ( + Some(idx), + has_finalized_changes + .and_then(|has_finalized_changes| if has_finalized_changes { + Ok(has_finalized_changes) + } else { + canonical_at_height(at.0).map(|can_hash| Some(at.1) == can_hash) + }), + )); + + let altered_changes = split_idx.is_some(); + if let Some(split_idx) = split_idx { + self.pending_changes = self.pending_changes.split_off(split_idx + 1); + } + has_finalized_changes.map(|has_finalized_changes| (altered_changes, has_finalized_changes)) + } +} + +/// Thread-safe consensus changes tracker reference. +pub(crate) type SharedConsensusChanges = Arc>>; diff --git a/core/finality-grandpa/src/environment.rs b/core/finality-grandpa/src/environment.rs new file mode 100644 index 0000000000000000000000000000000000000000..685337a311b401f9248a09745465dc9dcb311d76 --- /dev/null +++ b/core/finality-grandpa/src/environment.rs @@ -0,0 +1,622 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use log::{debug, warn, info}; +use parity_codec::Encode; +use futures::prelude::*; +use tokio::timer::Delay; +use parking_lot::RwLock; + +use client::{ + backend::Backend, BlockchainEvents, CallExecutor, Client, error::Error as ClientError +}; +use grandpa::{ + BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState, voter, VoterSet, +}; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{ + As, Block as BlockT, Header as HeaderT, NumberFor, One, Zero, +}; +use substrate_primitives::{Blake2Hasher, ed25519, H256, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; + +use crate::{ + Commit, Config, Error, Network, Precommit, Prevote, + CommandOrError, NewAuthoritySet, VoterCommand, +}; + +use crate::authorities::SharedAuthoritySet; +use crate::consensus_changes::SharedConsensusChanges; +use crate::justification::GrandpaJustification; +use crate::until_imported::UntilVoteTargetImported; + +use ed25519::Public as AuthorityId; + +/// Data about a completed round. +pub(crate) type CompletedRound = (u64, RoundState); + +/// A read-only view of the last completed round. +pub(crate) struct LastCompletedRound { + inner: RwLock>, +} + +impl LastCompletedRound { + /// Create a new tracker based on some starting last-completed round. + pub(crate) fn new(round: CompletedRound) -> Self { + LastCompletedRound { inner: RwLock::new(round) } + } + + /// Read the last completed round. + pub(crate) fn read(&self) -> CompletedRound { + self.inner.read().clone() + } + + // NOTE: not exposed outside of this module intentionally. + fn with(&self, f: F) -> R + where F: FnOnce(&mut CompletedRound) -> R + { + f(&mut *self.inner.write()) + } +} + +/// The environment we run GRANDPA in. +pub(crate) struct Environment, RA> { + pub(crate) inner: Arc>, + pub(crate) voters: Arc>, + pub(crate) config: Config, + pub(crate) authority_set: SharedAuthoritySet>, + pub(crate) consensus_changes: SharedConsensusChanges>, + pub(crate) network: N, + pub(crate) set_id: u64, + pub(crate) last_completed: LastCompletedRound>, +} + +impl, B, E, N, RA> grandpa::Chain> for Environment where + Block: 'static, + B: Backend + 'static, + E: CallExecutor + 'static, + N: Network + 'static, + N::In: 'static, + NumberFor: BlockNumberOps, +{ + fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { + if base == block { return Err(GrandpaError::NotDescendent) } + + let tree_route_res = ::client::blockchain::tree_route( + self.inner.backend().blockchain(), + BlockId::Hash(block), + BlockId::Hash(base), + ); + + let tree_route = match tree_route_res { + Ok(tree_route) => tree_route, + Err(e) => { + debug!(target: "afg", "Encountered error computing ancestry between block {:?} and base {:?}: {:?}", + block, base, e); + + return Err(GrandpaError::NotDescendent); + } + }; + + if tree_route.common_block().hash != base { + return Err(GrandpaError::NotDescendent); + } + + // skip one because our ancestry is meant to start from the parent of `block`, + // and `tree_route` includes it. + Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) + } + + fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, NumberFor)> { + // NOTE: when we finalize an authority set change through the sync protocol the voter is + // signalled asynchronously. therefore the voter could still vote in the next round + // before activating the new set. the `authority_set` is updated immediately thus we + // restrict the voter based on that. + if self.set_id != self.authority_set.inner().read().current().0 { + return None; + } + + // we refuse to vote beyond the current limit number where transitions are scheduled to + // occur. + // once blocks are finalized that make that transition irrelevant or activate it, + // we will proceed onwards. most of the time there will be no pending transition. + let limit = self.authority_set.current_limit(); + debug!(target: "afg", "Finding best chain containing block {:?} with number limit {:?}", block, limit); + + match self.inner.best_containing(block, None) { + Ok(Some(mut best_hash)) => { + let base_header = self.inner.header(&BlockId::Hash(block)).ok()? + .expect("Header known to exist after `best_containing` call; qed"); + + if let Some(limit) = limit { + // this is a rare case which might cause issues, + // might be better to return the header itself. + if *base_header.number() > limit { + debug!(target: "afg", "Encountered error finding best chain containing {:?} with limit {:?}: target block is after limit", + block, + limit, + ); + return None; + } + } + + let mut best_header = self.inner.header(&BlockId::Hash(best_hash)).ok()? + .expect("Header known to exist after `best_containing` call; qed"); + + // we target a vote towards 3/4 of the unfinalized chain (rounding up) + let target = { + let two = NumberFor::::one() + One::one(); + let three = two + One::one(); + let four = three + One::one(); + + let diff = *best_header.number() - *base_header.number(); + let diff = ((diff * three) + two) / four; + + *base_header.number() + diff + }; + + // unless our vote is currently being limited due to a pending change + let target = limit.map(|limit| limit.min(target)).unwrap_or(target); + + // walk backwards until we find the target block + loop { + if *best_header.number() < target { unreachable!(); } + if *best_header.number() == target { + return Some((best_hash, *best_header.number())); + } + + best_hash = *best_header.parent_hash(); + best_header = self.inner.header(&BlockId::Hash(best_hash)).ok()? + .expect("Header known to exist after `best_containing` call; qed"); + } + }, + Ok(None) => { + debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find target block", block); + None + } + Err(e) => { + debug!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e); + None + } + } + } +} + +impl, N, RA> voter::Environment> for Environment where + Block: 'static, + B: Backend + 'static, + E: CallExecutor + 'static + Send + Sync, + N: Network + 'static + Send, + N::In: 'static + Send, + RA: 'static + Send + Sync, + NumberFor: BlockNumberOps, +{ + type Timer = Box + Send>; + type Id = AuthorityId; + type Signature = ed25519::Signature; + + // regular round message streams + type In = Box, Self::Signature, Self::Id>, + Error = Self::Error, + > + Send>; + type Out = Box>, + SinkError = Self::Error, + > + Send>; + + type Error = CommandOrError>; + + fn round_data( + &self, + round: u64 + ) -> voter::RoundData { + let now = Instant::now(); + let prevote_timer = Delay::new(now + self.config.gossip_duration * 2); + let precommit_timer = Delay::new(now + self.config.gossip_duration * 4); + + let incoming = crate::communication::checked_message_stream::( + self.network.messages_for(round, self.set_id), + self.voters.clone(), + ); + + let local_key = self.config.local_key.as_ref() + .filter(|pair| self.voters.contains_key(&pair.public().into())); + + let (out_rx, outgoing) = crate::communication::outgoing_messages::( + round, + self.set_id, + local_key.cloned(), + self.voters.clone(), + self.network.clone(), + ); + + // schedule incoming messages from the network to be held until + // corresponding blocks are imported. + let incoming = UntilVoteTargetImported::new( + self.inner.import_notification_stream(), + self.inner.clone(), + incoming, + ); + + // join incoming network messages with locally originating ones. + let incoming = Box::new(out_rx.select(incoming).map_err(Into::into)); + + // schedule network message cleanup when sink drops. + let outgoing = Box::new(outgoing.sink_map_err(Into::into)); + + voter::RoundData { + prevote_timer: Box::new(prevote_timer.map_err(|e| Error::Timer(e).into())), + precommit_timer: Box::new(precommit_timer.map_err(|e| Error::Timer(e).into())), + incoming, + outgoing, + } + } + + fn completed(&self, round: u64, state: RoundState>) -> Result<(), Self::Error> { + debug!( + target: "afg", "Voter {} completed round {} in set {}. Estimate = {:?}, Finalized in round = {:?}", + self.config.name(), + round, + self.set_id, + state.estimate.as_ref().map(|e| e.1), + state.finalized.as_ref().map(|e| e.1), + ); + + self.last_completed.with(|last_completed| { + let set_state = crate::aux_schema::VoterSetState::Live(round, state.clone()); + crate::aux_schema::write_voter_set_state(&**self.inner.backend(), &set_state)?; + + *last_completed = (round, state); // after writing to DB successfully. + Ok(()) + }) + } + + fn finalize_block(&self, hash: Block::Hash, number: NumberFor, round: u64, commit: Commit) -> Result<(), Self::Error> { + use client::blockchain::HeaderBackend; + + let status = self.inner.backend().blockchain().info()?; + if number <= status.finalized_number && self.inner.backend().blockchain().hash(number)? == Some(hash) { + // This can happen after a forced change (triggered by the finality tracker when finality is stalled), since + // the voter will be restarted at the median last finalized block, which can be lower than the local best + // finalized block. + warn!(target: "afg", "Re-finalized block #{:?} ({:?}) in the canonical chain, current best finalized is #{:?}", + hash, + number, + status.finalized_number, + ); + + return Ok(()); + } + + finalize_block( + &*self.inner, + &self.authority_set, + &self.consensus_changes, + Some(As::sa(self.config.justification_period)), + hash, + number, + (round, commit).into(), + ) + } + + fn round_commit_timer(&self) -> Self::Timer { + use rand::{thread_rng, Rng}; + + //random between 0-1 seconds. + let delay: u64 = thread_rng().gen_range(0, 1000); + Box::new(Delay::new( + Instant::now() + Duration::from_millis(delay) + ).map_err(|e| Error::Timer(e).into())) + } + + fn prevote_equivocation( + &self, + _round: u64, + equivocation: ::grandpa::Equivocation, Self::Signature> + ) { + warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); + // nothing yet; this could craft misbehavior reports of some kind. + } + + fn precommit_equivocation( + &self, + _round: u64, + equivocation: Equivocation, Self::Signature> + ) { + warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); + // nothing yet + } +} + +pub(crate) enum JustificationOrCommit { + Justification(GrandpaJustification), + Commit((u64, Commit)), +} + +impl From<(u64, Commit)> for JustificationOrCommit { + fn from(commit: (u64, Commit)) -> JustificationOrCommit { + JustificationOrCommit::Commit(commit) + } +} + +impl From> for JustificationOrCommit { + fn from(justification: GrandpaJustification) -> JustificationOrCommit { + JustificationOrCommit::Justification(justification) + } +} + +/// Finalize the given block and apply any authority set changes. If an +/// authority set change is enacted then a justification is created (if not +/// given) and stored with the block when finalizing it. +/// This method assumes that the block being finalized has already been imported. +pub(crate) fn finalize_block, E, RA>( + client: &Client, + authority_set: &SharedAuthoritySet>, + consensus_changes: &SharedConsensusChanges>, + justification_period: Option>, + hash: Block::Hash, + number: NumberFor, + justification_or_commit: JustificationOrCommit, +) -> Result<(), CommandOrError>> where + B: Backend, + E: CallExecutor + Send + Sync, + RA: Send + Sync, +{ + // lock must be held through writing to DB to avoid race + let mut authority_set = authority_set.inner().write(); + + // FIXME #1483: clone only when changed + let old_authority_set = authority_set.clone(); + // holds the old consensus changes in case it is changed below, needed for + // reverting in case of failure + let mut old_consensus_changes = None; + + let mut consensus_changes = consensus_changes.lock(); + let canon_at_height = |canon_number| { + // "true" because the block is finalized + canonical_at_height(client, (hash, number), true, canon_number) + }; + + let update_res: Result<_, Error> = client.lock_import_and_run(|import_op| { + let status = authority_set.apply_standard_changes( + hash, + number, + &is_descendent_of(client, None), + ).map_err(|e| Error::Safety(e.to_string()))?; + + // check if this is this is the first finalization of some consensus changes + let (alters_consensus_changes, finalizes_consensus_changes) = consensus_changes + .finalize((number, hash), &canon_at_height)?; + + if alters_consensus_changes { + old_consensus_changes = Some(consensus_changes.clone()); + + let write_result = crate::aux_schema::update_consensus_changes( + &*consensus_changes, + |insert| client.apply_aux(import_op, insert, &[]), + ); + + if let Err(e) = write_result { + warn!(target: "finality", "Failed to write updated consensus changes to disk. Bailing."); + warn!(target: "finality", "Node is in a potentially inconsistent state."); + + return Err(e.into()); + } + } + + // NOTE: this code assumes that honest voters will never vote past a + // transition block, thus we don't have to worry about the case where + // we have a transition with `effective_block = N`, but we finalize + // `N+1`. this assumption is required to make sure we store + // justifications for transition blocks which will be requested by + // syncing clients. + let justification = match justification_or_commit { + JustificationOrCommit::Justification(justification) => Some(justification.encode()), + JustificationOrCommit::Commit((round_number, commit)) => { + let mut justification_required = + // justification is always required when block that enacts new authorities + // set is finalized + status.new_set_block.is_some() || + // justification is required when consensus changes are finalized + finalizes_consensus_changes; + + // justification is required every N blocks to be able to prove blocks + // finalization to remote nodes + if !justification_required { + if let Some(justification_period) = justification_period { + let last_finalized_number = client.info()?.chain.finalized_number; + justification_required = + (!last_finalized_number.is_zero() || number - last_finalized_number == justification_period) && + (last_finalized_number / justification_period != number / justification_period); + } + } + + if justification_required { + let justification = GrandpaJustification::from_commit( + client, + round_number, + commit, + )?; + + Some(justification.encode()) + } else { + None + } + }, + }; + + debug!(target: "afg", "Finalizing blocks up to ({:?}, {})", number, hash); + + // ideally some handle to a synchronization oracle would be used + // to avoid unconditionally notifying. + client.apply_finality(import_op, BlockId::Hash(hash), justification, true).map_err(|e| { + warn!(target: "finality", "Error applying finality to block {:?}: {:?}", (hash, number), e); + e + })?; + telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to"; + "number" => ?number, "hash" => ?hash, + ); + + let new_authorities = if let Some((canon_hash, canon_number)) = status.new_set_block { + // the authority set has changed. + let (new_id, set_ref) = authority_set.current(); + + if set_ref.len() > 16 { + info!("Applying GRANDPA set change to new set with {} authorities", set_ref.len()); + } else { + info!("Applying GRANDPA set change to new set {:?}", set_ref); + } + + telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set"; + "number" => ?canon_number, "hash" => ?canon_hash, + "authorities" => ?set_ref.to_vec(), + "set_id" => ?new_id, + ); + Some(NewAuthoritySet { + canon_hash, + canon_number, + set_id: new_id, + authorities: set_ref.to_vec(), + }) + } else { + None + }; + + if status.changed { + let write_result = crate::aux_schema::update_authority_set( + &authority_set, + new_authorities.as_ref(), + |insert| client.apply_aux(import_op, insert, &[]), + ); + + if let Err(e) = write_result { + warn!(target: "finality", "Failed to write updated authority set to disk. Bailing."); + warn!(target: "finality", "Node is in a potentially inconsistent state."); + + return Err(e.into()); + } + } + + Ok(new_authorities.map(VoterCommand::ChangeAuthorities)) + }); + + match update_res { + Ok(Some(command)) => Err(CommandOrError::VoterCommand(command)), + Ok(None) => Ok(()), + Err(e) => { + *authority_set = old_authority_set; + + if let Some(old_consensus_changes) = old_consensus_changes { + *consensus_changes = old_consensus_changes; + } + + Err(CommandOrError::Error(e)) + } + } +} + +/// Using the given base get the block at the given height on this chain. The +/// target block must be an ancestor of base, therefore `height <= base.height`. +pub(crate) fn canonical_at_height, RA>( + client: &Client, + base: (Block::Hash, NumberFor), + base_is_canonical: bool, + height: NumberFor, +) -> Result, ClientError> where + B: Backend, + E: CallExecutor + Send + Sync, +{ + use runtime_primitives::traits::{One, Zero, BlockNumberToHash}; + + if height > base.1 { + return Ok(None); + } + + if height == base.1 { + if base_is_canonical { + return Ok(Some(base.0)); + } else { + return Ok(client.block_number_to_hash(height)); + } + } else if base_is_canonical { + return Ok(client.block_number_to_hash(height)); + } + + let one = NumberFor::::one(); + + // start by getting _canonical_ block with number at parent position and then iterating + // backwards by hash. + let mut current = match client.header(&BlockId::Number(base.1 - one))? { + Some(header) => header, + _ => return Ok(None), + }; + + // we've already checked that base > height above. + let mut steps = base.1 - height - one; + + while steps > NumberFor::::zero() { + current = match client.header(&BlockId::Hash(*current.parent_hash()))? { + Some(header) => header, + _ => return Ok(None), + }; + + steps -= one; + } + + Ok(Some(current.hash())) +} + +/// Returns a function for checking block ancestry, the returned function will +/// return `true` if the given hash (second parameter) is a descendent of the +/// base (first parameter). If the `current` parameter is defined, it should +/// represent the current block `hash` and its `parent hash`, if given the +/// function that's returned will assume that `hash` isn't part of the local DB +/// yet, and all searches in the DB will instead reference the parent. +pub fn is_descendent_of<'a, B, E, Block: BlockT, RA>( + client: &'a Client, + current: Option<(&'a H256, &'a H256)>, +) -> impl Fn(&H256, &H256) -> Result + 'a +where B: Backend, + E: CallExecutor + Send + Sync, +{ + move |base, hash| { + if base == hash { return Ok(false); } + + let mut hash = hash; + if let Some((current_hash, current_parent_hash)) = current { + if base == current_hash { return Ok(false); } + if hash == current_hash { + if base == current_parent_hash { + return Ok(true); + } else { + hash = current_parent_hash; + } + } + } + + let tree_route = client::blockchain::tree_route( + client.backend().blockchain(), + BlockId::Hash(*hash), + BlockId::Hash(*base), + )?; + + Ok(tree_route.common_block().hash == *base) + } +} diff --git a/core/finality-grandpa/src/finality_proof.rs b/core/finality-grandpa/src/finality_proof.rs new file mode 100644 index 0000000000000000000000000000000000000000..2b34a094a06494cad6ff2c1d49f37a35bcf6afe6 --- /dev/null +++ b/core/finality-grandpa/src/finality_proof.rs @@ -0,0 +1,432 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! GRANDPA block finality proof generation and check. +//! +//! Finality of block B is proved by providing: +//! 1) valid headers sub-chain from the block B to the block F; +//! 2) valid (with respect to proved authorities) GRANDPA justification of the block F; +//! 3) proof-of-execution of the `grandpa_authorities` call at the block F. +//! +//! Since earliest possible justification is returned, the GRANDPA authorities set +//! at the block F is guaranteed to be the same as in the block B (this is because block +//! that enacts new GRANDPA authorities set always comes with justification). It also +//! means that the `set_id` is the same at blocks B and F. +//! +//! The caller should track the `set_id`. The most straightforward way is to fetch finality +//! proofs ONLY for blocks on the tip of the chain and track the latest known `set_id`. + +use grandpa::VoterSet; + +use client::{ + blockchain::Backend as BlockchainBackend, + error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult}, + light::fetcher::RemoteCallRequest, +}; +use parity_codec::{Encode, Decode}; +use grandpa::BlockNumberOps; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{ + NumberFor, Block as BlockT, Header as HeaderT, One, +}; +use substrate_primitives::{ed25519, H256}; +use ed25519::Public as AuthorityId; +use substrate_telemetry::{telemetry, CONSENSUS_INFO}; + +use crate::justification::GrandpaJustification; + +/// Prepare proof-of-finality for the given block. +/// +/// The proof is the serialized `FinalityProof` constructed using earliest known +/// justification of the block. None is returned if there's no known justification atm. +pub fn prove_finality( + blockchain: &B, + generate_execution_proof: G, + block: Block::Hash, +) -> ::client::error::Result>> + where + B: BlockchainBackend, + G: Fn(&BlockId, &str, &[u8]) -> ClientResult>>, +{ + let block_id = BlockId::Hash(block); + let mut block_number = blockchain.expect_block_number_from_id(&block_id)?; + + // early-return if we sure that the block isn't finalized yet + let info = blockchain.info()?; + if info.finalized_number < block_number { + return Ok(None); + } + + // early-return if we sure that the block is NOT a part of canonical chain + let canonical_block = blockchain.expect_block_hash_from_id(&BlockId::Number(block_number))?; + if block != canonical_block { + return Err(ClientErrorKind::Backend( + "Cannot generate finality proof for non-canonical block".into() + ).into()); + } + + // now that we know that the block is finalized, we can generate finalization proof + + // we need to prove grandpa authorities set that has generated justification + // BUT since `GrandpaApi::grandpa_authorities` call returns the set that becames actual + // at the next block, the proof-of execution is generated using parent block' state + // (this will fail if we're trying to prove genesis finality, but such the call itself is redundant) + let mut current_header = blockchain.expect_header(BlockId::Hash(block))?; + let parent_block_id = BlockId::Hash(*current_header.parent_hash()); + let authorities_proof = generate_execution_proof( + &parent_block_id, + "GrandpaApi_grandpa_authorities", + &[], + )?; + + // search for earliest post-block (inclusive) justification + let mut finalization_path = Vec::new(); + loop { + finalization_path.push(current_header); + + match blockchain.justification(BlockId::Number(block_number))? { + Some(justification) => return Ok(Some(FinalityProof { + finalization_path, + justification, + authorities_proof, + }.encode())), + None if block_number == info.finalized_number => break, + None => { + block_number = block_number + One::one(); + current_header = blockchain.expect_header(BlockId::Number(block_number))?; + }, + } + } + + Err(ClientErrorKind::Backend( + "cannot find justification for finalized block".into() + ).into()) +} + +/// Check proof-of-finality for the given block. +/// +/// Returns the vector of headers (including `block` header, ordered by ASC block number) that MUST be +/// validated + imported at once (i.e. within single db transaction). If at least one of those headers +/// is invalid, all other MUST be considered invalid. +pub fn check_finality_proof, C>( + check_execution_proof: C, + parent_header: Block::Header, + block: (NumberFor, Block::Hash), + set_id: u64, + remote_proof: Vec, +) -> ClientResult> + where + NumberFor: grandpa::BlockNumberOps, + C: Fn(&RemoteCallRequest) -> ClientResult>, +{ + do_check_finality_proof::>( + check_execution_proof, + parent_header, + block, + set_id, + remote_proof, + ) +} + +/// Check proof-of-finality using given justification type. +fn do_check_finality_proof, C, J>( + check_execution_proof: C, + parent_header: Block::Header, + block: (NumberFor, Block::Hash), + set_id: u64, + remote_proof: Vec, +) -> ClientResult> + where + NumberFor: grandpa::BlockNumberOps, + C: Fn(&RemoteCallRequest) -> ClientResult>, + J: ProvableJustification, +{ + // decode finality proof + let proof = FinalityProof::::decode(&mut &remote_proof[..]) + .ok_or_else(|| ClientErrorKind::BadJustification("failed to decode finality proof".into()))?; + + // check that the first header in finalization path is the block itself + { + let finalized_header = proof.finalization_path.first() + .ok_or_else(|| ClientError::from(ClientErrorKind::BadJustification( + "finality proof: finalized path is empty".into() + )))?; + if *finalized_header.number() != block.0 || finalized_header.hash() != block.1 { + return Err(ClientErrorKind::BadJustification( + "finality proof: block is not a part of finalized path".into() + ).into()); + } + } + + // check that the last header in finalization path is the justification target block + let just_block = proof.justification.target_block(); + { + let finalized_header = proof.finalization_path.last() + .expect("checked above that proof.finalization_path is not empty; qed"); + if *finalized_header.number() != just_block.0 || finalized_header.hash() != just_block.1 { + return Err(ClientErrorKind::BadJustification( + "finality proof: target justification block is not a part of finalized path".into() + ).into()); + } + } + + // check authorities set proof && get grandpa authorities that should have signed justification + let grandpa_authorities = check_execution_proof(&RemoteCallRequest { + block: just_block.1, + header: parent_header, + method: "GrandpaApi_grandpa_authorities".into(), + call_data: vec![], + retry_count: None, + })?; + let grandpa_authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &grandpa_authorities[..]) + .ok_or_else(|| ClientErrorKind::BadJustification("failed to decode GRANDPA authorities set proof".into()))?; + + // and now check justification + proof.justification.verify(set_id, &grandpa_authorities.into_iter().collect())?; + + telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok"; + "set_id" => ?set_id, "finalized_header_hash" => ?block.1); + Ok(proof.finalization_path) +} + +/// Proof of finality. +/// +/// Finality of block B is proved by providing: +/// 1) valid headers sub-chain from the block B to the block F; +/// 2) proof of `GrandpaApi::grandpa_authorities()` call at the block F; +/// 3) valid (with respect to proved authorities) GRANDPA justification of the block F. +#[derive(Debug, PartialEq, Encode, Decode)] +struct FinalityProof { + /// Headers-path (ordered by block number, ascending) from the block we're gathering proof for + /// (inclusive) to the target block of the justification (inclusive). + pub finalization_path: Vec
, + /// Justification (finalization) of the last block from the `finalization_path`. + pub justification: Justification, + /// Proof of `GrandpaApi::grandpa_authorities` call execution at the + /// justification' target block. + pub authorities_proof: Vec>, +} + +/// Justification used to prove block finality. +trait ProvableJustification: Encode + Decode { + /// Get target block of this justification. + fn target_block(&self) -> (Header::Number, Header::Hash); + + /// Verify justification with respect to authorities set and authorities set id. + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()>; +} + +impl> ProvableJustification for GrandpaJustification + where + NumberFor: BlockNumberOps, +{ + fn target_block(&self) -> (NumberFor, Block::Hash) { + (self.commit.target_number, self.commit.target_hash) + } + + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + GrandpaJustification::verify(self, set_id, authorities) + } +} + +#[cfg(test)] +mod tests { + use test_client::runtime::{Block, Header}; + use test_client::client::backend::NewBlockState; + use test_client::client::in_mem::Blockchain as InMemoryBlockchain; + use super::*; + + type FinalityProof = super::FinalityProof>; + + #[derive(Encode, Decode)] + struct ValidFinalityProof(Vec); + + impl ProvableJustification
for ValidFinalityProof { + fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } + + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + assert_eq!(set_id, 1); + assert_eq!(authorities, &vec![ + (AuthorityId([1u8; 32]), 1), + (AuthorityId([2u8; 32]), 2), + (AuthorityId([3u8; 32]), 3), + ].into_iter().collect()); + Ok(()) + } + } + + fn header(number: u64) -> Header { + let parent_hash = match number { + 0 => Default::default(), + _ => header(number - 1).hash(), + }; + Header::new(number, H256::from_low_u64_be(0), H256::from_low_u64_be(0), parent_hash, Default::default()) + } + + fn side_header(number: u64) -> Header { + Header::new(number, H256::from_low_u64_be(0), H256::from_low_u64_be(1), header(number - 1).hash(), Default::default()) + } + + fn test_blockchain() -> InMemoryBlockchain { + let blockchain = InMemoryBlockchain::::new(); + blockchain.insert(header(0).hash(), header(0), Some(vec![0]), None, NewBlockState::Final).unwrap(); + blockchain.insert(header(1).hash(), header(1), Some(vec![1]), None, NewBlockState::Final).unwrap(); + blockchain.insert(header(2).hash(), header(2), None, None, NewBlockState::Best).unwrap(); + blockchain.insert(header(3).hash(), header(3), Some(vec![3]), None, NewBlockState::Final).unwrap(); + blockchain + } + + #[test] + fn finality_proof_is_not_generated_for_non_final_block() { + let blockchain = test_blockchain(); + blockchain.insert(header(4).hash(), header(4), None, None, NewBlockState::Best).unwrap(); + + // when asking for finality of block 4, None is returned + let proof_of_4 = prove_finality(&blockchain, |_, _, _| Ok(vec![vec![42]]), header(4).hash()) + .unwrap(); + assert_eq!(proof_of_4, None); + } + + #[test] + fn finality_proof_fails_for_non_canonical_block() { + let blockchain = test_blockchain(); + blockchain.insert(header(4).hash(), header(4), None, None, NewBlockState::Best).unwrap(); + blockchain.insert(side_header(4).hash(), side_header(4), None, None, NewBlockState::Best).unwrap(); + blockchain.insert(header(5).hash(), header(5), Some(vec![5]), None, NewBlockState::Final).unwrap(); + + // when asking for finality of side-block 42, None is returned + let proof_of_side_4_fails = prove_finality(&blockchain, |_, _, _| Ok(vec![vec![42]]), H256::from_low_u64_be(42)).is_err(); + assert_eq!(proof_of_side_4_fails, true); + } + + #[test] + fn finality_proof_fails_if_no_justification_known() { + let blockchain = test_blockchain(); + blockchain.insert(header(4).hash(), header(4), None, None, NewBlockState::Final).unwrap(); + + // when asking for finality of block 4, search for justification failing + let proof_of_4_fails = prove_finality(&blockchain, |_, _, _| Ok(vec![vec![42]]), H256::from_low_u64_be(42)).is_err(); + assert_eq!(proof_of_4_fails, true); + } + + #[test] + fn prove_finality_is_generated() { + let blockchain = test_blockchain(); + + // when asking for finality of block 2, justification of 3 is returned + let proof_of_2: FinalityProof = prove_finality(&blockchain, |_, _, _| Ok(vec![vec![42]]), header(2).hash()) + .unwrap().and_then(|p| Decode::decode(&mut &p[..])).unwrap(); + assert_eq!(proof_of_2, FinalityProof { + finalization_path: vec![header(2), header(3)], + justification: vec![3], + authorities_proof: vec![vec![42]], + }); + + // when asking for finality of block 3, justification of 3 is returned + let proof_of_3: FinalityProof = prove_finality(&blockchain, |_, _, _| Ok(vec![vec![42]]), header(3).hash()) + .unwrap().and_then(|p| Decode::decode(&mut &p[..])).unwrap(); + assert_eq!(proof_of_3, FinalityProof { + finalization_path: vec![header(3)], + justification: vec![3], + authorities_proof: vec![vec![42]], + }); + } + + #[test] + fn finality_proof_check_fails_when_block_is_not_included() { + let mut proof_of_2: FinalityProof = prove_finality( + &test_blockchain(), + |_, _, _| Ok(vec![vec![42]]), + header(2).hash(), + ).unwrap().and_then(|p| Decode::decode(&mut &p[..])).unwrap(); + proof_of_2.finalization_path.remove(0); + + // block for which we're trying to request finality proof is missing from finalization_path + assert_eq!(do_check_finality_proof::( + |_| Ok(Vec::::new().encode()), + header(1), + (2, header(2).hash()), + 1, + proof_of_2.encode(), + ).is_err(), true); + } + + #[test] + fn finality_proof_check_fails_when_justified_block_is_not_included() { + let mut proof_of_2: FinalityProof = prove_finality( + &test_blockchain(), + |_, _, _| Ok(vec![vec![42]]), + header(2).hash(), + ).unwrap().and_then(|p| Decode::decode(&mut &p[..])).unwrap(); + proof_of_2.finalization_path.remove(1); + + // justified block is missing from finalization_path + assert_eq!(do_check_finality_proof::( + |_| Ok(Vec::::new().encode()), + header(1), + (2, header(2).hash()), + 1, + proof_of_2.encode(), + ).is_err(), true); + } + + #[test] + fn finality_proof_check_fails_when_justification_verification_fails() { + #[derive(Encode, Decode)] + struct InvalidFinalityProof(Vec); + + impl ProvableJustification
for InvalidFinalityProof { + fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } + + fn verify(&self, _set_id: u64, _authorities: &VoterSet) -> ClientResult<()> { + Err(ClientErrorKind::Backend("test error".into()).into()) + } + } + + let mut proof_of_2: FinalityProof = prove_finality( + &test_blockchain(), + |_, _, _| Ok(vec![vec![42]]), + header(2).hash(), + ).unwrap().and_then(|p| Decode::decode(&mut &p[..])).unwrap(); + proof_of_2.finalization_path.remove(1); + + // justification is not valid + assert_eq!(do_check_finality_proof::( + |_| Ok(Vec::::new().encode()), + header(1), + (2, header(2).hash()), + 1, + proof_of_2.encode(), + ).is_err(), true); + } + + #[test] + fn finality_proof_check_works() { + let proof_of_2 = prove_finality(&test_blockchain(), |_, _, _| Ok(vec![vec![42]]), header(2).hash()) + .unwrap().unwrap(); + assert_eq!(do_check_finality_proof::( + |_| Ok(vec![ + (AuthorityId([1u8; 32]), 1u64), + (AuthorityId([2u8; 32]), 2u64), + (AuthorityId([3u8; 32]), 3u64), + ].encode()), + header(1), + (2, header(2).hash()), + 1, + proof_of_2, + ).unwrap(), vec![header(2), header(3)]); + } +} diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs new file mode 100644 index 0000000000000000000000000000000000000000..9ff3486b861f92c00fa1cd855c0bc07ffe4ca3d8 --- /dev/null +++ b/core/finality-grandpa/src/import.rs @@ -0,0 +1,584 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::sync::Arc; + +use log::{debug, trace, info}; +use parity_codec::Encode; +use futures::sync::mpsc; +use parking_lot::RwLockWriteGuard; + +use client::{blockchain, CallExecutor, Client}; +use client::blockchain::HeaderBackend; +use client::backend::Backend; +use client::runtime_api::ApiExt; +use consensus_common::{ + BlockImport, Error as ConsensusError, ErrorKind as ConsensusErrorKind, + ImportBlock, ImportResult, JustificationImport, +}; +use fg_primitives::GrandpaApi; +use runtime_primitives::Justification; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{ + Block as BlockT, DigestFor, DigestItemFor, DigestItem, + Header as HeaderT, NumberFor, ProvideRuntimeApi, +}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; + +use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; +use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; +use crate::consensus_changes::SharedConsensusChanges; +use crate::environment::{finalize_block, is_descendent_of}; +use crate::justification::GrandpaJustification; + +use ed25519::Public as AuthorityId; + +/// A block-import handler for GRANDPA. +/// +/// This scans each imported block for signals of changing authority set. +/// If the block being imported enacts an authority set change then: +/// - If the current authority set is still live: we import the block +/// - Otherwise, the block must include a valid justification. +/// +/// When using GRANDPA, the block import worker should be using this block import +/// object. +pub struct GrandpaBlockImport, RA, PRA> { + inner: Arc>, + authority_set: SharedAuthoritySet>, + send_voter_commands: mpsc::UnboundedSender>>, + consensus_changes: SharedConsensusChanges>, + api: Arc, +} + +impl, RA, PRA> JustificationImport + for GrandpaBlockImport where + NumberFor: grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + DigestItemFor: DigestItem, + RA: Send + Sync, + PRA: ProvideRuntimeApi, + PRA::Api: GrandpaApi, +{ + type Error = ConsensusError; + + fn on_start(&self, link: &::consensus_common::import_queue::Link) { + let chain_info = match self.inner.info() { + Ok(info) => info.chain, + _ => return, + }; + + // request justifications for all pending changes for which change blocks have already been imported + let authorities = self.authority_set.inner().read(); + for pending_change in authorities.pending_changes() { + if pending_change.delay_kind == DelayKind::Finalized && + pending_change.effective_number() > chain_info.finalized_number && + pending_change.effective_number() <= chain_info.best_number + { + let effective_block_hash = self.inner.best_containing( + pending_change.canon_hash, + Some(pending_change.effective_number()), + ); + + if let Ok(Some(hash)) = effective_block_hash { + if let Ok(Some(header)) = self.inner.header(&BlockId::Hash(hash)) { + if *header.number() == pending_change.effective_number() { + link.request_justification(&header.hash(), *header.number()); + } + } + } + } + } + } + + fn import_justification( + &self, + hash: Block::Hash, + number: NumberFor, + justification: Justification, + ) -> Result<(), Self::Error> { + self.import_justification(hash, number, justification, false) + } +} + +enum AppliedChanges { + Standard, + Forced(NewAuthoritySet), + None, +} + +impl AppliedChanges { + fn needs_justification(&self) -> bool { + match *self { + AppliedChanges::Standard => true, + AppliedChanges::Forced(_) | AppliedChanges::None => false, + } + } +} + +struct PendingSetChanges<'a, Block: 'a + BlockT> { + just_in_case: Option<( + AuthoritySet>, + RwLockWriteGuard<'a, AuthoritySet>>, + )>, + applied_changes: AppliedChanges>, + do_pause: bool, +} + +impl<'a, Block: 'a + BlockT> PendingSetChanges<'a, Block> { + // revert the pending set change explicitly. + fn revert(self) { } + + fn defuse(mut self) -> (AppliedChanges>, bool) { + self.just_in_case = None; + let applied_changes = ::std::mem::replace(&mut self.applied_changes, AppliedChanges::None); + (applied_changes, self.do_pause) + } +} + +impl<'a, Block: 'a + BlockT> Drop for PendingSetChanges<'a, Block> { + fn drop(&mut self) { + if let Some((old_set, mut authorities)) = self.just_in_case.take() { + *authorities = old_set; + } + } +} + +impl, RA, PRA> GrandpaBlockImport where + NumberFor: grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + DigestItemFor: DigestItem, + RA: Send + Sync, + PRA: ProvideRuntimeApi, + PRA::Api: GrandpaApi, +{ + // check for a new authority set change. + fn check_new_change(&self, header: &Block::Header, hash: Block::Hash) + -> Result>>, ConsensusError> + { + let at = BlockId::hash(*header.parent_hash()); + let digest = header.digest(); + + let api = self.api.runtime_api(); + + // check for forced change. + { + let maybe_change = api.grandpa_forced_change( + &at, + digest, + ); + + match maybe_change { + Err(e) => match api.has_api_with::, _>(&at, |v| v >= 2) { + Err(e) => return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()), + Ok(true) => { + // API version is high enough to support forced changes + // but got error, so it is legitimate. + return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()) + }, + Ok(false) => { + // API version isn't high enough to support forced changes + }, + }, + Ok(None) => {}, + Ok(Some((median_last_finalized, change))) => return Ok(Some(PendingChange { + next_authorities: change.next_authorities, + delay: change.delay, + canon_height: *header.number(), + canon_hash: hash, + delay_kind: DelayKind::Best { median_last_finalized }, + })), + } + } + + // check normal scheduled change. + { + let maybe_change = api.grandpa_pending_change( + &at, + digest, + ); + + match maybe_change { + Err(e) => Err(ConsensusErrorKind::ClientImport(e.to_string()).into()), + Ok(Some(change)) => Ok(Some(PendingChange { + next_authorities: change.next_authorities, + delay: change.delay, + canon_height: *header.number(), + canon_hash: hash, + delay_kind: DelayKind::Finalized, + })), + Ok(None) => Ok(None), + } + } + } + + fn make_authorities_changes<'a>(&'a self, block: &mut ImportBlock, hash: Block::Hash) + -> Result, ConsensusError> + { + // when we update the authorities, we need to hold the lock + // until the block is written to prevent a race if we need to restore + // the old authority set on error or panic. + struct InnerGuard<'a, T: 'a> { + old: Option, + guard: Option>, + } + + impl<'a, T: 'a> InnerGuard<'a, T> { + fn as_mut(&mut self) -> &mut T { + &mut **self.guard.as_mut().expect("only taken on deconstruction; qed") + } + + fn set_old(&mut self, old: T) { + if self.old.is_none() { + // ignore "newer" old changes. + self.old = Some(old); + } + } + + fn consume(mut self) -> Option<(T, RwLockWriteGuard<'a, T>)> { + if let Some(old) = self.old.take() { + Some((old, self.guard.take().expect("only taken on deconstruction; qed"))) + } else { + None + } + } + } + + impl<'a, T: 'a> Drop for InnerGuard<'a, T> { + fn drop(&mut self) { + if let (Some(mut guard), Some(old)) = (self.guard.take(), self.old.take()) { + *guard = old; + } + } + } + + let number = block.header.number().clone(); + let maybe_change = self.check_new_change( + &block.header, + hash, + )?; + + // returns a function for checking whether a block is a descendent of another + // consistent with querying client directly after importing the block. + let parent_hash = *block.header.parent_hash(); + let is_descendent_of = is_descendent_of(&self.inner, Some((&hash, &parent_hash))); + + let mut guard = InnerGuard { + guard: Some(self.authority_set.inner().write()), + old: None, + }; + + // whether to pause the old authority set -- happens after import + // of a forced change block. + let mut do_pause = false; + + // add any pending changes. + if let Some(change) = maybe_change { + let old = guard.as_mut().clone(); + guard.set_old(old); + + if let DelayKind::Best { .. } = change.delay_kind { + do_pause = true; + } + + guard.as_mut().add_pending_change( + change, + &is_descendent_of, + ).map_err(|e| ConsensusError::from(ConsensusErrorKind::ClientImport(e.to_string())))?; + } + + let applied_changes = { + let forced_change_set = guard.as_mut().apply_forced_changes(hash, number, &is_descendent_of) + .map_err(|e| ConsensusErrorKind::ClientImport(e.to_string())) + .map_err(ConsensusError::from)?; + + if let Some((median_last_finalized_number, new_set)) = forced_change_set { + let new_authorities = { + let (set_id, new_authorities) = new_set.current(); + + // we will use the median last finalized number as a hint + // for the canon block the new authority set should start + // with. we use the minimum between the median and the local + // best finalized block. + let best_finalized_number = self.inner.backend().blockchain().info() + .map_err(|e| ConsensusErrorKind::ClientImport(e.to_string()))? + .finalized_number; + + let canon_number = best_finalized_number.min(median_last_finalized_number); + + let canon_hash = + self.inner.backend().blockchain().header(BlockId::Number(canon_number)) + .map_err(|e| ConsensusErrorKind::ClientImport(e.to_string()))? + .expect("the given block number is less or equal than the current best finalized number; \ + current best finalized number must exist in chain; qed.") + .hash(); + + NewAuthoritySet { + canon_number, + canon_hash, + set_id, + authorities: new_authorities.to_vec(), + } + }; + let old = ::std::mem::replace(guard.as_mut(), new_set); + guard.set_old(old); + + AppliedChanges::Forced(new_authorities) + } else { + let did_standard = guard.as_mut().enacts_standard_change(hash, number, &is_descendent_of) + .map_err(|e| ConsensusErrorKind::ClientImport(e.to_string())) + .map_err(ConsensusError::from)?; + + if did_standard { + AppliedChanges::Standard + } else { + AppliedChanges::None + } + } + }; + + // consume the guard safely and write necessary changes. + let just_in_case = guard.consume(); + if let Some((_, ref authorities)) = just_in_case { + let authorities_change = match applied_changes { + AppliedChanges::Forced(ref new) => Some(new), + AppliedChanges::Standard => None, // the change isn't actually applied yet. + AppliedChanges::None => None, + }; + + crate::aux_schema::update_authority_set( + authorities, + authorities_change, + |insert| block.auxiliary.extend( + insert.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + ) + ); + } + + Ok(PendingSetChanges { just_in_case, applied_changes, do_pause }) + } +} + +impl, RA, PRA> BlockImport + for GrandpaBlockImport where + NumberFor: grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + DigestItemFor: DigestItem, + RA: Send + Sync, + PRA: ProvideRuntimeApi, + PRA::Api: GrandpaApi, +{ + type Error = ConsensusError; + + fn import_block(&self, mut block: ImportBlock, new_authorities: Option>) + -> Result + { + let hash = block.post_header().hash(); + let number = block.header.number().clone(); + + // early exit if block already in chain, otherwise the check for + // authority changes will error when trying to re-import a change block + match self.inner.backend().blockchain().status(BlockId::Hash(hash)) { + Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), + Ok(blockchain::BlockStatus::Unknown) => {}, + Err(e) => return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()), + } + + let pending_changes = self.make_authorities_changes(&mut block, hash)?; + + // we don't want to finalize on `inner.import_block` + let justification = block.justification.take(); + let enacts_consensus_change = new_authorities.is_some(); + let import_result = self.inner.import_block(block, new_authorities); + + let mut imported_aux = { + match import_result { + Ok(ImportResult::Imported(aux)) => aux, + Ok(r) => { + debug!(target: "afg", "Restoring old authority set after block import result: {:?}", r); + pending_changes.revert(); + return Ok(r); + }, + Err(e) => { + debug!(target: "afg", "Restoring old authority set after block import error: {:?}", e); + pending_changes.revert(); + return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()); + }, + } + }; + + let (applied_changes, do_pause) = pending_changes.defuse(); + + // Send the pause signal after import but BEFORE sending a `ChangeAuthorities` message. + if do_pause { + let _ = self.send_voter_commands.unbounded_send( + VoterCommand::Pause(format!("Forced change scheduled after inactivity")) + ); + } + + let needs_justification = applied_changes.needs_justification(); + if let AppliedChanges::Forced(new) = applied_changes { + // NOTE: when we do a force change we are "discrediting" the old set so we + // ignore any justifications from them. this block may contain a justification + // which should be checked and imported below against the new authority + // triggered by this forced change. the new grandpa voter will start at the + // last median finalized block (which is before the block that enacts the + // change), full nodes syncing the chain will not be able to successfully + // import justifications for those blocks since their local authority set view + // is still of the set before the forced change was enacted, still after #1867 + // they should import the block and discard the justification, and they will + // then request a justification from sync if it's necessary (which they should + // then be able to successfully validate). + let _ = self.send_voter_commands.unbounded_send(VoterCommand::ChangeAuthorities(new)); + + // we must clear all pending justifications requests, presumably they won't be + // finalized hence why this forced changes was triggered + imported_aux.clear_justification_requests = true; + } + + if !needs_justification && !enacts_consensus_change { + return Ok(ImportResult::Imported(imported_aux)); + } + + match justification { + Some(justification) => { + self.import_justification(hash, number, justification, needs_justification).unwrap_or_else(|err| { + debug!(target: "finality", "Imported block #{} that enacts authority set change with \ + invalid justification: {:?}, requesting justification from peers.", number, err); + imported_aux.bad_justification = true; + imported_aux.needs_justification = true; + }); + }, + None => { + if needs_justification { + trace!( + target: "finality", + "Imported unjustified block #{} that enacts authority set change, waiting for finality for enactment.", + number, + ); + } + + // we have imported block with consensus data changes, but without justification + // => remember to create justification when next block will be finalized + if enacts_consensus_change { + self.consensus_changes.lock().note_change((number, hash)); + } + imported_aux.needs_justification = true; + } + } + + Ok(ImportResult::Imported(imported_aux)) + } + + fn check_block( + &self, + hash: Block::Hash, + parent_hash: Block::Hash, + ) -> Result { + self.inner.check_block(hash, parent_hash) + } +} + +impl, RA, PRA> GrandpaBlockImport { + pub(crate) fn new( + inner: Arc>, + authority_set: SharedAuthoritySet>, + send_voter_commands: mpsc::UnboundedSender>>, + consensus_changes: SharedConsensusChanges>, + api: Arc, + ) -> GrandpaBlockImport { + GrandpaBlockImport { + inner, + authority_set, + send_voter_commands, + consensus_changes, + api, + } + } +} + +impl, RA, PRA> GrandpaBlockImport + where + NumberFor: grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, +{ + + /// Import a block justification and finalize the block. + /// + /// If `enacts_change` is set to true, then finalizing this block *must* + /// enact an authority set change, the function will panic otherwise. + fn import_justification( + &self, + hash: Block::Hash, + number: NumberFor, + justification: Justification, + enacts_change: bool, + ) -> Result<(), ConsensusError> { + let justification = GrandpaJustification::decode_and_verify( + justification, + self.authority_set.set_id(), + &self.authority_set.current_authorities(), + ); + + let justification = match justification { + Err(e) => return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()), + Ok(justification) => justification, + }; + + let result = finalize_block( + &*self.inner, + &self.authority_set, + &self.consensus_changes, + None, + hash, + number, + justification.into(), + ); + + match result { + Err(CommandOrError::VoterCommand(command)) => { + info!(target: "finality", "Imported justification for block #{} that triggers \ + command {}, signalling voter.", number, command); + + if let Err(e) = self.send_voter_commands.unbounded_send(command) { + return Err(ConsensusErrorKind::ClientImport(e.to_string()).into()); + } + }, + Err(CommandOrError::Error(e)) => { + return Err(match e { + Error::Grandpa(error) => ConsensusErrorKind::ClientImport(error.to_string()), + Error::Network(error) => ConsensusErrorKind::ClientImport(error), + Error::Blockchain(error) => ConsensusErrorKind::ClientImport(error), + Error::Client(error) => ConsensusErrorKind::ClientImport(error.to_string()), + Error::Safety(error) => ConsensusErrorKind::ClientImport(error), + Error::Timer(error) => ConsensusErrorKind::ClientImport(error.to_string()), + }.into()); + }, + Ok(_) => { + assert!(!enacts_change, "returns Ok when no authority set change should be enacted; qed;"); + }, + } + + Ok(()) + } +} diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs new file mode 100644 index 0000000000000000000000000000000000000000..d837e6a30862ea36a7fef9a91a986ed3c0a5c98d --- /dev/null +++ b/core/finality-grandpa/src/justification.rs @@ -0,0 +1,220 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::collections::{HashMap, HashSet}; + +use client::{CallExecutor, Client}; +use client::backend::Backend; +use client::blockchain::HeaderBackend; +use client::error::{Error as ClientError, ErrorKind as ClientErrorKind}; +use parity_codec::{Encode, Decode}; +use grandpa::VoterSet; +use grandpa::{Error as GrandpaError}; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; + +use crate::{Commit, Error}; +use crate::communication; + +use ed25519::Public as 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(Encode, Decode)] +pub(crate) struct GrandpaJustification { + round: u64, + pub(crate) commit: Commit, + votes_ancestries: Vec, +} + +impl> GrandpaJustification { + /// Create a GRANDPA justification from the given commit. This method + /// assumes the commit is valid and well-formed. + pub(crate) fn from_commit( + client: &Client, + round: u64, + commit: Commit, + ) -> Result, Error> where + B: Backend, + E: CallExecutor + Send + Sync, + RA: Send + Sync, + { + let mut votes_ancestries_hashes = HashSet::new(); + let mut votes_ancestries = Vec::new(); + + let error = || { + let msg = "invalid precommits for target commit".to_string(); + Err(Error::Client(ClientErrorKind::BadJustification(msg).into())) + }; + + for signed in commit.precommits.iter() { + let mut current_hash = signed.precommit.target_hash.clone(); + loop { + if current_hash == commit.target_hash { break; } + + match client.backend().blockchain().header(BlockId::Hash(current_hash))? { + Some(current_header) => { + if *current_header.number() <= commit.target_number { + return error(); + } + + let parent_hash = current_header.parent_hash().clone(); + if votes_ancestries_hashes.insert(current_hash) { + votes_ancestries.push(current_header); + } + current_hash = parent_hash; + }, + _ => return error(), + } + } + } + + Ok(GrandpaJustification { round, commit, votes_ancestries }) + } + + /// Decode a GRANDPA justification and validate the commit and the votes' + /// ancestry proofs. + pub(crate) fn decode_and_verify( + encoded: Vec, + set_id: u64, + voters: &VoterSet, + ) -> Result, ClientError> where + NumberFor: grandpa::BlockNumberOps, + { + GrandpaJustification::::decode(&mut &*encoded).ok_or_else(|| { + let msg = "failed to decode grandpa justification".to_string(); + ClientErrorKind::BadJustification(msg).into() + }).and_then(|just| just.verify(set_id, voters).map(|_| just)) + } + + /// Validate the commit and the votes' ancestry proofs. + pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> + where + NumberFor: grandpa::BlockNumberOps, + { + use grandpa::Chain; + + let ancestry_chain = AncestryChain::::new(&self.votes_ancestries); + + match grandpa::validate_commit( + &self.commit, + voters, + &ancestry_chain, + ) { + Ok(Some(_)) => {}, + _ => { + let msg = "invalid commit in grandpa justification".to_string(); + return Err(ClientErrorKind::BadJustification(msg).into()); + } + } + + let mut visited_hashes = HashSet::new(); + for signed in self.commit.precommits.iter() { + if let Err(_) = communication::check_message_sig::( + &grandpa::Message::Precommit(signed.precommit.clone()), + &signed.id, + &signed.signature, + self.round, + set_id, + ) { + return Err(ClientErrorKind::BadJustification( + "invalid signature for precommit in grandpa justification".to_string()).into()); + } + + if self.commit.target_hash == signed.precommit.target_hash { + continue; + } + + match ancestry_chain.ancestry(self.commit.target_hash, signed.precommit.target_hash) { + Ok(route) => { + // ancestry starts from parent hash but the precommit target hash has been visited + visited_hashes.insert(signed.precommit.target_hash); + for hash in route { + visited_hashes.insert(hash); + } + }, + _ => { + return Err(ClientErrorKind::BadJustification( + "invalid precommit ancestry proof in grandpa justification".to_string()).into()); + }, + } + } + + let ancestry_hashes = self.votes_ancestries + .iter() + .map(|h: &Block::Header| h.hash()) + .collect(); + + if visited_hashes != ancestry_hashes { + return Err(ClientErrorKind::BadJustification( + "invalid precommit ancestries in grandpa justification with unused headers".to_string()).into()); + } + + Ok(()) + } +} + +/// A utility trait implementing `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 grandpa::Chain> for AncestryChain where + NumberFor: grandpa::BlockNumberOps +{ + fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { + let mut route = Vec::new(); + let mut current_hash = block; + loop { + if current_hash == base { break; } + match self.ancestry.get(¤t_hash) { + Some(current_header) => { + current_hash = *current_header.parent_hash(); + route.push(current_hash); + }, + _ => return Err(GrandpaError::NotDescendent), + } + } + route.pop(); // remove the base + + Ok(route) + } + + fn best_chain_containing(&self, _block: Block::Hash) -> Option<(Block::Hash, NumberFor)> { + None + } +} diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index dfbea1fe8135a9a046882c8b4c610cd1ad681ea6..a62cceb6553625ffefd28023648ac2f823316ab3 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,6 +16,8 @@ //! Integration of the GRANDPA finality gadget into substrate. //! +//! This crate is unstable and the API and usage may change. +//! //! This crate provides a long-running future that produces finality notifications. //! //! # Usage @@ -43,78 +45,54 @@ //! logic is complex to compute because it requires looking arbitrarily far //! back in the chain. //! -//! Instead, we keep track of a list of all signals we've seen so far, -//! sorted ascending by the block number they would be applied at. We never vote -//! on chains with number higher than the earliest handoff block number -//! (this is num(signal) + N). When finalizing a block, we either apply or prune -//! any signaled changes based on whether the signaling block is included in the -//! newly-finalized chain. - -extern crate finality_grandpa as grandpa; -extern crate futures; -extern crate substrate_client as client; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_consensus_common as consensus_common; -extern crate substrate_network as network; -extern crate substrate_primitives; -extern crate tokio; -extern crate parking_lot; -extern crate parity_codec as codec; -extern crate substrate_finality_grandpa_primitives as fg_primitives; -extern crate rand; - -#[macro_use] -extern crate log; - -#[cfg(feature="service-integration")] -extern crate substrate_service as service; - -#[cfg(test)] -extern crate substrate_keyring as keyring; - -#[cfg(test)] -extern crate substrate_test_client as test_client; - -#[cfg(test)] -extern crate env_logger; - -#[macro_use] -extern crate parity_codec_derive; +//! Instead, we keep track of a list of all signals we've seen so far (across +//! all forks), sorted ascending by the block number they would be applied at. +//! We never vote on chains with number higher than the earliest handoff block +//! number (this is num(signal) + N). When finalizing a block, we either apply +//! or prune any signaled changes based on whether the signaling block is +//! included in the newly-finalized chain. use futures::prelude::*; -use futures::sync::mpsc; +use log::{debug, info, warn, trace}; +use futures::sync::{self, mpsc, oneshot}; use client::{ BlockchainEvents, CallExecutor, Client, backend::Backend, - error::Error as ClientError, error::ErrorKind as ClientErrorKind, + error::Error as ClientError, }; use client::blockchain::HeaderBackend; -use codec::{Encode, Decode}; -use consensus_common::{BlockImport, ImportBlock, ImportResult, Authorities}; +use parity_codec::{Encode, Decode}; use runtime_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, DigestFor, ProvideRuntimeApi, Hash as HashT, + DigestItemFor, DigestItem, }; use fg_primitives::GrandpaApi; +use inherents::InherentDataProviders; use runtime_primitives::generic::BlockId; -use substrate_primitives::{ed25519, H256, AuthorityId, Blake2Hasher}; -use tokio::timer::Delay; +use substrate_primitives::{ed25519, H256, Blake2Hasher, Pair}; +use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; + +use srml_finality_tracker; use grandpa::Error as GrandpaError; -use grandpa::{voter, round::State as RoundState, Equivocation, BlockNumberOps}; +use grandpa::{voter, round::State as RoundState, BlockNumberOps, VoterSet}; + +use network::Service as NetworkService; +use network::consensus_gossip as network_gossip; -use network::{Service as NetworkService, ExHashT}; -use network::consensus_gossip::{ConsensusMessage}; -use std::collections::{HashMap, HashSet}; use std::fmt; use std::sync::Arc; -use std::time::{Instant, Duration}; - -use authorities::SharedAuthoritySet; -use until_imported::{UntilCommitBlocksImported, UntilVoteTargetImported}; +use std::time::Duration; pub use fg_primitives::ScheduledChange; mod authorities; +mod aux_schema; mod communication; +mod consensus_changes; +mod environment; +mod finality_proof; +mod import; +mod justification; mod until_imported; #[cfg(feature="service-integration")] @@ -122,14 +100,19 @@ mod service_integration; #[cfg(feature="service-integration")] pub use service_integration::{LinkHalfForService, BlockImportForService}; +use aux_schema::{PersistentData, VoterSetState}; +use environment::Environment; +pub use finality_proof::{prove_finality, check_finality_proof}; +use import::GrandpaBlockImport; +use until_imported::UntilCommitBlocksImported; + +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; + #[cfg(test)] mod tests; -const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round"; -const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; - -/// round-number, round-state -type LastCompleted = (u64, RoundState); +const GRANDPA_ENGINE_ID: network::ConsensusEngineId = [b'a', b'f', b'g', b'1']; +const MESSAGE_ROUND_TOLERANCE: u64 = 2; /// A GRANDPA message for a substrate chain. pub type Message = grandpa::Message<::Hash, NumberFor>; @@ -137,9 +120,28 @@ pub type Message = grandpa::Message<::Hash, NumberFor = grandpa::SignedMessage< ::Hash, NumberFor, - ed25519::Signature, + AuthoritySignature, AuthorityId, >; + +/// Grandpa gossip message type. +/// This is the root type that gets encoded and sent on the network. +#[derive(Debug, Encode, Decode)] +pub enum GossipMessage { + /// Grandpa message with round and set info. + VoteOrPrecommit(VoteOrPrecommitMessage), + /// Grandpa commit message with round and set info. + Commit(FullCommitMessage), +} + +/// Network level message with topic information. +#[derive(Debug, Encode, Decode)] +pub struct VoteOrPrecommitMessage { + pub round: u64, + pub set_id: u64, + pub message: SignedMessage, +} + /// A prevote message for this chain's block type. pub type Prevote = grandpa::Prevote<::Hash, NumberFor>; /// A precommit message for this chain's block type. @@ -148,22 +150,34 @@ pub type Precommit = grandpa::Precommit<::Hash, NumberFo pub type Commit = grandpa::Commit< ::Hash, NumberFor, - ed25519::Signature, + AuthoritySignature, AuthorityId >; /// A compact commit message for this chain's block type. pub type CompactCommit = grandpa::CompactCommit< ::Hash, NumberFor, - ed25519::Signature, + AuthoritySignature, AuthorityId >; +/// Network level commit message with topic information. +#[derive(Debug, Encode, Decode)] +pub struct FullCommitMessage { + pub round: u64, + pub set_id: u64, + pub message: CompactCommit, +} + /// Configuration for the GRANDPA service. #[derive(Clone)] pub struct Config { /// The expected duration for a message to be gossiped across the network. pub gossip_duration: Duration, + /// Justification generation period (in blocks). GRANDPA will try to generate justifications + /// at least every justification_period blocks. There are some other events which might cause + /// justification generation. + pub justification_period: u64, /// The local signing key. pub local_key: Option>, /// Some local identifier of the voter. @@ -187,6 +201,8 @@ pub enum Error { Blockchain(String), /// Could not complete a round on disk. Client(ClientError), + /// An invariant has been violated (e.g. not finalizing pending change blocks in-order) + Safety(String), /// A timer failed to fire. Timer(::tokio::timer::Error), } @@ -203,11 +219,221 @@ impl From for Error { } } +/// A stream used by NetworkBridge in its implementation of Network. +pub struct NetworkStream { + inner: Option>>, + outer: oneshot::Receiver>> +} + +impl Stream for NetworkStream { + type Item = Vec; + type Error = (); + + fn poll(&mut self) -> Poll, Self::Error> { + if let Some(ref mut inner) = self.inner { + return inner.poll(); + } + match self.outer.poll() { + Ok(futures::Async::Ready(mut inner)) => { + let poll_result = inner.poll(); + self.inner = Some(inner); + poll_result + }, + Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady), + Err(_) => Err(()) + } + } +} + +struct TopicTracker { + min_live_round: u64, + max_round: u64, + set_id: u64, +} + +impl TopicTracker { + fn is_expired(&self, round: u64, set_id: u64) -> bool { + if set_id < self.set_id { + trace!(target: "afg", "Expired: Message with expired set_id {} (ours {})", set_id, self.set_id); + telemetry!(CONSENSUS_TRACE; "afg.expired_set_id"; + "set_id" => ?set_id, "ours" => ?self.set_id + ); + return true; + } else if set_id == self.set_id + 1 { + // allow a few first rounds of future set. + if round > MESSAGE_ROUND_TOLERANCE { + trace!(target: "afg", "Expired: Message too far in the future set, round {} (ours set_id {})", round, self.set_id); + telemetry!(CONSENSUS_TRACE; "afg.expired_msg_too_far_in_future_set"; + "round" => ?round, "ours" => ?self.set_id + ); + return true; + } + } else if set_id == self.set_id { + if round < self.min_live_round.saturating_sub(MESSAGE_ROUND_TOLERANCE) { + trace!(target: "afg", "Expired: Message round is out of bounds {} (ours {}-{})", round, self.min_live_round, self.max_round); + telemetry!(CONSENSUS_TRACE; "afg.msg_round_oob"; + "round" => ?round, "our_min_live_round" => ?self.min_live_round, "our_max_round" => ?self.max_round + ); + return true; + } + } else { + trace!(target: "afg", "Expired: Message in invalid future set {} (ours {})", set_id, self.set_id); + telemetry!(CONSENSUS_TRACE; "afg.expired_msg_in_invalid_future_set"; + "set_id" => ?set_id, "ours" => ?self.set_id + ); + return true; + } + false + } +} + +struct GossipValidator { + rounds: parking_lot::RwLock, + _marker: ::std::marker::PhantomData, +} + +impl GossipValidator { + fn new() -> GossipValidator { + GossipValidator { + rounds: parking_lot::RwLock::new(TopicTracker { + min_live_round: 0, + max_round: 0, + set_id: 0, + }), + _marker: Default::default(), + } + } + + fn note_round(&self, round: u64, set_id: u64) { + let mut rounds = self.rounds.write(); + if set_id > rounds.set_id { + rounds.set_id = set_id; + rounds.max_round = 0; + rounds.min_live_round = 0; + } + rounds.max_round = rounds.max_round.max(round); + } + + fn note_set(&self, _set_id: u64) { + } + + fn drop_round(&self, round: u64, set_id: u64) { + let mut rounds = self.rounds.write(); + if set_id == rounds.set_id && round >= rounds.min_live_round { + rounds.min_live_round = round + 1; + } + } + + fn drop_set(&self, _set_id: u64) { + } + + fn is_expired(&self, round: u64, set_id: u64) -> bool { + self.rounds.read().is_expired(round, set_id) + } + + fn validate_round_message(&self, full: VoteOrPrecommitMessage) + -> network_gossip::ValidationResult + { + if self.is_expired(full.round, full.set_id) { + return network_gossip::ValidationResult::Expired; + } + + if let Err(()) = communication::check_message_sig::( + &full.message.message, + &full.message.id, + &full.message.signature, + full.round, + full.set_id + ) { + debug!(target: "afg", "Bad message signature {}", full.message.id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + return network_gossip::ValidationResult::Invalid; + } + + let topic = message_topic::(full.round, full.set_id); + network_gossip::ValidationResult::Valid(topic) + } + + fn validate_commit_message(&self, full: FullCommitMessage) + -> network_gossip::ValidationResult + { + use grandpa::Message as GrandpaMessage; + if self.is_expired(full.round, full.set_id) { + return network_gossip::ValidationResult::Expired; + } + + if full.message.precommits.len() != full.message.auth_data.len() || full.message.precommits.is_empty() { + debug!(target: "afg", "Malformed compact commit"); + telemetry!(CONSENSUS_DEBUG; "afg.malformed_compact_commit"; + "precommits_len" => ?full.message.precommits.len(), + "auth_data_len" => ?full.message.auth_data.len(), + "precommits_is_empty" => ?full.message.precommits.is_empty(), + ); + return network_gossip::ValidationResult::Invalid; + } + + // check signatures on all contained precommits. + for (precommit, &(ref sig, ref id)) in full.message.precommits.iter().zip(&full.message.auth_data) { + if let Err(()) = communication::check_message_sig::( + &GrandpaMessage::Precommit(precommit.clone()), + id, + sig, + full.round, + full.set_id, + ) { + debug!(target: "afg", "Bad commit message signature {}", id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); + return network_gossip::ValidationResult::Invalid; + } + } + + let topic = commit_topic::(full.set_id); + + let precommits_signed_by: Vec = full.message.auth_data.iter().map(move |(_, a)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.received_commit_msg"; + "contains_precommits_signed_by" => ?precommits_signed_by, + "round" => ?full.round, + "set_id" => ?full.set_id, + "topic" => ?topic, + "block_hash" => ?full.message, + ); + network_gossip::ValidationResult::Valid(topic) + } +} + +impl network_gossip::Validator for GossipValidator { + fn validate(&self, mut data: &[u8]) -> network_gossip::ValidationResult { + match GossipMessage::::decode(&mut data) { + Some(GossipMessage::VoteOrPrecommit(message)) => self.validate_round_message(message), + Some(GossipMessage::Commit(message)) => self.validate_commit_message(message), + None => { + debug!(target: "afg", "Error decoding message"); + telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); + network_gossip::ValidationResult::Invalid + } + } + } + + fn message_expired<'a>(&'a self) -> Box bool + 'a> { + let rounds = self.rounds.read(); + Box::new(move |_topic, mut data| { + match GossipMessage::::decode(&mut data) { + None => true, + Some(GossipMessage::Commit(full)) => rounds.is_expired(full.round, full.set_id), + Some(GossipMessage::VoteOrPrecommit(full)) => + rounds.is_expired(full.round, full.set_id), + } + }) + } +} + /// A handle to the network. This is generally implemented by providing some /// handle to a gossip service or similar. /// /// Intended to be a lightweight handle such as an `Arc`. -pub trait Network: Clone { +pub trait Network: Clone { /// A stream of input messages for a topic. type In: Stream,Error=()>; @@ -219,32 +445,45 @@ pub trait Network: Clone { fn send_message(&self, round: u64, set_id: u64, message: Vec); /// Clean up messages for a round. - fn drop_messages(&self, round: u64, set_id: u64); + fn drop_round_messages(&self, round: u64, set_id: u64); + + /// Clean up messages for a given authority set id (e.g. commit messages). + fn drop_set_messages(&self, set_id: u64); /// Get a stream of commit messages for a specific set-id. This stream /// should never logically conclude. fn commit_messages(&self, set_id: u64) -> Self::In; /// Send message over the commit channel. - fn send_commit(&self, set_id: u64, message: Vec); + fn send_commit(&self, round: u64, set_id: u64, message: Vec); + + /// Inform peers that a block with given hash should be downloaded. + fn announce(&self, round: u64, set_id: u64, block: Block::Hash); } /// Bridge between NetworkService, gossiping consensus messages and Grandpa -pub struct NetworkBridge, H: ExHashT> { - service: Arc> +pub struct NetworkBridge> { + service: Arc>, + validator: Arc>, } -impl, H: ExHashT> NetworkBridge { +impl> NetworkBridge { /// Create a new NetworkBridge to the given NetworkService - pub fn new(service: Arc>) -> Self { - NetworkBridge { service } + pub fn new(service: Arc>) -> Self { + let validator = Arc::new(GossipValidator::new()); + let v = validator.clone(); + service.with_gossip(move |gossip, _| { + gossip.register_validator(GRANDPA_ENGINE_ID, v); + }); + NetworkBridge { service, validator: validator } } } -impl, H: ExHashT> Clone for NetworkBridge { +impl,> Clone for NetworkBridge { fn clone(&self) -> Self { NetworkBridge { - service: Arc::clone(&self.service) + service: Arc::clone(&self.service), + validator: Arc::clone(&self.validator), } } } @@ -257,29 +496,54 @@ fn commit_topic(set_id: u64) -> B::Hash { <::Hashing as HashT>::hash(format!("{}-COMMITS", set_id).as_bytes()) } -impl, H: ExHashT> Network for NetworkBridge { - type In = mpsc::UnboundedReceiver; +impl,> Network for NetworkBridge { + type In = NetworkStream; fn messages_for(&self, round: u64, set_id: u64) -> Self::In { - self.service.consensus_gossip().write().messages_for(message_topic::(round, set_id)) + self.validator.note_round(round, set_id); + let (tx, rx) = sync::oneshot::channel(); + self.service.with_gossip(move |gossip, _| { + let inner_rx = gossip.messages_for(GRANDPA_ENGINE_ID, message_topic::(round, set_id)); + let _ = tx.send(inner_rx); + }); + NetworkStream { outer: rx, inner: None } } fn send_message(&self, round: u64, set_id: u64, message: Vec) { let topic = message_topic::(round, set_id); - self.service.gossip_consensus_message(topic, message, false); + self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message); } - fn drop_messages(&self, round: u64, set_id: u64) { - let topic = message_topic::(round, set_id); - self.service.consensus_gossip().write().collect_garbage(|t| t == &topic); + fn drop_round_messages(&self, round: u64, set_id: u64) { + self.validator.drop_round(round, set_id); + self.service.with_gossip(move |gossip, _| gossip.collect_garbage()); + } + + fn drop_set_messages(&self, set_id: u64) { + self.validator.drop_set(set_id); + self.service.with_gossip(move |gossip, _| gossip.collect_garbage()); } fn commit_messages(&self, set_id: u64) -> Self::In { - self.service.consensus_gossip().write().messages_for(commit_topic::(set_id)) + self.validator.note_set(set_id); + let (tx, rx) = sync::oneshot::channel(); + self.service.with_gossip(move |gossip, _| { + let inner_rx = gossip.messages_for(GRANDPA_ENGINE_ID, commit_topic::(set_id)); + let _ = tx.send(inner_rx); + }); + NetworkStream { outer: rx, inner: None } } - fn send_commit(&self, set_id: u64, message: Vec) { + fn send_commit(&self, _round: u64, set_id: u64, message: Vec) { let topic = commit_topic::(set_id); - self.service.gossip_consensus_message(topic, message, true); + self.service.gossip_consensus_message(topic, GRANDPA_ENGINE_ID, message); + } + + fn announce(&self, round: u64, _set_id: u64, block: B::Hash) { + debug!(target: "afg", "Announcing block {} to peers which we voted on in round {}", block, round); + telemetry!(CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; + "block" => ?block, "round" => ?round + ); + self.service.announce_block(block) } } @@ -303,780 +567,81 @@ impl, RA> BlockStatus for Arc { - inner: Arc>, - voters: Arc>, - config: Config, - authority_set: SharedAuthoritySet>, - network: N, - set_id: u64, +/// A new authority set along with the canonical block it changed at. +#[derive(Debug)] +pub(crate) struct NewAuthoritySet { + pub(crate) canon_number: N, + pub(crate) canon_hash: H, + pub(crate) set_id: u64, + pub(crate) authorities: Vec<(AuthorityId, u64)>, } -impl, B, E, N, RA> grandpa::Chain> for Environment where - Block: 'static, - B: Backend + 'static, - E: CallExecutor + 'static, - N: Network + 'static, - N::In: 'static, - NumberFor: BlockNumberOps, -{ - fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { - if base == block { return Err(GrandpaError::NotDescendent) } - - let tree_route_res = ::client::blockchain::tree_route( - self.inner.backend().blockchain(), - BlockId::Hash(block), - BlockId::Hash(base), - ); - - let tree_route = match tree_route_res { - Ok(tree_route) => tree_route, - Err(e) => { - debug!(target: "afg", "Encountered error computing ancestry between block {:?} and base {:?}: {:?}", - block, base, e); - - return Err(GrandpaError::NotDescendent); - } - }; - - if tree_route.common_block().hash != base { - return Err(GrandpaError::NotDescendent); - } - - // skip one because our ancestry is meant to start from the parent of `block`, - // and `tree_route` includes it. - Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) - } - - fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, NumberFor)> { - // we refuse to vote beyond the current limit number where transitions are scheduled to - // occur. - // once blocks are finalized that make that transition irrelevant or activate it, - // we will proceed onwards. most of the time there will be no pending transition. - let limit = self.authority_set.current_limit(); - debug!(target: "afg", "Finding best chain containing block {:?} with number limit {:?}", block, limit); - - match self.inner.best_containing(block, limit) { - Ok(Some(hash)) => { - let header = self.inner.header(&BlockId::Hash(hash)).ok()? - .expect("Header known to exist after `best_containing` call; qed"); +/// Commands issued to the voter. +#[derive(Debug)] +pub(crate) enum VoterCommand { + /// Pause the voter for given reason. + Pause(String), + /// New authorities. + ChangeAuthorities(NewAuthoritySet) +} - Some((hash, header.number().clone())) - } - // Ok(None) can be returned when `block` is after `limit`. That might cause issues. - // might be better to return the header itself in this (rare) case. - Ok(None) => None, - Err(e) => { - debug!(target: "afg", "Encountered error finding best chain containing {:?}: {:?}", block, e); - None - } +impl fmt::Display for VoterCommand { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + VoterCommand::Pause(ref reason) => write!(f, "Pausing voter: {}", reason), + VoterCommand::ChangeAuthorities(_) => write!(f, "Changing authorities"), } } } -/// A new authority set along with the canonical block it changed at. -#[derive(Debug)] -struct NewAuthoritySet { - canon_number: N, - canon_hash: H, - set_id: u64, - authorities: Vec<(AuthorityId, u64)>, -} - /// Signals either an early exit of a voter or an error. #[derive(Debug)] -enum ExitOrError { +pub(crate) enum CommandOrError { /// An error occurred. Error(Error), - /// Early exit of the voter: the new set ID and the new authorities along with respective weights. - AuthoritiesChanged(NewAuthoritySet), + /// A command to the voter. + VoterCommand(VoterCommand), } -impl From for ExitOrError { +impl From for CommandOrError { fn from(e: Error) -> Self { - ExitOrError::Error(e) + CommandOrError::Error(e) } } -impl From for ExitOrError { +impl From for CommandOrError { fn from(e: ClientError) -> Self { - ExitOrError::Error(Error::Client(e)) + CommandOrError::Error(Error::Client(e)) } } -impl From for ExitOrError { +impl From for CommandOrError { fn from(e: grandpa::Error) -> Self { - ExitOrError::Error(Error::from(e)) + CommandOrError::Error(Error::from(e)) } } -impl ::std::error::Error for ExitOrError { } - -impl fmt::Display for ExitOrError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExitOrError::Error(ref e) => write!(f, "{:?}", e), - ExitOrError::AuthoritiesChanged(_) => write!(f, "restarting voter on new authorities"), - } - } -} - -impl, N, RA> voter::Environment> for Environment where - Block: 'static, - B: Backend + 'static, - E: CallExecutor + 'static + Send + Sync, - N: Network + 'static + Send, - N::In: 'static + Send, - RA: 'static + Send + Sync, - NumberFor: BlockNumberOps, -{ - type Timer = Box + Send>; - type Id = AuthorityId; - type Signature = ed25519::Signature; - - // regular round message streams - type In = Box, Self::Signature, Self::Id>, - Error = Self::Error, - > + Send>; - type Out = Box>, - SinkError = Self::Error, - > + Send>; - - type Error = ExitOrError>; - - fn round_data( - &self, - round: u64 - ) -> voter::RoundData { - let now = Instant::now(); - let prevote_timer = Delay::new(now + self.config.gossip_duration * 2); - let precommit_timer = Delay::new(now + self.config.gossip_duration * 4); - - // TODO: dispatch this with `mpsc::spawn`. - let incoming = ::communication::checked_message_stream::( - round, - self.set_id, - self.network.messages_for(round, self.set_id), - self.voters.clone(), - ); - - let (out_rx, outgoing) = ::communication::outgoing_messages::( - round, - self.set_id, - self.config.local_key.clone(), - self.voters.clone(), - self.network.clone(), - ); - - // schedule incoming messages from the network to be held until - // corresponding blocks are imported. - let incoming = UntilVoteTargetImported::new( - self.inner.import_notification_stream(), - self.inner.clone(), - incoming, - ); - - // join incoming network messages with locally originating ones. - let incoming = Box::new(out_rx.select(incoming).map_err(Into::into)); - - // schedule network message cleanup when sink drops. - let outgoing = Box::new(outgoing.sink_map_err(Into::into)); - - voter::RoundData { - prevote_timer: Box::new(prevote_timer.map_err(|e| Error::Timer(e).into())), - precommit_timer: Box::new(precommit_timer.map_err(|e| Error::Timer(e).into())), - incoming, - outgoing, - } - } - - fn completed(&self, round: u64, state: RoundState>) -> Result<(), Self::Error> { - debug!( - target: "afg", "Voter {} completed round {} in set {}. Estimate = {:?}, Finalized in round = {:?}", - self.config.name(), - round, - self.set_id, - state.estimate.as_ref().map(|e| e.1), - state.finalized.as_ref().map(|e| e.1), - ); - - let encoded_state = (round, state).encode(); - let res = Backend::insert_aux(&**self.inner.backend(), &[(LAST_COMPLETED_KEY, &encoded_state[..])], &[]); - if let Err(e) = res { - warn!(target: "afg", "Shutting down voter due to error bookkeeping last completed round in DB: {:?}", e); - Err(Error::Client(e).into()) - } else { - Ok(()) - } - } - - fn finalize_block(&self, hash: Block::Hash, number: NumberFor, round: u64, commit: Commit) -> Result<(), Self::Error> { - finalize_block(&*self.inner, &self.authority_set, hash, number, (round, commit).into()) - } - - fn round_commit_timer(&self) -> Self::Timer { - use rand::{thread_rng, Rng}; - - //random between 0-1 seconds. - let delay: u64 = thread_rng().gen_range(0, 1000); - Box::new(Delay::new( - Instant::now() + Duration::from_millis(delay) - ).map_err(|e| Error::Timer(e).into())) - } - - fn prevote_equivocation( - &self, - _round: u64, - equivocation: ::grandpa::Equivocation, Self::Signature> - ) { - warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); - // nothing yet; this could craft misbehavior reports of some kind. +impl From> for CommandOrError { + fn from(e: VoterCommand) -> Self { + CommandOrError::VoterCommand(e) } - - fn precommit_equivocation( - &self, - _round: u64, - equivocation: Equivocation, Self::Signature> - ) { - warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); - // nothing yet - } -} - -/// 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(Encode, Decode)] -struct GrandpaJustification { - round: u64, - commit: Commit, - votes_ancestries: Vec, } -impl> GrandpaJustification { - /// Create a GRANDPA justification from the given commit. This method - /// assumes the commit is valid and well-formed. - fn from_commit( - client: &Client, - round: u64, - commit: Commit, - ) -> Result, Error> where - B: Backend, - E: CallExecutor + Send + Sync, - RA: Send + Sync, - { - let mut votes_ancestries_hashes = HashSet::new(); - let mut votes_ancestries = Vec::new(); - - let error = || { - let msg = "invalid precommits for target commit".to_string(); - Err(Error::Client(ClientErrorKind::BadJustification(msg).into())) - }; +impl ::std::error::Error for CommandOrError { } - for signed in commit.precommits.iter() { - let mut current_hash = signed.precommit.target_hash.clone(); - loop { - if current_hash == commit.target_hash { break; } - - match client.backend().blockchain().header(BlockId::Hash(current_hash))? { - Some(current_header) => { - if *current_header.number() <= commit.target_number { - return error(); - } - - let parent_hash = current_header.parent_hash().clone(); - if votes_ancestries_hashes.insert(current_hash) { - votes_ancestries.push(current_header); - } - current_hash = parent_hash; - }, - _ => return error(), - } - } - } - - Ok(GrandpaJustification { round, commit, votes_ancestries }) - } - - /// Decode a GRANDPA justification and validate the commit and the votes' - /// ancestry proofs. - fn decode_and_verify( - encoded: Vec, - set_id: u64, - voters: &HashMap, - ) -> Result, ClientError> where - NumberFor: grandpa::BlockNumberOps, - { - use grandpa::Chain; - - let justification = match GrandpaJustification::decode(&mut &*encoded) { - Some(justification) => justification, - _ => { - let msg = "failed to decode grandpa justification".to_string(); - return Err(ClientErrorKind::BadJustification(msg).into()); - } - }; - - let ancestry_chain = AncestryChain::::new(&justification.votes_ancestries); - - match grandpa::validate_commit( - &justification.commit, - voters, - None, - &ancestry_chain, - ) { - Ok(Some(_)) => {}, - _ => { - let msg = "invalid commit in grandpa justification".to_string(); - return Err(ClientErrorKind::BadJustification(msg).into()); - } - } - - let mut visited_hashes = HashSet::new(); - for signed in justification.commit.precommits.iter() { - if let Err(_) = communication::check_message_sig::( - &grandpa::Message::Precommit(signed.precommit.clone()), - &signed.id, - &signed.signature, - justification.round, - set_id, - ) { - return Err(ClientErrorKind::BadJustification( - "invalid signature for precommit in grandpa justification".to_string()).into()); - } - - if justification.commit.target_hash == signed.precommit.target_hash { - continue; - } - - match ancestry_chain.ancestry(justification.commit.target_hash, signed.precommit.target_hash) { - Ok(route) => { - // ancestry starts from parent hash but the precommit target hash has been visited - visited_hashes.insert(signed.precommit.target_hash); - for hash in route { - visited_hashes.insert(hash); - } - }, - _ => { - return Err(ClientErrorKind::BadJustification( - "invalid precommit ancestry proof in grandpa justification".to_string()).into()); - }, - } - } - - let ancestry_hashes = justification.votes_ancestries - .iter() - .map(|h: &Block::Header| h.hash()) - .collect(); - - if visited_hashes != ancestry_hashes { - return Err(ClientErrorKind::BadJustification( - "invalid precommit ancestries in grandpa justification with unused headers".to_string()).into()); - } - - Ok(justification) - } -} - -enum JustificationOrCommit { - Justification(GrandpaJustification), - Commit((u64, Commit)), -} - -impl From<(u64, Commit)> for JustificationOrCommit { - fn from(commit: (u64, Commit)) -> JustificationOrCommit { - JustificationOrCommit::Commit(commit) - } -} - -impl From> for JustificationOrCommit { - fn from(justification: GrandpaJustification) -> JustificationOrCommit { - JustificationOrCommit::Justification(justification) - } -} - -/// Finalize the given block and apply any authority set changes. If an -/// authority set change is enacted then a justification is created (if not -/// given) and stored with the block when finalizing it. -fn finalize_block, E, RA>( - client: &Client, - authority_set: &SharedAuthoritySet>, - hash: Block::Hash, - number: NumberFor, - justification_or_commit: JustificationOrCommit, -) -> Result<(), ExitOrError>> where - B: Backend, - E: CallExecutor + Send + Sync, - RA: Send + Sync, -{ - // lock must be held through writing to DB to avoid race - let mut authority_set = authority_set.inner().write(); - let status = authority_set.apply_changes(number, |canon_number| { - canonical_at_height(client, (hash, number), canon_number) - })?; - - if status.changed { - // write new authority set state to disk. - let encoded_set = authority_set.encode(); - - let write_result = if let Some((ref canon_hash, ref canon_number)) = status.new_set_block { - // we also overwrite the "last completed round" entry with a blank slate - // because from the perspective of the finality gadget, the chain has - // reset. - let round_state = RoundState::genesis((*canon_hash, *canon_number)); - let last_completed: LastCompleted<_, _> = (0, round_state); - let encoded = last_completed.encode(); - - Backend::insert_aux( - &**client.backend(), - &[ - (AUTHORITY_SET_KEY, &encoded_set[..]), - (LAST_COMPLETED_KEY, &encoded[..]), - ], - &[] - ) - } else { - Backend::insert_aux(&**client.backend(), &[(AUTHORITY_SET_KEY, &encoded_set[..])], &[]) - }; - - if let Err(e) = write_result { - warn!(target: "finality", "Failed to write updated authority set to disk. Bailing."); - warn!(target: "finality", "Node is in a potentially inconsistent state."); - - return Err(e.into()); - } - } - - // NOTE: this code assumes that honest voters will never vote past a - // transition block, thus we don't have to worry about the case where - // we have a transition with `effective_block = N`, but we finalize - // `N+1`. this assumption is required to make sure we store - // justifications for transition blocks which will be requested by - // syncing clients. - let justification = match justification_or_commit { - JustificationOrCommit::Justification(justification) => Some(justification.encode()), - JustificationOrCommit::Commit((round_number, commit)) => - if status.new_set_block.is_some() { - let justification = GrandpaJustification::from_commit( - client, - round_number, - commit, - )?; - - Some(justification.encode()) - } else { - None - }, - }; - - debug!(target: "afg", "Finalizing blocks up to ({:?}, {})", number, hash); - - // ideally some handle to a synchronization oracle would be used - // to avoid unconditionally notifying. - client.finalize_block(BlockId::Hash(hash), justification, true).map_err(|e| { - warn!(target: "finality", "Error applying finality to block {:?}: {:?}", (hash, number), e); - warn!(target: "finality", "Node is in a potentially inconsistent state."); - e - })?; - - if let Some((canon_hash, canon_number)) = status.new_set_block { - // the authority set has changed. - let (new_id, set_ref) = authority_set.current(); - - if set_ref.len() > 16 { - info!("Applying GRANDPA set change to new set with {} authorities", set_ref.len()); - } else { - info!("Applying GRANDPA set change to new set {:?}", set_ref); - } - - Err(ExitOrError::AuthoritiesChanged(NewAuthoritySet { - canon_hash, - canon_number, - set_id: new_id, - authorities: set_ref.to_vec(), - })) - } else { - Ok(()) - } -} - -/// A block-import handler for GRANDPA. -/// -/// This scans each imported block for signals of changing authority set. -/// If the block being imported enacts an authority set change then: -/// - If the current authority set is still live: we import the block -/// - Otherwise, the block must include a valid justification. -/// -/// When using GRANDPA, the block import worker should be using this block import -/// object. -pub struct GrandpaBlockImport, RA, PRA> { - inner: Arc>, - authority_set: SharedAuthoritySet>, - authority_set_change: mpsc::UnboundedSender>>, - api: Arc, -} - -impl, RA, PRA> BlockImport - for GrandpaBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, -{ - type Error = ClientError; - - fn import_block(&self, mut block: ImportBlock, new_authorities: Option>) - -> Result - { - use authorities::PendingChange; - - let hash = block.post_header().hash(); - let number = block.header.number().clone(); - - let maybe_change = self.api.runtime_api().grandpa_pending_change( - &BlockId::hash(*block.header.parent_hash()), - &block.header.digest().clone(), - )?; - - // when we update the authorities, we need to hold the lock - // until the block is written to prevent a race if we need to restore - // the old authority set on error. - let just_in_case = if let Some(change) = maybe_change { - let parent_hash = *block.header.parent_hash(); - - let mut authorities = self.authority_set.inner().write(); - let old_set = authorities.clone(); - - let is_equal_or_descendent_of = |base: &Block::Hash| -> Result<(), ClientError> { - let error = || { - Err(ClientErrorKind::Backend( - "invalid authority set change: multiple pending changes on the same chain".to_string() - ).into()) - }; - - if *base == hash { return error(); } - if *base == parent_hash { return error(); } - - let tree_route = ::client::blockchain::tree_route( - self.inner.backend().blockchain(), - BlockId::Hash(parent_hash), - BlockId::Hash(*base), - )?; - - if tree_route.common_block().hash == *base { - return error(); - } - - Ok(()) - }; - - authorities.add_pending_change( - PendingChange { - next_authorities: change.next_authorities, - finalization_depth: change.delay, - canon_height: number, - canon_hash: hash, - }, - is_equal_or_descendent_of, - )?; - - block.auxiliary.push((AUTHORITY_SET_KEY.to_vec(), Some(authorities.encode()))); - Some((old_set, authorities)) - } else { - None - }; - - // we don't want to finalize on `inner.import_block` - let justification = block.justification.take(); - let import_result = self.inner.import_block(block, new_authorities).map_err(|e| { - if let Some((old_set, mut authorities)) = just_in_case { - debug!(target: "afg", "Restoring old set after block import error: {:?}", e); - *authorities = old_set; - } - e - })?; - - if import_result != ImportResult::Queued { - return Ok(import_result); - } - - let enacts_change = self.authority_set.inner().read().enacts_change(number, |canon_number| { - canonical_at_height(&self.inner, (hash, number), canon_number) - })?; - - if !enacts_change { - return Ok(import_result); - } - - match justification { - Some(justification) => { - let justification = GrandpaJustification::decode_and_verify( - justification, - self.authority_set.set_id(), - &self.authority_set.current_authorities(), - )?; - - let result = finalize_block( - &*self.inner, - &self.authority_set, - hash, - number, - justification.into(), - ); - - match result { - Ok(_) => { - unreachable!("returns Ok when no authority set change should be enacted; \ - verified previously that finalizing the current block enacts a change; \ - qed;"); - }, - Err(ExitOrError::AuthoritiesChanged(new)) => { - debug!(target: "finality", "Imported justified block #{} that enacts authority set change, signalling voter.", number); - if let Err(_) = self.authority_set_change.unbounded_send(new) { - return Err(ClientErrorKind::Backend( - "imported and finalized change block but grandpa voter is no longer running".to_string() - ).into()); - } - }, - Err(ExitOrError::Error(_)) => { - return Err(ClientErrorKind::Backend( - "imported change block but failed to finalize it, node may be in an inconsistent state".to_string() - ).into()); - }, - } - }, - None => { - trace!(target: "finality", "Imported unjustified block #{} that enacts authority set change, waiting for finality for enactment.", number); - } +impl fmt::Display for CommandOrError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + CommandOrError::Error(ref e) => write!(f, "{:?}", e), + CommandOrError::VoterCommand(ref cmd) => write!(f, "{}", cmd), } - - Ok(import_result) - } -} - -/// Using the given base get the block at the given height on this chain. The -/// target block must be an ancestor of base, therefore `height <= base.height`. -fn canonical_at_height, RA>( - client: &Client, - base: (Block::Hash, NumberFor), - height: NumberFor, -) -> Result, ClientError> where - B: Backend, - E: CallExecutor + Send + Sync, -{ - use runtime_primitives::traits::{One, Zero}; - - if height > base.1 { - return Ok(None); - } - - if height == base.1 { - return Ok(Some(base.0)); - } - - let mut current = match client.header(&BlockId::Hash(base.0))? { - Some(header) => header, - _ => return Ok(None), - }; - - let mut steps = base.1 - height; - - while steps > NumberFor::::zero() { - current = match client.header(&BlockId::Hash(*current.parent_hash()))? { - Some(header) => header, - _ => return Ok(None), - }; - - steps -= NumberFor::::one(); - } - - Ok(Some(current.hash())) -} - -impl, RA, PRA> Authorities for GrandpaBlockImport -where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, -{ - - type Error = as Authorities>::Error; - fn authorities(&self, at: &BlockId) -> Result, Self::Error> { - self.inner.authorities_at(at) - } -} - -impl, RA, PRA> ProvideRuntimeApi for GrandpaBlockImport -where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - PRA: ProvideRuntimeApi, -{ - type Api = PRA::Api; - - fn runtime_api<'a>(&'a self) -> ::runtime_primitives::traits::ApiRef<'a, Self::Api> { - self.api.runtime_api() } } -/// Half of a link between a block-import worker and a the background voter. -// This should remain non-clone. pub struct LinkHalf, RA> { client: Arc>, - authority_set: SharedAuthoritySet>, - authority_set_change: mpsc::UnboundedReceiver>>, -} - -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 grandpa::Chain> for AncestryChain where - NumberFor: grandpa::BlockNumberOps -{ - fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { - let mut route = Vec::new(); - let mut current_hash = block; - loop { - if current_hash == base { break; } - match self.ancestry.get(¤t_hash) { - Some(current_header) => { - current_hash = *current_header.parent_hash(); - route.push(current_hash); - }, - _ => return Err(GrandpaError::NotDescendent), - } - } - route.pop(); // remove the base - - Ok(route) - } - - fn best_chain_containing(&self, _block: Block::Hash) -> Option<(Block::Hash, NumberFor)> { - None - } + persistent_data: PersistentData>, + voter_commands_rx: mpsc::UnboundedReceiver>>, } /// Make block importer and link half necessary to tie the background voter @@ -1090,74 +655,70 @@ pub fn block_import, RA, PRA>( E: CallExecutor + 'static + Clone + Send + Sync, RA: Send + Sync, PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi + PRA::Api: GrandpaApi, { use runtime_primitives::traits::Zero; - let authority_set = match Backend::get_aux(&**client.backend(), AUTHORITY_SET_KEY)? { - None => { - info!(target: "afg", "Loading GRANDPA authorities \ - from genesis on what appears to be first startup."); - - // no authority set on disk: fetch authorities from genesis state. - // if genesis state is not available, we may be a light client, but these - // are unsupported for following GRANDPA directly. - let genesis_authorities = api.runtime_api() - .grandpa_authorities(&BlockId::number(Zero::zero()))?; - let authority_set = SharedAuthoritySet::genesis(genesis_authorities); - let encoded = authority_set.inner().read().encode(); - Backend::insert_aux(&**client.backend(), &[(AUTHORITY_SET_KEY, &encoded[..])], &[])?; + let chain_info = client.info()?; + let genesis_hash = chain_info.chain.genesis_hash; - authority_set + let persistent_data = aux_schema::load_persistent( + &**client.backend(), + genesis_hash, + >::zero(), + || { + let genesis_authorities = api.runtime_api() + .grandpa_authorities(&BlockId::number(Zero::zero()))?; + telemetry!(CONSENSUS_DEBUG; "afg.loading_authorities"; + "authorities_len" => ?genesis_authorities.len() + ); + Ok(genesis_authorities) } - Some(raw) => ::authorities::AuthoritySet::decode(&mut &raw[..]) - .ok_or_else(|| ::client::error::ErrorKind::Backend( - format!("GRANDPA authority set kept in invalid format") - ))? - .into(), - }; + )?; - let (authority_set_change_tx, authority_set_change_rx) = mpsc::unbounded(); + let (voter_commands_tx, voter_commands_rx) = mpsc::unbounded(); Ok(( - GrandpaBlockImport { - inner: client.clone(), - authority_set: authority_set.clone(), - authority_set_change: authority_set_change_tx, - api - }, + GrandpaBlockImport::new( + client.clone(), + persistent_data.authority_set.clone(), + voter_commands_tx, + persistent_data.consensus_changes.clone(), + api, + ), LinkHalf { client, - authority_set, - authority_set_change: authority_set_change_rx, + persistent_data, + voter_commands_rx, }, )) } fn committer_communication, B, E, N, RA>( + local_key: Option>, set_id: u64, - voters: &Arc>, + voters: &Arc>, client: &Arc>, network: &N, ) -> ( impl Stream< - Item = (u64, ::grandpa::CompactCommit, ed25519::Signature, AuthorityId>), - Error = ExitOrError>, + Item = (u64, ::grandpa::CompactCommit, AuthoritySignature, AuthorityId>), + Error = CommandOrError>, >, impl Sink< - SinkItem = (u64, ::grandpa::Commit, ed25519::Signature, AuthorityId>), - SinkError = ExitOrError>, + SinkItem = (u64, ::grandpa::Commit, AuthoritySignature, AuthorityId>), + SinkError = CommandOrError>, >, ) where B: Backend, E: CallExecutor + Send + Sync, - N: Network, + N: Network, RA: Send + Sync, NumberFor: BlockNumberOps, + DigestItemFor: DigestItem, { // verification stream - let commit_in = ::communication::checked_commit_stream::( - set_id, + let commit_in = crate::communication::checked_commit_stream::( network.commit_messages(set_id), voters.clone(), ); @@ -1169,9 +730,14 @@ fn committer_communication, B, E, N, RA>( commit_in, ); - let commit_out = ::communication::CommitsOut::::new( + let is_voter = local_key + .map(|pair| voters.contains_key(&pair.public().into())) + .unwrap_or(false); + + let commit_out = crate::communication::CommitsOut::::new( network.clone(), set_id, + is_voter, ); let commit_in = commit_in.map_err(Into::into); @@ -1180,41 +746,68 @@ fn committer_communication, B, E, N, RA>( (commit_in, commit_out) } +/// Register the finality tracker inherent data provider (which is used by +/// GRANDPA), if not registered already. +fn register_finality_tracker_inherent_data_provider, RA>( + client: Arc>, + inherent_data_providers: &InherentDataProviders, +) -> Result<(), consensus_common::Error> where + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, +{ + if !inherent_data_providers.has_provider(&srml_finality_tracker::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(srml_finality_tracker::InherentDataProvider::new(move || { + match client.backend().blockchain().info() { + Err(e) => Err(std::borrow::Cow::Owned(e.to_string())), + Ok(info) => { + telemetry!(CONSENSUS_INFO; "afg.finalized"; + "finalized_number" => ?info.finalized_number, + "finalized_hash" => ?info.finalized_hash, + ); + Ok(info.finalized_number) + }, + } + })) + .map_err(|err| consensus_common::ErrorKind::InherentData(err.into()).into()) + } else { + Ok(()) + } +} + /// Run a GRANDPA voter as a task. Provide configuration and a link to a /// block import worker that has already been instantiated with `block_import`. pub fn run_grandpa, N, RA>( config: Config, link: LinkHalf, network: N, + inherent_data_providers: InherentDataProviders, + on_exit: impl Future + Send + 'static, ) -> ::client::error::Result + Send + 'static> where Block::Hash: Ord, B: Backend + 'static, E: CallExecutor + Send + Sync + 'static, - N: Network + Send + Sync + 'static, + N: Network + Send + Sync + 'static, N::In: Send + 'static, NumberFor: BlockNumberOps, DigestFor: Encode, + DigestItemFor: DigestItem, RA: Send + Sync + 'static, { use futures::future::{self, Loop as FutureLoop}; - use runtime_primitives::traits::Zero; let LinkHalf { client, - authority_set, - authority_set_change, + persistent_data, + voter_commands_rx, } = link; + // we shadow network with the wrapping/rebroadcasting network to avoid + // accidental reuse. + let (broadcast_worker, network) = communication::rebroadcasting_network(network); + let PersistentData { authority_set, set_state, consensus_changes } = persistent_data; - let chain_info = client.info()?; - let genesis_hash = chain_info.chain.genesis_hash; - - let (last_round_number, last_state) = match Backend::get_aux(&**client.backend(), LAST_COMPLETED_KEY)? { - None => (0, RoundState::genesis((genesis_hash, >::zero()))), - Some(raw) => LastCompleted::decode(&mut &raw[..]) - .ok_or_else(|| ::client::error::ErrorKind::Backend( - format!("Last GRANDPA round state kept in invalid format") - ))? - }; + register_finality_tracker_inherent_data_provider(client.clone(), &inherent_data_providers)?; let voters = authority_set.current_authorities(); @@ -1225,92 +818,153 @@ pub fn run_grandpa, N, RA>( network: network.clone(), set_id: authority_set.set_id(), authority_set: authority_set.clone(), + consensus_changes: consensus_changes.clone(), + last_completed: environment::LastCompletedRound::new(set_state.round()), }); - let initial_state = (initial_environment, last_round_number, last_state, authority_set_change.into_future()); + let initial_state = (initial_environment, set_state, voter_commands_rx.into_future()); let voter_work = future::loop_fn(initial_state, move |params| { - let (env, last_round_number, last_state, authority_set_change) = params; + let (env, set_state, voter_commands_rx) = params; debug!(target: "afg", "{}: Starting new voter with set ID {}", config.name(), env.set_id); + telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; + "name" => ?config.name(), "set_id" => ?env.set_id + ); - let chain_info = match client.info() { - Ok(i) => i, - Err(e) => return future::Either::B(future::err(Error::Client(e))), - }; + let mut maybe_voter = match set_state.clone() { + VoterSetState::Live(last_round_number, last_round_state) => { + let chain_info = match client.info() { + Ok(i) => i, + Err(e) => return future::Either::B(future::err(Error::Client(e))), + }; - let last_finalized = ( - chain_info.chain.finalized_hash, - chain_info.chain.finalized_number, - ); + let last_finalized = ( + chain_info.chain.finalized_hash, + chain_info.chain.finalized_number, + ); - let committer_data = committer_communication( - env.set_id, - &env.voters, - &client, - &network, - ); + let committer_data = committer_communication( + config.local_key.clone(), + env.set_id, + &env.voters, + &client, + &network, + ); - let voters = (*env.voters).clone(); + let voters = (*env.voters).clone(); + + Some(voter::Voter::new( + env.clone(), + voters, + committer_data, + last_round_number, + last_round_state, + last_finalized, + )) + } + VoterSetState::Paused(_, _) => None, + }; + + // needs to be combined with another future otherwise it can deadlock. + let poll_voter = future::poll_fn(move || match maybe_voter { + Some(ref mut voter) => voter.poll(), + None => Ok(Async::NotReady), + }); - let voter = voter::Voter::new( - env, - voters, - committer_data, - last_round_number, - last_state, - last_finalized, - ); let client = client.clone(); let config = config.clone(); let network = network.clone(); let authority_set = authority_set.clone(); + let consensus_changes = consensus_changes.clone(); + + let handle_voter_command = move |command: VoterCommand<_, _>, voter_commands_rx| { + match command { + VoterCommand::ChangeAuthorities(new) => { + let voters: Vec = new.authorities.iter().map(move |(a, _)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; + "number" => ?new.canon_number, + "hash" => ?new.canon_hash, + "voters" => ?voters, + "set_id" => ?new.set_id, + ); + + // start the new authority set using the block where the + // set changed (not where the signal happened!) as the base. + let genesis_state = RoundState::genesis((new.canon_hash, new.canon_number)); + let env = Arc::new(Environment { + inner: client, + config, + voters: Arc::new(new.authorities.into_iter().collect()), + set_id: new.set_id, + network, + authority_set, + consensus_changes, + last_completed: environment::LastCompletedRound::new( + (0, genesis_state.clone()) + ), + }); + + + let set_state = VoterSetState::Live( + 0, // always start at round 0 when changing sets. + genesis_state, + ); + + Ok(FutureLoop::Continue((env, set_state, voter_commands_rx))) + } + VoterCommand::Pause(reason) => { + info!(target: "afg", "Pausing old validator set: {}", reason); + + // not racing because old voter is shut down. + let (last_round_number, last_round_state) = env.last_completed.read(); + let set_state = VoterSetState::Paused( + last_round_number, + last_round_state, + ); - let trigger_authority_set_change = |new: NewAuthoritySet<_, _>, authority_set_change| { - let env = Arc::new(Environment { - inner: client, - config, - voters: Arc::new(new.authorities.into_iter().collect()), - set_id: new.set_id, - network, - authority_set, - }); - - // start the new authority set using the block where the - // set changed (not where the signal happened!) as the base. - Ok(FutureLoop::Continue(( - env, - 0, // always start at round 0 when changing sets. - RoundState::genesis((new.canon_hash, new.canon_number)), - authority_set_change, - ))) + aux_schema::write_voter_set_state(&**client.backend(), &set_state)?; + + Ok(FutureLoop::Continue((env, set_state, voter_commands_rx))) + }, + } }; - future::Either::A(voter.select2(authority_set_change).then(move |res| match res { + future::Either::A(poll_voter.select2(voter_commands_rx).then(move |res| match res { Ok(future::Either::A(((), _))) => { // voters don't conclude naturally; this could reasonably be an error. Ok(FutureLoop::Break(())) }, Err(future::Either::B(_)) => { - // the `authority_set_change` stream should not fail. + // the `voter_commands_rx` stream should not fail. Ok(FutureLoop::Break(())) }, Ok(future::Either::B(((None, _), _))) => { - // the `authority_set_change` stream should never conclude since it's never closed. + // the `voter_commands_rx` stream should never conclude since it's never closed. Ok(FutureLoop::Break(())) }, - Err(future::Either::A((ExitOrError::Error(e), _))) => { + Err(future::Either::A((CommandOrError::Error(e), _))) => { // return inner voter error Err(e) } - Ok(future::Either::B(((Some(new), authority_set_change), _))) => { - // authority set change triggered externally through the channel - trigger_authority_set_change(new, authority_set_change.into_future()) + Ok(future::Either::B(((Some(command), voter_commands_rx), _))) => { + // some command issued externally. + handle_voter_command(command, voter_commands_rx.into_future()) } - Err(future::Either::A((ExitOrError::AuthoritiesChanged(new), authority_set_change))) => { - // authority set change triggered internally by finalizing a change block - trigger_authority_set_change(new, authority_set_change) + Err(future::Either::A((CommandOrError::VoterCommand(command), voter_commands_rx))) => { + // some command issued internally. + handle_voter_command(command, voter_commands_rx) }, })) - }).map_err(|e| warn!("GRANDPA Voter failed: {:?}", e)); + }); + + let voter_work = voter_work + .join(broadcast_worker) + .map(|((), ())| ()) + .map_err(|e| { + warn!("GRANDPA Voter failed: {:?}", e); + telemetry!(CONSENSUS_WARN; "afg.voter_failed"; "e" => ?e); + }); - Ok(voter_work) + Ok(voter_work.select(on_exit).then(|_| Ok(()))) } diff --git a/core/finality-grandpa/src/service_integration.rs b/core/finality-grandpa/src/service_integration.rs index c4f5398312663c1f114bbc5e14814d388b212291..3eee1dd9408d490f7275532fff3a8ea27ac7b73d 100644 --- a/core/finality-grandpa/src/service_integration.rs +++ b/core/finality-grandpa/src/service_integration.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ use client; use service::{FullBackend, FullExecutor, ServiceFactory}; -pub type BlockImportForService = ::GrandpaBlockImport< +pub type BlockImportForService = crate::GrandpaBlockImport< FullBackend, FullExecutor, ::Block, @@ -32,9 +32,9 @@ pub type BlockImportForService = ::GrandpaBlockImport< >, >; -pub type LinkHalfForService = ::LinkHalf< +pub type LinkHalfForService = crate::LinkHalf< FullBackend, FullExecutor, ::Block, ::RuntimeApi ->; \ No newline at end of file +>; diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index d01a48d62f3b749f4e54172c0a81344723de53be..a6a9f32a9d4994f751b3f3e07703eac0c12e5180 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,24 +17,29 @@ //! Tests and test helpers for GRANDPA. use super::*; -use network::test::{Block, Hash, TestNetFactory, Peer, PeersClient}; -use network::import_queue::{PassThroughVerifier}; +use network::test::{Block, DummySpecialization, Hash, TestNetFactory, Peer, PeersClient}; +use network::test::{PassThroughVerifier}; use network::config::{ProtocolConfig, Roles}; use parking_lot::Mutex; use tokio::runtime::current_thread; -use keyring::Keyring; +use keyring::AuthorityKeyring; use client::{ BlockchainEvents, error::Result, - runtime_api::{Core, RuntimeVersion, ApiExt, ConstructRuntimeApi, CallRuntimeAt}, + blockchain::Backend as BlockchainBackend, + runtime_api::{Core, RuntimeVersion, ApiExt}, }; use test_client::{self, runtime::BlockNumber}; -use codec::Decode; -use consensus_common::BlockOrigin; -use std::{collections::HashSet, result}; -use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, RuntimeApiInfo}; +use consensus_common::{BlockOrigin, ForkChoiceStrategy, ImportedAux, ImportBlock, ImportResult}; +use consensus_common::import_queue::{SharedBlockImport, SharedJustificationImport}; +use std::collections::{HashMap, HashSet}; +use std::result; +use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi}; use runtime_primitives::generic::BlockId; +use runtime_primitives::ExecutionContext; +use substrate_primitives::NativeOrEncoded; use authorities::AuthoritySet; +use consensus_changes::ConsensusChanges; type PeerData = Mutex< @@ -47,12 +52,12 @@ type PeerData = > > >; -type GrandpaPeer = Peer; +type GrandpaPeer = Peer; struct GrandpaTestNet { peers: Vec>, test_config: TestApi, - started: bool + started: bool, } impl GrandpaTestNet { @@ -63,16 +68,15 @@ impl GrandpaTestNet { test_config, }; let config = Self::default_config(); - for _ in 0..n_peers { net.add_peer(&config); } - net } } impl TestNetFactory for GrandpaTestNet { + type Specialization = DummySpecialization; type Verifier = PassThroughVerifier; type PeerData = PeerData; @@ -81,7 +85,7 @@ impl TestNetFactory for GrandpaTestNet { GrandpaTestNet { peers: Vec::new(), test_config: Default::default(), - started: false + started: false, } } @@ -99,13 +103,14 @@ impl TestNetFactory for GrandpaTestNet { } fn make_block_import(&self, client: Arc) - -> (Arc + Send + Sync>, PeerData) + -> (SharedBlockImport, Option>, PeerData) { let (import, link) = block_import( client, Arc::new(self.test_config.clone()) ).expect("Could not create block import for fresh peer."); - (Arc::new(import), Mutex::new(Some(link))) + let shared_import = Arc::new(import); + (shared_import.clone(), Some(shared_import), Mutex::new(Some(link))) } fn peer(&self, i: usize) -> &GrandpaPeer { @@ -116,7 +121,7 @@ impl TestNetFactory for GrandpaTestNet { &self.peers } - fn mut_peers>)>(&mut self, closure: F) { + fn mut_peers>)>(&mut self, closure: F) { closure(&mut self.peers); } @@ -133,55 +138,53 @@ impl TestNetFactory for GrandpaTestNet { struct MessageRouting { inner: Arc>, peer_id: usize, + validator: Arc>, } impl MessageRouting { fn new(inner: Arc>, peer_id: usize,) -> Self { + let validator = Arc::new(GossipValidator::new()); + let v = validator.clone(); + { + let inner = inner.lock(); + let peer = inner.peer(peer_id); + peer.with_gossip(move |gossip, _| { + gossip.register_validator(GRANDPA_ENGINE_ID, v); + }); + } MessageRouting { inner, peer_id, + validator, } } + + fn drop_messages(&self, topic: Hash) { + let inner = self.inner.lock(); + let peer = inner.peer(self.peer_id); + peer.consensus_gossip_collect_garbage_for_topic(topic); + } } fn make_topic(round: u64, set_id: u64) -> Hash { - let mut hash = Hash::default(); - round.using_encoded(|s| { - let raw = hash.as_mut(); - raw[..8].copy_from_slice(s); - }); - set_id.using_encoded(|s| { - let raw = hash.as_mut(); - raw[8..16].copy_from_slice(s); - }); - hash + message_topic::(round, set_id) } fn make_commit_topic(set_id: u64) -> Hash { - let mut hash = Hash::default(); - - { - let raw = hash.as_mut(); - raw[16..22].copy_from_slice(b"commit"); - } - set_id.using_encoded(|s| { - let raw = hash.as_mut(); - raw[24..].copy_from_slice(s); - }); - - hash + commit_topic::(set_id) } -impl Network for MessageRouting { +impl Network for MessageRouting { type In = Box,Error=()> + Send>; fn messages_for(&self, round: u64, set_id: u64) -> Self::In { + self.validator.note_round(round, set_id); let inner = self.inner.lock(); let peer = inner.peer(self.peer_id); - let mut gossip = peer.consensus_gossip().write(); - let messages = peer.with_spec(move |_, _| { - gossip.messages_for(make_topic(round, set_id)) - }); + let messages = peer.consensus_gossip_messages_for( + GRANDPA_ENGINE_ID, + make_topic(round, set_id), + ); let messages = messages.map_err( move |_| panic!("Messages for round {} dropped too early", round) @@ -191,28 +194,30 @@ impl Network for MessageRouting { } fn send_message(&self, round: u64, set_id: u64, message: Vec) { - let mut inner = self.inner.lock(); - inner.peer(self.peer_id).gossip_message(make_topic(round, set_id), message, false); - inner.route_until_complete(); + let inner = self.inner.lock(); + inner.peer(self.peer_id).gossip_message(make_topic(round, set_id), GRANDPA_ENGINE_ID, message); } - fn drop_messages(&self, round: u64, set_id: u64) { + fn drop_round_messages(&self, round: u64, set_id: u64) { + self.validator.drop_round(round, set_id); let topic = make_topic(round, set_id); - let inner = self.inner.lock(); - let peer = inner.peer(self.peer_id); - let mut gossip = peer.consensus_gossip().write(); - peer.with_spec(move |_, _| { - gossip.collect_garbage(|t| t == &topic) - }); + self.drop_messages(topic); + } + + fn drop_set_messages(&self, set_id: u64) { + self.validator.drop_set(set_id); + let topic = make_commit_topic(set_id); + self.drop_messages(topic); } fn commit_messages(&self, set_id: u64) -> Self::In { + self.validator.note_set(set_id); let inner = self.inner.lock(); let peer = inner.peer(self.peer_id); - let mut gossip = peer.consensus_gossip().write(); - let messages = peer.with_spec(move |_, _| { - gossip.messages_for(make_commit_topic(set_id)) - }); + let messages = peer.consensus_gossip_messages_for( + GRANDPA_ENGINE_ID, + make_commit_topic(set_id), + ); let messages = messages.map_err( move |_| panic!("Commit messages for set {} dropped too early", set_id) @@ -221,10 +226,13 @@ impl Network for MessageRouting { Box::new(messages) } - fn send_commit(&self, set_id: u64, message: Vec) { - let mut inner = self.inner.lock(); - inner.peer(self.peer_id).gossip_message(make_commit_topic(set_id), message, true); - inner.route_until_complete(); + fn send_commit(&self, _round: u64, set_id: u64, message: Vec) { + let inner = self.inner.lock(); + inner.peer(self.peer_id).gossip_message(make_commit_topic(set_id), GRANDPA_ENGINE_ID, message); + } + + fn announce(&self, _round: u64, _set_id: u64, _block: H256) { + } } @@ -232,6 +240,7 @@ impl Network for MessageRouting { struct TestApi { genesis_authorities: Vec<(AuthorityId, u64)>, scheduled_changes: Arc>>>, + forced_changes: Arc)>>>, } impl TestApi { @@ -239,6 +248,7 @@ impl TestApi { TestApi { genesis_authorities, scheduled_changes: Arc::new(Mutex::new(HashMap::new())), + forced_changes: Arc::new(Mutex::new(HashMap::new())), } } } @@ -256,23 +266,43 @@ impl ProvideRuntimeApi for TestApi { } impl Core for RuntimeApi { - fn version(&self, _: &BlockId) -> Result { + fn version_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result> { unimplemented!("Not required for testing!") } - fn authorities(&self, _: &BlockId) -> Result> { + fn authorities_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result>> { unimplemented!("Not required for testing!") } - fn execute_block(&self, _: &BlockId, _: &Block) -> Result<()> { + fn execute_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<(Block)>, + _: Vec, + ) -> Result> { unimplemented!("Not required for testing!") } - fn initialise_block( + fn initialise_block_runtime_api_impl( &self, _: &BlockId, - _: &::Header - ) -> Result<()> { + _: ExecutionContext, + _: Option<&::Header>, + _: Vec, + ) -> Result> { unimplemented!("Not required for testing!") } } @@ -285,32 +315,51 @@ impl ApiExt for RuntimeApi { unimplemented!("Not required for testing!") } - fn has_api(&self, _: &BlockId) -> Result { - unimplemented!("Not required for testing!") - } -} - -impl ConstructRuntimeApi for RuntimeApi { - fn construct_runtime_api<'a, T: CallRuntimeAt>(_: &'a T) -> ApiRef<'a, Self> { + fn runtime_version_at(&self, _: &BlockId) -> Result { unimplemented!("Not required for testing!") } } impl GrandpaApi for RuntimeApi { - fn grandpa_authorities( + fn grandpa_authorities_runtime_api_impl( &self, - at: &BlockId - ) -> Result> { + at: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result>> { if at == &BlockId::Number(0) { - Ok(self.inner.genesis_authorities.clone()) + Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) } else { panic!("should generally only request genesis authorities") } } - fn grandpa_pending_change(&self, at: &BlockId, _: &DigestFor) - -> Result>>> - { + fn grandpa_pending_change_runtime_api_impl( + &self, + at: &BlockId, + _: ExecutionContext, + _: Option<(&DigestFor)>, + _: Vec, + ) -> Result>>>> { + let parent_hash = match at { + &BlockId::Hash(at) => at, + _ => panic!("not requested by block hash!!"), + }; + + // we take only scheduled changes at given block number where there are no + // extrinsics. + Ok(self.inner.scheduled_changes.lock().get(&parent_hash).map(|c| c.clone())).map(NativeOrEncoded::Native) + } + + fn grandpa_forced_change_runtime_api_impl( + &self, + at: &BlockId, + _: ExecutionContext, + _: Option<(&DigestFor)>, + _: Vec, + ) + -> Result, ScheduledChange>)>>> { let parent_hash = match at { &BlockId::Hash(at) => at, _ => panic!("not requested by block hash!!"), @@ -318,42 +367,39 @@ impl GrandpaApi for RuntimeApi { // we take only scheduled changes at given block number where there are no // extrinsics. - Ok(self.inner.scheduled_changes.lock().get(&parent_hash).map(|c| c.clone())) + Ok(self.inner.forced_changes.lock().get(&parent_hash).map(|c| c.clone())).map(NativeOrEncoded::Native) } } const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); -fn make_ids(keys: &[Keyring]) -> Vec<(AuthorityId, u64)> { +fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(AuthorityId, u64)> { keys.iter() .map(|key| AuthorityId(key.to_raw_public())) .map(|id| (id, 1)) .collect() } -#[test] -fn finalize_3_voters_no_observers() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); - net.peer(0).push_blocks(20, false); - net.sync(); - - for i in 0..3 { - assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 20, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); +// run the voters to completion. provide a closure to be invoked after +// the voters are spawned but before blocking on them. +fn run_to_completion_with( + blocks: u64, + net: Arc>, + peers: &[AuthorityKeyring], + before_waiting: F, +) -> u64 { + use parking_lot::RwLock; let mut finality_notifications = Vec::new(); let mut runtime = current_thread::Runtime::new().unwrap(); + let highest_finalized = Arc::new(RwLock::new(0)); + for (peer_id, key) in peers.iter().enumerate() { + let highest_finalized = highest_finalized.clone(); let (client, link) = { - let mut net = net.lock(); + let net = net.lock(); // temporary needed for some reason let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); ( @@ -363,7 +409,13 @@ fn finalize_3_voters_no_observers() { }; finality_notifications.push( client.finality_notification_stream() - .take_while(|n| Ok(n.header.number() < &20)) + .take_while(move |n| { + let mut highest_finalized = highest_finalized.write(); + if *n.header.number() > *highest_finalized { + *highest_finalized = *n.header.number(); + } + Ok(n.header.number() < &blocks) + }) .for_each(|_| Ok(())) ); fn assert_send(_: &T) { } @@ -371,11 +423,14 @@ fn finalize_3_voters_no_observers() { let voter = run_grandpa( Config { gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, local_key: Some(Arc::new(key.clone().into())), name: Some(format!("peer#{}", peer_id)), }, link, MessageRouting::new(net.clone(), peer_id), + InherentDataProviders::new(), + futures::empty(), ).expect("all in order with client and network"); assert_send(&voter); @@ -389,16 +444,54 @@ fn finalize_3_voters_no_observers() { .map_err(|_| ()); let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL) - .for_each(move |_| { net.lock().route_until_complete(); Ok(()) }) + .for_each(move |_| { + net.lock().send_import_notifications(); + net.lock().send_finality_notifications(); + net.lock().route_fast(); + Ok(()) + }) .map(|_| ()) .map_err(|_| ()); + (before_waiting)(); + runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap(); + + let highest_finalized = *highest_finalized.read(); + + highest_finalized +} + +fn run_to_completion(blocks: u64, net: Arc>, peers: &[AuthorityKeyring]) -> u64 { + run_to_completion_with(blocks, net, peers, || {}) +} + +#[test] +fn finalize_3_voters_no_observers() { + let _ = env_logger::try_init(); + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); + net.peer(0).push_blocks(20, false); + net.sync(); + + for i in 0..3 { + assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 20, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(20, net.clone(), peers); + + // normally there's no justification for finalized blocks + assert!(net.lock().peer(0).client().backend().blockchain().justification(BlockId::Number(20)).unwrap().is_none(), + "Extra justification for block#1"); } #[test] fn finalize_3_voters_1_observer() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); @@ -416,7 +509,7 @@ fn finalize_3_voters_1_observer() { for (peer_id, local_key) in all_peers.enumerate() { let (client, link) = { - let mut net = net.lock(); + let net = net.lock(); let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); ( net.peers[peer_id].client().clone(), @@ -431,11 +524,14 @@ fn finalize_3_voters_1_observer() { let voter = run_grandpa( Config { gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, local_key, name: Some(format!("peer#{}", peer_id)), }, link, MessageRouting::new(net.clone(), peer_id), + InherentDataProviders::new(), + futures::empty(), ).expect("all in order with client and network"); runtime.spawn(voter); @@ -447,7 +543,7 @@ fn finalize_3_voters_1_observer() { .map_err(|_| ()); let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL) - .for_each(move |_| { net.lock().route_until_complete(); Ok(()) }) + .for_each(move |_| { net.lock().route_fast(); Ok(()) }) .map(|_| ()) .map_err(|_| ()); @@ -456,25 +552,26 @@ fn finalize_3_voters_1_observer() { #[test] fn transition_3_voters_twice_1_observer() { + let _ = env_logger::try_init(); let peers_a = &[ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, + AuthorityKeyring::Alice, + AuthorityKeyring::Bob, + AuthorityKeyring::Charlie, ]; let peers_b = &[ - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, + AuthorityKeyring::Dave, + AuthorityKeyring::Eve, + AuthorityKeyring::Ferdie, ]; let peers_c = &[ - Keyring::Alice, - Keyring::Eve, - Keyring::Two, + AuthorityKeyring::Alice, + AuthorityKeyring::Eve, + AuthorityKeyring::Two, ]; - let observer = &[Keyring::One]; + let observer = &[AuthorityKeyring::One]; let genesis_voters = make_ids(peers_a); @@ -482,20 +579,21 @@ fn transition_3_voters_twice_1_observer() { let transitions = api.scheduled_changes.clone(); let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8))); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); + let mut runtime = current_thread::Runtime::new().unwrap(); net.lock().peer(0).push_blocks(1, false); net.lock().sync(); for (i, peer) in net.lock().peers().iter().enumerate() { assert_eq!(peer.client().info().unwrap().chain.best_number, 1, - "Peer #{} failed to sync", i); + "Peer #{} failed to sync", i); - let set_raw = peer.client().backend().get_aux(::AUTHORITY_SET_KEY).unwrap().unwrap(); - let set = AuthoritySet::::decode(&mut &set_raw[..]).unwrap(); + let set: AuthoritySet = crate::aux_schema::load_authorities( + &**peer.client().backend() + ).unwrap(); assert_eq!(set.current(), (0, make_ids(peers_a).as_slice())); - assert_eq!(set.pending_changes().len(), 0); + assert_eq!(set.pending_changes().count(), 0); } { @@ -565,7 +663,7 @@ fn transition_3_voters_twice_1_observer() { for (peer_id, local_key) in all_peers { let (client, link) = { - let mut net = net.lock(); + let net = net.lock(); let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); ( net.peers[peer_id].client().clone(), @@ -577,21 +675,25 @@ fn transition_3_voters_twice_1_observer() { .take_while(|n| Ok(n.header.number() < &30)) .for_each(move |_| Ok(())) .map(move |()| { - let set_raw = client.backend().get_aux(::AUTHORITY_SET_KEY).unwrap().unwrap(); - let set = AuthoritySet::::decode(&mut &set_raw[..]).unwrap(); + let set: AuthoritySet = crate::aux_schema::load_authorities( + &**client.backend() + ).unwrap(); assert_eq!(set.current(), (2, make_ids(peers_c).as_slice())); - assert!(set.pending_changes().is_empty()); + assert_eq!(set.pending_changes().count(), 0); }) ); let voter = run_grandpa( Config { gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, local_key, name: Some(format!("peer#{}", peer_id)), }, link, MessageRouting::new(net.clone(), peer_id), + InherentDataProviders::new(), + futures::empty(), ).expect("all in order with client and network"); runtime.spawn(voter); @@ -605,7 +707,8 @@ fn transition_3_voters_twice_1_observer() { let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL) .for_each(move |_| { net.lock().send_import_notifications(); - net.lock().sync(); + net.lock().send_finality_notifications(); + net.lock().route_fast(); Ok(()) }) .map(|_| ()) @@ -613,3 +716,330 @@ fn transition_3_voters_twice_1_observer() { runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap(); } + +#[test] +fn justification_is_emitted_when_consensus_data_changes() { + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); + + // import block#1 WITH consensus data change + let new_authorities = vec![AuthorityId::from_raw([42; 32])]; + net.peer(0).push_authorities_change_block(new_authorities); + net.sync(); + let net = Arc::new(Mutex::new(net)); + run_to_completion(1, net.clone(), peers); + + // ... and check that there's no justification for block#1 + assert!(net.lock().peer(0).client().backend().blockchain().justification(BlockId::Number(1)).unwrap().is_some(), + "Missing justification for block#1"); +} + +#[test] +fn justification_is_generated_periodically() { + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); + net.peer(0).push_blocks(32, false); + net.sync(); + + let net = Arc::new(Mutex::new(net)); + run_to_completion(32, net.clone(), peers); + + // when block#32 (justification_period) is finalized, justification + // is required => generated + for i in 0..3 { + assert!(net.lock().peer(i).client().backend().blockchain() + .justification(BlockId::Number(32)).unwrap().is_some()); + } +} + +#[test] +fn consensus_changes_works() { + let mut changes = ConsensusChanges::::empty(); + + // pending changes are not finalized + changes.note_change((10, H256::from_low_u64_be(1))); + assert_eq!(changes.finalize((5, H256::from_low_u64_be(5)), |_| Ok(None)).unwrap(), (false, false)); + + // no change is selected from competing pending changes + changes.note_change((1, H256::from_low_u64_be(1))); + changes.note_change((1, H256::from_low_u64_be(101))); + assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1001)))).unwrap(), (true, false)); + + // change is selected from competing pending changes + changes.note_change((1, H256::from_low_u64_be(1))); + changes.note_change((1, H256::from_low_u64_be(101))); + assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1)))).unwrap(), (true, true)); +} + +#[test] +fn sync_justifications_on_change_blocks() { + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; + let voters = make_ids(peers_b); + + // 4 peers, 3 of them are authorities and participate in grandpa + let api = TestApi::new(voters); + let transitions = api.scheduled_changes.clone(); + let mut net = GrandpaTestNet::new(api, 4); + + // add 20 blocks + net.peer(0).push_blocks(20, false); + + // at block 21 we do add a transition which is instant + net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let block = builder.bake().unwrap(); + transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + block + }); + + // add more blocks on top of it (until we have 25) + net.peer(0).push_blocks(4, false); + net.sync(); + + for i in 0..4 { + assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 25, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(25, net.clone(), peers_a); + + // the first 3 peers are grandpa voters and therefore have already finalized + // block 21 and stored a justification + for i in 0..3 { + assert!(net.lock().peer(i).client().justification(&BlockId::Number(21)).unwrap().is_some()); + } + + // the last peer should get the justification by syncing from other peers + while net.lock().peer(3).client().justification(&BlockId::Number(21)).unwrap().is_none() { + net.lock().route_fast(); + } +} + +#[test] +fn finalizes_multiple_pending_changes_in_order() { + let _ = env_logger::try_init(); + + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie]; + let peers_c = &[AuthorityKeyring::Dave, AuthorityKeyring::Alice, AuthorityKeyring::Bob]; + + let all_peers = &[ + AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, + AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie, + ]; + let genesis_voters = make_ids(peers_a); + + // 6 peers, 3 of them are authorities and participate in grandpa from genesis + let api = TestApi::new(genesis_voters); + let transitions = api.scheduled_changes.clone(); + let mut net = GrandpaTestNet::new(api, 6); + + // add 20 blocks + net.peer(0).push_blocks(20, false); + + // at block 21 we do add a transition which is instant + net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let block = builder.bake().unwrap(); + transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + block + }); + + // add more blocks on top of it (until we have 25) + net.peer(0).push_blocks(4, false); + + // at block 26 we add another which is enacted at block 30 + net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let block = builder.bake().unwrap(); + transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_c), + delay: 4, + }); + block + }); + + // add more blocks on top of it (until we have 30) + net.peer(0).push_blocks(4, false); + + net.sync(); + + // all peers imported both change blocks + for i in 0..6 { + assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 30, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(30, net.clone(), all_peers); +} + +#[test] +fn doesnt_vote_on_the_tip_of_the_chain() { + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let mut net = GrandpaTestNet::new(api, 3); + + // add 100 blocks + net.peer(0).push_blocks(100, false); + net.sync(); + + for i in 0..3 { + assert_eq!(net.peer(i).client().info().unwrap().chain.best_number, 100, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + let highest = run_to_completion(75, net.clone(), peers_a); + + // the highest block to be finalized will be 3/4 deep in the unfinalized chain + assert_eq!(highest, 75); +} + +#[test] +fn force_change_to_new_set() { + // two of these guys are offline. + let genesis_authorities = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, AuthorityKeyring::One, AuthorityKeyring::Two]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let api = TestApi::new(make_ids(genesis_authorities)); + + let voters = make_ids(peers_a); + let normal_transitions = api.scheduled_changes.clone(); + let forced_transitions = api.forced_changes.clone(); + let net = GrandpaTestNet::new(api, 3); + let net = Arc::new(Mutex::new(net)); + + let runner_net = net.clone(); + let add_blocks = move || { + net.lock().peer(0).push_blocks(1, false); + + { + // add a forced transition at block 12. + let parent_hash = net.lock().peer(0).client().info().unwrap().chain.best_hash; + forced_transitions.lock().insert(parent_hash, (0, ScheduledChange { + next_authorities: voters.clone(), + delay: 10, + })); + + // add a normal transition too to ensure that forced changes take priority. + normal_transitions.lock().insert(parent_hash, ScheduledChange { + next_authorities: make_ids(genesis_authorities), + delay: 5, + }); + } + + net.lock().peer(0).push_blocks(25, false); + net.lock().sync(); + + for (i, peer) in net.lock().peers().iter().enumerate() { + assert_eq!(peer.client().info().unwrap().chain.best_number, 26, + "Peer #{} failed to sync", i); + + let set: AuthoritySet = crate::aux_schema::load_authorities( + &**peer.client().backend() + ).unwrap(); + + assert_eq!(set.current(), (1, voters.as_slice())); + assert_eq!(set.pending_changes().count(), 0); + } + }; + + // it will only finalize if the forced transition happens. + // we add_blocks after the voters are spawned because otherwise + // the link-halfs have the wrong AuthoritySet + run_to_completion_with(25, runner_net, peers_a, add_blocks); +} + +#[test] +fn allows_reimporting_change_blocks() { + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let net = GrandpaTestNet::new(api.clone(), 3); + + let client = net.peer(0).client().clone(); + let (block_import, ..) = net.make_block_import(client.clone()); + + let builder = client.new_block_at(&BlockId::Number(0)).unwrap(); + let block = builder.bake().unwrap(); + api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + + let block = || { + let block = block.clone(); + ImportBlock { + origin: BlockOrigin::File, + header: block.header, + justification: None, + post_digests: Vec::new(), + body: Some(block.extrinsics), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + } + }; + + assert_eq!( + block_import.import_block(block(), None).unwrap(), + ImportResult::Imported(ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: false }), + ); + + assert_eq!( + block_import.import_block(block(), None).unwrap(), + ImportResult::AlreadyInChain + ); +} + +#[test] +fn test_bad_justification() { + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let net = GrandpaTestNet::new(api.clone(), 3); + + let client = net.peer(0).client().clone(); + let (block_import, ..) = net.make_block_import(client.clone()); + + let builder = client.new_block_at(&BlockId::Number(0)).unwrap(); + let block = builder.bake().unwrap(); + api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + + let block = || { + let block = block.clone(); + ImportBlock { + origin: BlockOrigin::File, + header: block.header, + justification: Some(Vec::new()), + post_digests: Vec::new(), + body: Some(block.extrinsics), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + } + }; + + assert_eq!( + block_import.import_block(block(), None).unwrap(), + ImportResult::Imported(ImportedAux { needs_justification: true, clear_justification_requests: false, bad_justification: true }), + ); + + assert_eq!( + block_import.import_block(block(), None).unwrap(), + ImportResult::AlreadyInChain + ); +} diff --git a/core/finality-grandpa/src/until_imported.rs b/core/finality-grandpa/src/until_imported.rs index 028b710acb7e129a5fb6c071e06b1a0c3cc065db..4b867c18c8e2bea8f0ca2e02db34a2fd5eaf75a2 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/core/finality-grandpa/src/until_imported.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,18 +22,21 @@ use super::{BlockStatus, Error, SignedMessage, CompactCommit}; +use log::{debug, warn}; use client::ImportNotifications; use futures::prelude::*; use futures::stream::Fuse; use parking_lot::Mutex; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use substrate_primitives::AuthorityId; +use substrate_primitives::ed25519::Public as AuthorityId; use tokio::timer::Interval; use std::collections::{HashMap, VecDeque}; use std::sync::{atomic::{AtomicUsize, Ordering}, Arc}; use std::time::{Duration, Instant}; +const LOG_PENDING_INTERVAL: Duration = Duration::from_secs(15); + // something which will block until imported. pub(crate) trait BlockUntilImported: Sized { // the type that is blocked on. @@ -65,7 +68,7 @@ pub(crate) struct UntilImported, ready: VecDeque, check_pending: Interval, - pending: HashMap>, + pending: HashMap)>, } impl UntilImported @@ -112,14 +115,15 @@ impl Stream for UntilImported Async::Ready(Some(input)) => { // new input: schedule wait of any parts which require // blocks to be known. - let mut ready = &mut self.ready; - let mut pending = &mut self.pending; + let ready = &mut self.ready; + let pending = &mut self.pending; M::schedule_wait( input, &self.status_check, |target_hash, wait| pending .entry(target_hash) - .or_insert_with(Vec::new) + .or_insert_with(|| (Instant::now(), Vec::new())) + .1 .push(wait), |ready_item| ready.push_back(ready_item), )?; @@ -134,7 +138,7 @@ impl Stream for UntilImported Ok(Async::Ready(None)) => return Ok(Async::Ready(None)), Ok(Async::Ready(Some(notification))) => { // new block imported. queue up all messages tied to that hash. - if let Some(messages) = self.pending.remove(¬ification.hash) { + if let Some((_, messages)) = self.pending.remove(¬ification.hash) { let canon_number = notification.header.number().clone(); let ready_messages = messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -153,14 +157,27 @@ impl Stream for UntilImported if update_interval { let mut known_keys = Vec::new(); - for &block_hash in self.pending.keys() { + for (&block_hash, &mut (ref mut last_log, ref v)) in &mut self.pending { if let Some(number) = self.status_check.block_number(block_hash)? { known_keys.push((block_hash, number)); + } else { + let next_log = *last_log + LOG_PENDING_INTERVAL; + if Instant::now() <= next_log { + debug!( + target: "afg", + "Waiting to import block {} before {} votes can be imported. \ + Possible fork?", + block_hash, + v.len(), + ); + + *last_log = next_log; + } } } for (known_hash, canon_number) in known_keys { - if let Some(pending_messages) = self.pending.remove(&known_hash) { + if let Some((_, pending_messages)) = self.pending.remove(&known_hash) { let ready_messages = pending_messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -176,6 +193,7 @@ impl Stream for UntilImported if self.import_notifications.is_done() && self.inner.is_done() { Ok(Async::Ready(None)) } else { + Ok(Async::NotReady) } } @@ -283,7 +301,7 @@ impl BlockUntilImported for BlockCommitMessage { // check integrity: all precommits for same hash have same number. let canon_number = match checked_hashes.entry(target_hash) { Entry::Occupied(entry) => entry.get().number().clone(), - Entry::Vacant(mut entry) => { + Entry::Vacant(entry) => { if let Some(number) = status_check.block_number(target_hash)? { entry.insert(KnownOrUnknown::Known(number)); number diff --git a/core/inherents/Cargo.toml b/core/inherents/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..d3292095cc5f405a388ab1aab179cf8057030057 --- /dev/null +++ b/core/inherents/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "substrate-inherents" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +parking_lot = { version = "0.7", optional = true } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } + +[features] +default = [ "std" ] +std = [ + "parking_lot", + "rstd/std", + "parity-codec/std", + "runtime_primitives/std", +] diff --git a/core/inherents/src/lib.rs b/core/inherents/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..eadd45ba9e67b95d2d9220ea01f3c5462b994515 --- /dev/null +++ b/core/inherents/src/lib.rs @@ -0,0 +1,577 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides types and traits for creating and checking inherents. +//! +//! Each inherent is added to a produced block. Each runtime decides on which inherents its +//! want to attach to its blocks. All data that is required for the runtime to create the inherents +//! is stored in the `InherentData`. This `InherentData` is constructed by the node and given to +//! the runtime. +//! +//! Types that provide data for inherents, should implement `InherentDataProvider` and need to be +//! registered at `InherentDataProviders`. +//! +//! In the runtime, modules need to implement `ProvideInherent` when they can create and/or check +//! inherents. By implementing `ProvideInherent`, a module is not enforced to create an inherent. +//! A module can also just check given inherents. For using a module as inherent provider, it needs +//! to be registered by the `construct_runtime!` macro. The macro documentation gives more +//! information on how that is done. + +#![cfg_attr(not(feature = "std"), no_std)] + +use parity_codec as codec; +use codec::{Encode, Decode}; + +use rstd::{collections::btree_map::{BTreeMap, IntoIter, Entry}, vec::Vec}; + +#[cfg(feature = "std")] +use parking_lot::RwLock; + +#[cfg(feature = "std")] +use std::{sync::Arc, format}; + +pub use runtime_primitives::RuntimeString; + +/// An identifier for an inherent. +pub type InherentIdentifier = [u8; 8]; + +/// Inherent data to include in a block. +#[derive(Clone, Default)] +pub struct InherentData { + /// All inherent data encoded with parity-codec and an identifier. + data: BTreeMap> +} + +impl InherentData { + /// Create a new instance. + pub fn new() -> Self { + Self::default() + } + + /// Put data for an inherent into the internal storage. + /// + /// # Return + /// + /// Returns `Ok(())` if the data could be inserted an no data for an inherent with the same + /// identifier existed, otherwise an error is returned. + /// + /// Inherent identifiers need to be unique, otherwise decoding of these values will not work! + pub fn put_data( + &mut self, + identifier: InherentIdentifier, + inherent: &I, + ) -> Result<(), RuntimeString> { + match self.data.entry(identifier) { + Entry::Vacant(entry) => { + entry.insert(inherent.encode()); + Ok(()) + }, + Entry::Occupied(_) => { + Err("Inherent with same identifier already exists!".into()) + } + } + } + + /// Replace the data for an inherent. + /// + /// If it does not exist, the data is just inserted. + pub fn replace_data( + &mut self, + identifier: InherentIdentifier, + inherent: &I, + ) { + self.data.insert(identifier, inherent.encode()); + } + + /// Returns the data for the requested inherent. + /// + /// # Return + /// + /// - `Ok(Some(I))` if the data could be found and deserialized. + /// - `Ok(None)` if the data could not be found. + /// - `Err(_)` if the data could be found, but deserialization did not work. + pub fn get_data( + &self, + identifier: &InherentIdentifier, + ) -> Result, RuntimeString> { + match self.data.get(identifier) { + Some(inherent) => + I::decode(&mut &inherent[..]) + .ok_or_else(|| "Could not decode requested inherent type!".into()) + .map(Some), + None => Ok(None) + } + } +} + +impl codec::Encode for InherentData { + fn encode(&self) -> Vec { + let keys = self.data.keys().collect::>(); + let values = self.data.values().collect::>(); + + let mut encoded = keys.encode(); + encoded.extend(values.encode()); + encoded + } +} + +impl codec::Decode for InherentData { + fn decode(value: &mut I) -> Option { + Vec::::decode(value) + .and_then(|i| Vec::>::decode(value).map(|v| (i, v))) + .and_then(|(i, v)| { + if i.len() == v.len() { + Some(Self { + data: i.into_iter().zip(v.into_iter()).collect() + }) + } else { + None + } + }) + } +} + +/// The result of checking inherents. +/// +/// It either returns okay for all checks, stores all occurred errors or just one fatal error. +/// +/// When a fatal error occurres, all other errors are removed and the implementation needs to +/// abbort checking inherents. +#[derive(Encode, Decode, Clone)] +pub struct CheckInherentsResult { + /// Did the check succeed? + okay: bool, + /// Did we encounter a fatal error? + fatal_error: bool, + /// We use the `InherentData` to store our errors. + errors: InherentData, +} + +impl Default for CheckInherentsResult { + fn default() -> Self { + Self { + okay: true, + errors: InherentData::new(), + fatal_error: false, + } + } +} + +impl CheckInherentsResult { + /// Create a new instance. + pub fn new() -> Self { + Self::default() + } + + /// Put an error into the result. + /// + /// This makes this result resolve to `ok() == false`. + /// + /// # Parameters + /// + /// - identifier - The identifier of the inherent that generated the error. + /// - error - The error that will be encoded. + pub fn put_error( + &mut self, + identifier: InherentIdentifier, + error: &E, + ) -> Result<(), RuntimeString> { + // Don't accept any other error + if self.fatal_error { + return Err("No other errors are accepted after an hard error!".into()) + } + + if error.is_fatal_error() { + // remove the other errors. + self.errors.data.clear(); + } + + self.errors.put_data(identifier, error)?; + + self.okay = false; + self.fatal_error = error.is_fatal_error(); + Ok(()) + } + + /// Get an error out of the result. + /// + /// # Return + /// + /// - `Ok(Some(I))` if the error could be found and deserialized. + /// - `Ok(None)` if the error could not be found. + /// - `Err(_)` if the error could be found, but deserialization did not work. + pub fn get_error( + &self, + identifier: &InherentIdentifier, + ) -> Result, RuntimeString> { + self.errors.get_data(identifier) + } + + /// Convert into an iterator over all contained errors. + pub fn into_errors(self) -> IntoIter> { + self.errors.data.into_iter() + } + + /// Is this result ok? + pub fn ok(&self) -> bool { + self.okay + } + + /// Is this a fatal error? + pub fn fatal_error(&self) -> bool { + self.fatal_error + } +} + +#[cfg(feature = "std")] +impl PartialEq for CheckInherentsResult { + fn eq(&self, other: &Self) -> bool { + self.fatal_error == other.fatal_error && + self.okay == other.okay && + self.errors.data == other.errors.data + } +} + +/// All `InherentData` providers. +#[cfg(feature = "std")] +#[derive(Clone, Default)] +pub struct InherentDataProviders { + providers: Arc>>>, +} + +#[cfg(feature = "std")] +impl InherentDataProviders { + /// Create a new instance. + pub fn new() -> Self { + Self::default() + } + + /// Register an `InherentData` provider. + /// + /// The registration order is preserved and this order will also be used when creating the + /// inherent data. + /// + /// # Result + /// + /// Will return an error, if a provider with the same identifier already exists. + pub fn register_provider( + &self, + provider: P, + ) -> Result<(), RuntimeString> { + if self.has_provider(&provider.inherent_identifier()) { + Err( + format!( + "Inherent data provider with identifier {:?} already exists!", + &provider.inherent_identifier() + ).into() + ) + } else { + provider.on_register(self)?; + self.providers.write().push(Box::new(provider)); + Ok(()) + } + } + + /// Returns if a provider for the given identifier exists. + pub fn has_provider(&self, identifier: &InherentIdentifier) -> bool { + self.providers.read().iter().any(|p| p.inherent_identifier() == identifier) + } + + /// Create inherent data. + pub fn create_inherent_data(&self) -> Result { + let mut data = InherentData::new(); + self.providers.read().iter().try_for_each(|p| { + p.provide_inherent_data(&mut data) + .map_err(|e| format!("Error for `{:?}`: {:?}", p.inherent_identifier(), e)) + })?; + Ok(data) + } + + /// Converts a given encoded error into a `String`. + /// + /// Useful if the implementation encouters an error for an identifier it does not know. + pub fn error_to_string(&self, identifier: &InherentIdentifier, error: &[u8]) -> String { + let res = self.providers.read().iter().filter_map(|p| + if p.inherent_identifier() == identifier { + Some( + p.error_to_string(error) + .unwrap_or_else(|| error_to_string_fallback(identifier)) + ) + } else { + None + } + ).next(); + + match res { + Some(res) => res, + None => format!( + "Error while checking inherent of type \"{}\", but this inherent type is unknown.", + String::from_utf8_lossy(identifier) + ) + } + } +} + +/// Something that provides inherent data. +#[cfg(feature = "std")] +pub trait ProvideInherentData { + /// Is called when this inherent data provider is registered at the given + /// `InherentDataProviders`. + fn on_register(&self, _: &InherentDataProviders) -> Result<(), RuntimeString> { + Ok(()) + } + + /// The identifier of the inherent for that data will be provided. + fn inherent_identifier(&self) -> &'static InherentIdentifier; + + /// Provide inherent data that should be included in a block. + /// + /// The data should be stored in the given `InherentData` structure. + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString>; + + /// Convert the given encoded error to a string. + /// + /// If the given error could not be decoded, `None` should be returned. + fn error_to_string(&self, error: &[u8]) -> Option; +} + +/// A fallback function, if the decoding of an error fails. +#[cfg(feature = "std")] +fn error_to_string_fallback(identifier: &InherentIdentifier) -> String { + format!( + "Error while checking inherent of type \"{}\", but error could not be decoded.", + String::from_utf8_lossy(identifier) + ) +} + +/// Did we encounter a fatal error while checking an inherent? +/// +/// A fatal error is everything that fails while checking an inherent error, e.g. the inherent +/// was not found, could not be decoded etc. +/// Then there are cases where you not want the inherent check to fail, but report that there is an +/// action required. For example a timestamp of a block is in the future, the timestamp is still +/// correct, but it is required to verify the block at a later time again and then the inherent +/// check will succeed. +pub trait IsFatalError { + /// Is this a fatal error? + fn is_fatal_error(&self) -> bool; +} + +/// Auxiliary to make any given error resolve to `is_fatal_error() == true`. +#[derive(Encode)] +pub struct MakeFatalError(E); + +impl From for MakeFatalError { + fn from(err: E) -> Self { + MakeFatalError(err) + } +} + +impl IsFatalError for MakeFatalError { + fn is_fatal_error(&self) -> bool { + true + } +} + +/// A module that provides an inherent and may also verifies it. +pub trait ProvideInherent { + /// The call type of the module. + type Call; + /// The error returned by `check_inherent`. + type Error: codec::Encode + IsFatalError; + /// The inherent identifier used by this inherent. + const INHERENT_IDENTIFIER: self::InherentIdentifier; + + /// Create an inherent out of the given `InherentData`. + fn create_inherent(data: &InherentData) -> Option; + + /// Check the given inherent if it is valid. + /// Checking the inherent is optional and can be omitted. + fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Encode, Decode}; + + const TEST_INHERENT_0: InherentIdentifier = *b"testinh0"; + const TEST_INHERENT_1: InherentIdentifier = *b"testinh1"; + + #[derive(Encode)] + struct NoFatalError(E); + impl IsFatalError for NoFatalError { + fn is_fatal_error(&self) -> bool { + false + } + } + + #[test] + fn inherent_data_encodes_and_decodes() { + let inherent_0 = vec![1, 2, 3]; + let inherent_1: u32 = 7; + + let mut data = InherentData::new(); + data.put_data(TEST_INHERENT_0, &inherent_0).unwrap(); + data.put_data(TEST_INHERENT_1, &inherent_1).unwrap(); + + let encoded = data.encode(); + + let decoded = InherentData::decode(&mut &encoded[..]).unwrap(); + + assert_eq!(decoded.get_data::>(&TEST_INHERENT_0).unwrap().unwrap(), inherent_0); + assert_eq!(decoded.get_data::(&TEST_INHERENT_1).unwrap().unwrap(), inherent_1); + } + + #[test] + fn adding_same_inherent_returns_an_error() { + let mut data = InherentData::new(); + data.put_data(TEST_INHERENT_0, &8).unwrap(); + assert!(data.put_data(TEST_INHERENT_0, &10).is_err()); + } + + #[derive(Clone)] + struct TestInherentDataProvider { + registered: Arc>, + } + + impl TestInherentDataProvider { + fn new() -> Self { + let inst = Self { + registered: Default::default(), + }; + + // just make sure + assert!(!inst.is_registered()); + + inst + } + + fn is_registered(&self) -> bool { + *self.registered.read() + } + } + + const ERROR_TO_STRING: &str = "Found error!"; + + impl ProvideInherentData for TestInherentDataProvider { + fn on_register(&self, _: &InherentDataProviders) -> Result<(), RuntimeString> { + *self.registered.write() = true; + Ok(()) + } + + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &TEST_INHERENT_0 + } + + fn provide_inherent_data(&self, data: &mut InherentData) -> Result<(), RuntimeString> { + data.put_data(TEST_INHERENT_0, &42) + } + + fn error_to_string(&self, _: &[u8]) -> Option { + Some(ERROR_TO_STRING.into()) + } + } + + #[test] + fn registering_inherent_provider() { + let provider = TestInherentDataProvider::new(); + let providers = InherentDataProviders::new(); + + providers.register_provider(provider.clone()).unwrap(); + assert!(provider.is_registered()); + assert!(providers.has_provider(provider.inherent_identifier())); + + // Second time should fail + assert!(providers.register_provider(provider.clone()).is_err()); + } + + #[test] + fn create_inherent_data_from_all_providers() { + let provider = TestInherentDataProvider::new(); + let providers = InherentDataProviders::new(); + + providers.register_provider(provider.clone()).unwrap(); + assert!(provider.is_registered()); + + let inherent_data = providers.create_inherent_data().unwrap(); + + assert_eq!( + inherent_data.get_data::(provider.inherent_identifier()).unwrap().unwrap(), + 42u32 + ); + } + + #[test] + fn encoded_error_to_string() { + let provider = TestInherentDataProvider::new(); + let providers = InherentDataProviders::new(); + + providers.register_provider(provider.clone()).unwrap(); + assert!(provider.is_registered()); + + assert_eq!( + &providers.error_to_string(&TEST_INHERENT_0, &[1, 2]), ERROR_TO_STRING + ); + + assert!( + providers + .error_to_string(&TEST_INHERENT_1, &[1, 2]) + .contains("inherent type is unknown") + ); + } + + #[test] + fn check_inherents_result_encodes_and_decodes() { + let mut result = CheckInherentsResult::new(); + assert!(result.ok()); + + result.put_error(TEST_INHERENT_0, &NoFatalError(2u32)).unwrap(); + assert!(!result.ok()); + assert!(!result.fatal_error()); + + let encoded = result.encode(); + + let decoded = CheckInherentsResult::decode(&mut &encoded[..]).unwrap(); + + assert_eq!(decoded.get_error::(&TEST_INHERENT_0).unwrap().unwrap(), 2); + assert!(!decoded.ok()); + assert!(!decoded.fatal_error()); + } + + #[test] + fn check_inherents_result_removes_other_errors_on_fatal_error() { + let mut result = CheckInherentsResult::new(); + assert!(result.ok()); + + result.put_error(TEST_INHERENT_0, &NoFatalError(2u32)).unwrap(); + assert!(!result.ok()); + assert!(!result.fatal_error()); + + result.put_error(TEST_INHERENT_1, &MakeFatalError(4u32)).unwrap(); + assert!(!result.ok()); + assert!(result.fatal_error()); + + assert!(result.put_error(TEST_INHERENT_0, &NoFatalError(5u32)).is_err()); + + result.into_errors().for_each(|(i, e)| match i { + TEST_INHERENT_1 => assert_eq!(u32::decode(&mut &e[..]).unwrap(), 4), + _ => panic!("There should be no other error!"), + }); + } +} diff --git a/core/keyring/Cargo.toml b/core/keyring/Cargo.toml index 04d6c2bd134bfc73900e07a16bfe78b7533d2440..e3203742473e4a3c2cf66d8ccbcd00d88f00d1dc 100644 --- a/core/keyring/Cargo.toml +++ b/core/keyring/Cargo.toml @@ -2,6 +2,7 @@ name = "substrate-keyring" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] substrate-primitives = { path = "../primitives" } diff --git a/core/keyring/src/ed25519.rs b/core/keyring/src/ed25519.rs new file mode 100644 index 0000000000000000000000000000000000000000..1ac7de17c3d9182be547fd65f42d746d6f3ec87e --- /dev/null +++ b/core/keyring/src/ed25519.rs @@ -0,0 +1,178 @@ +// 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 . + +//! Support code for the runtime. A set of test accounts. + +use std::collections::HashMap; +use std::ops::Deref; +use lazy_static::lazy_static; +use substrate_primitives::{ed25519::{Pair, Public, Signature}, Pair as _Pair, H256}; +pub use substrate_primitives::ed25519; + +/// Set of test accounts. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, + One, + Two, +} + +impl Keyring { + pub fn from_public(who: &Public) -> Option { + [ + Keyring::Alice, + Keyring::Bob, + Keyring::Charlie, + Keyring::Dave, + Keyring::Eve, + Keyring::Ferdie, + Keyring::One, + Keyring::Two, + ].iter() + .map(|i| *i) + .find(|&k| &Public::from(k) == who) + } + + pub fn from_raw_public(who: [u8; 32]) -> Option { + Self::from_public(&Public::from_raw(who)) + } + + pub fn to_raw_public(self) -> [u8; 32] { + *Public::from(self).as_array_ref() + } + + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + + pub fn to_raw_public_vec(self) -> Vec { + Public::from(self).to_raw_vec() + } + + pub fn sign(self, msg: &[u8]) -> Signature { + Pair::from(self).sign(msg) + } + + pub fn pair(self) -> Pair { + Pair::from_string(&format!("//{}", <&'static str>::from(self)), None) + .expect("static values are known good; qed") + } +} + +impl From for &'static str { + fn from(k: Keyring) -> Self { + match k { + Keyring::Alice => "Alice", + Keyring::Bob => "Bob", + Keyring::Charlie => "Charlie", + Keyring::Dave => "Dave", + Keyring::Eve => "Eve", + Keyring::Ferdie => "Ferdie", + Keyring::One => "One", + Keyring::Two => "Two", + } + } +} + +lazy_static! { + static ref PRIVATE_KEYS: HashMap = { + [ + Keyring::Alice, + Keyring::Bob, + Keyring::Charlie, + Keyring::Dave, + Keyring::Eve, + Keyring::Ferdie, + Keyring::One, + Keyring::Two, + ].iter().map(|&i| (i, i.pair())).collect() + }; + + static ref PUBLIC_KEYS: HashMap = { + PRIVATE_KEYS.iter().map(|(&name, pair)| (name, pair.public())).collect() + }; +} + +impl From for Public { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().clone() + } +} + +impl From for Pair { + fn from(k: Keyring) -> Self { + k.pair() + } +} + +impl From for [u8; 32] { + fn from(k: Keyring) -> Self { + *(*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() + } +} + +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + +impl From for &'static [u8; 32] { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() + } +} + +impl AsRef<[u8; 32]> for Keyring { + fn as_ref(&self) -> &[u8; 32] { + (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() + } +} + +impl AsRef for Keyring { + fn as_ref(&self) -> &Public { + (*PUBLIC_KEYS).get(self).unwrap() + } +} + +impl Deref for Keyring { + type Target = [u8; 32]; + fn deref(&self) -> &[u8; 32] { + (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use substrate_primitives::{ed25519::Pair, Pair as _Pair}; + + #[test] + fn should_work() { + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); + } +} diff --git a/core/keyring/src/lib.rs b/core/keyring/src/lib.rs index d2970c54c6b24de9d426e35490418b053b1dcb5e..5cf38401d0823f84a80054e9ccb9eb2d9bb8eba0 100644 --- a/core/keyring/src/lib.rs +++ b/core/keyring/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,160 +16,21 @@ //! Support code for the runtime. A set of test accounts. -#[macro_use] extern crate hex_literal; -#[macro_use] extern crate lazy_static; -extern crate substrate_primitives; +/// Test account crypto for sr25519. +pub mod sr25519; -use std::collections::HashMap; -use std::ops::Deref; -use substrate_primitives::ed25519::{Pair, Public, Signature}; -pub use substrate_primitives::ed25519; +/// Test account crypto for ed25519. +pub mod ed25519; -/// Set of test accounts. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub enum Keyring { - Alice, - Bob, - Charlie, - Dave, - Eve, - Ferdie, - One, - Two, -} - -impl Keyring { - pub fn from_public(who: Public) -> Option { - [ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, - Keyring::One, - Keyring::Two, - ].iter() - .map(|i| *i) - .find(|&k| Public::from(k) == who) - } - - pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(Public::from_raw(who)) - } - - pub fn to_raw_public(self) -> [u8; 32] { - *Public::from(self).as_array_ref() - } - - pub fn to_raw_public_vec(self) -> Vec { - Public::from(self).to_raw_vec() - } - - pub fn sign(self, msg: &[u8]) -> Signature { - Pair::from(self).sign(msg) - } - - pub fn pair(self) -> Pair { - match self { - Keyring::Alice => Pair::from_seed(b"Alice "), - Keyring::Bob => Pair::from_seed(b"Bob "), - Keyring::Charlie => Pair::from_seed(b"Charlie "), - Keyring::Dave => Pair::from_seed(b"Dave "), - Keyring::Eve => Pair::from_seed(b"Eve "), - Keyring::Ferdie => Pair::from_seed(b"Ferdie "), - Keyring::One => Pair::from_seed(b"12345678901234567890123456789012"), - Keyring::Two => Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")), - } - } -} - -impl From for &'static str { - fn from(k: Keyring) -> Self { - match k { - Keyring::Alice => "Alice", - Keyring::Bob => "Bob", - Keyring::Charlie => "Charlie", - Keyring::Dave => "Dave", - Keyring::Eve => "Eve", - Keyring::Ferdie => "Ferdie", - Keyring::One => "one", - Keyring::Two => "two", - } - } -} - -lazy_static! { - static ref PRIVATE_KEYS: HashMap = { - [ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, - Keyring::One, - Keyring::Two, - ].iter().map(|&i| (i, i.pair())).collect() - }; - - static ref PUBLIC_KEYS: HashMap = { - PRIVATE_KEYS.iter().map(|(&name, pair)| (name, pair.public())).collect() - }; -} - -impl From for Public { - fn from(k: Keyring) -> Self { - (*PUBLIC_KEYS).get(&k).unwrap().clone() - } -} - -impl From for Pair { - fn from(k: Keyring) -> Self { - k.pair() - } -} - -impl From for [u8; 32] { - fn from(k: Keyring) -> Self { - *(*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() - } -} - -impl From for &'static [u8; 32] { - fn from(k: Keyring) -> Self { - (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() - } -} - -impl AsRef<[u8; 32]> for Keyring { - fn as_ref(&self) -> &[u8; 32] { - (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() - } -} - -impl AsRef for Keyring { - fn as_ref(&self) -> &Public { - (*PUBLIC_KEYS).get(self).unwrap() - } -} - -impl Deref for Keyring { - type Target = [u8; 32]; - fn deref(&self) -> &[u8; 32] { - (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() - } -} +/// Convenience export: Sr25519's Keyring is exposed as `AccountKeyring`, +/// since it tends to be used for accounts. +pub use sr25519::Keyring as AccountKeyring; -#[cfg(test)] -mod tests { - use super::*; - use ed25519::Verifiable; +/// Convenience export: Ed25519's Keyring is exposed as `AuthorityKeyring`, +/// since it tends to be used for authorities (session keys &c.). +pub use ed25519::Keyring as AuthorityKeyring; - #[test] - fn should_work() { - assert!(Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Bob!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Bob)); - } +pub mod test { + /// The keyring for use with accounts when using the test runtime. + pub use super::ed25519::Keyring as AccountKeyring; } diff --git a/core/keyring/src/sr25519.rs b/core/keyring/src/sr25519.rs new file mode 100644 index 0000000000000000000000000000000000000000..17404ad1c6ef02a0b903b11d7ed13c102a9e44f4 --- /dev/null +++ b/core/keyring/src/sr25519.rs @@ -0,0 +1,178 @@ +// 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 . + +//! Support code for the runtime. A set of test accounts. + +use std::collections::HashMap; +use std::ops::Deref; +use lazy_static::lazy_static; +use substrate_primitives::{sr25519::{Pair, Public, Signature}, Pair as _Pair, H256}; +pub use substrate_primitives::sr25519; + +/// Set of test accounts. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, + One, + Two, +} + +impl Keyring { + pub fn from_public(who: &Public) -> Option { + [ + Keyring::Alice, + Keyring::Bob, + Keyring::Charlie, + Keyring::Dave, + Keyring::Eve, + Keyring::Ferdie, + Keyring::One, + Keyring::Two, + ].iter() + .map(|i| *i) + .find(|&k| &Public::from(k) == who) + } + + pub fn from_raw_public(who: [u8; 32]) -> Option { + Self::from_public(&Public::from_raw(who)) + } + + pub fn to_raw_public(self) -> [u8; 32] { + *Public::from(self).as_array_ref() + } + + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + + pub fn to_raw_public_vec(self) -> Vec { + Public::from(self).to_raw_vec() + } + + pub fn sign(self, msg: &[u8]) -> Signature { + Pair::from(self).sign(msg) + } + + pub fn pair(self) -> Pair { + Pair::from_string(&format!("//{}", <&'static str>::from(self)), None) + .expect("static values are known good; qed") + } +} + +impl From for &'static str { + fn from(k: Keyring) -> Self { + match k { + Keyring::Alice => "Alice", + Keyring::Bob => "Bob", + Keyring::Charlie => "Charlie", + Keyring::Dave => "Dave", + Keyring::Eve => "Eve", + Keyring::Ferdie => "Ferdie", + Keyring::One => "One", + Keyring::Two => "Two", + } + } +} + +lazy_static! { + static ref PRIVATE_KEYS: HashMap = { + [ + Keyring::Alice, + Keyring::Bob, + Keyring::Charlie, + Keyring::Dave, + Keyring::Eve, + Keyring::Ferdie, + Keyring::One, + Keyring::Two, + ].iter().map(|&i| (i, i.pair())).collect() + }; + + static ref PUBLIC_KEYS: HashMap = { + PRIVATE_KEYS.iter().map(|(&name, pair)| (name, pair.public())).collect() + }; +} + +impl From for Public { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().clone() + } +} + +impl From for Pair { + fn from(k: Keyring) -> Self { + k.pair() + } +} + +impl From for [u8; 32] { + fn from(k: Keyring) -> Self { + *(*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() + } +} + +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + +impl From for &'static [u8; 32] { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() + } +} + +impl AsRef<[u8; 32]> for Keyring { + fn as_ref(&self) -> &[u8; 32] { + (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() + } +} + +impl AsRef for Keyring { + fn as_ref(&self) -> &Public { + (*PUBLIC_KEYS).get(self).unwrap() + } +} + +impl Deref for Keyring { + type Target = [u8; 32]; + fn deref(&self) -> &[u8; 32] { + (*PUBLIC_KEYS).get(self).unwrap().as_array_ref() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use substrate_primitives::{sr25519::Pair, Pair as _Pair}; + + #[test] + fn should_work() { + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); + } +} diff --git a/core/keystore/Cargo.toml b/core/keystore/Cargo.toml index 760e064158ac200b259b96556aa768c599130f15..9a028d21d975ca37386483f2f2b7ee7654017d28 100644 --- a/core/keystore/Cargo.toml +++ b/core/keystore/Cargo.toml @@ -2,17 +2,18 @@ name = "substrate-keystore" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] substrate-primitives = { path = "../primitives" } -parity-crypto = { version = "0.1", default-features = false } +crypto = { package = "parity-crypto", version = "0.3", default-features = false } error-chain = "0.12" hex = "0.3" -rand = "0.4" +rand = "0.6" serde_json = "1.0" serde = "1.0" serde_derive = "1.0" -subtle = "0.5" +subtle = "2.0" [dev-dependencies] tempdir = "0.3" diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index 6d8e3b3ae9f2398fa2ba35f012e0baf3d2a93f75..f0ab573cd6dd64002d837a72d043b2e1f2707dee 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,28 +16,19 @@ //! Keystore (and session key management) for ed25519 based chains like Polkadot. -extern crate substrate_primitives; -extern crate parity_crypto as crypto; -extern crate subtle; -extern crate rand; -extern crate serde_json; -extern crate hex; - -#[macro_use] -extern crate serde_derive; - -#[macro_use] -extern crate error_chain; - -#[cfg(test)] -extern crate tempdir; +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/substrate/issues/1547 +#![allow(deprecated)] use std::collections::HashMap; use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; -use substrate_primitives::{hashing::blake2_256, ed25519::{Pair, Public, PKCS_LEN}}; +use error_chain::{bail, error_chain, error_chain_processing, impl_error_chain_processed, + impl_extract_backtrace, impl_error_chain_kind}; + +use substrate_primitives::{ed25519::{Pair, Public}, Pair as _Pair}; pub use crypto::KEY_ITERATIONS; @@ -52,99 +43,21 @@ error_chain! { description("Invalid password"), display("Invalid password"), } - InvalidPKCS8 { - description("Invalid PKCS#8 data"), - display("Invalid PKCS#8 data"), + InvalidPhrase { + description("Invalid recovery phrase (BIP39) data"), + display("Invalid recovery phrase (BIP39) data"), } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct InvalidPassword; - -#[derive(Serialize, Deserialize)] -struct EncryptedKey { - mac: [u8; 32], - salt: [u8; 32], - ciphertext: Vec, // TODO: switch to fixed-size when serde supports - iv: [u8; 16], - iterations: u32, -} - -impl EncryptedKey { - fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: u32) -> Self { - use rand::{Rng, OsRng}; - - let mut rng = OsRng::new().expect("OS Randomness available on all supported platforms; qed"); - - let salt: [u8; 32] = rng.gen(); - let iv: [u8; 16] = rng.gen(); - - // two parts of derived key - // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); - - // preallocated (on-stack in case of `Secret`) buffer to hold cipher - // length = length(plain) as we are using CTR-approach - let mut ciphertext = vec![0; PKCS_LEN]; - - // aes-128-ctr with initial vector of iv - crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext) - .expect("input lengths of key and iv are both 16; qed"); - - // Blake2_256(DK[16..31] ++ ), where DK[16..31] - derived_right_bits - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &*ciphertext)); - - EncryptedKey { - salt, - iv, - mac, - iterations, - ciphertext, + InvalidSeed { + description("Invalid seed"), + display("Invalid seed"), } } - - fn decrypt(&self, password: &str) -> Result<[u8; PKCS_LEN]> { - let (derived_left_bits, derived_right_bits) = - crypto::derive_key_iterations(password.as_bytes(), &self.salt, self.iterations); - - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &self.ciphertext)); - - if subtle::slices_equal(&mac[..], &self.mac[..]) != 1 { - return Err(ErrorKind::InvalidPassword.into()); - } - - let mut plain = [0; PKCS_LEN]; - crypto::aes::decrypt_128_ctr(&derived_left_bits, &self.iv, &self.ciphertext, &mut plain[..]) - .expect("input lengths of key and iv are both 16; qed"); - Ok(plain) - } } -type Seed = [u8; 32]; - /// Key store. pub struct Store { path: PathBuf, - additional: HashMap, -} - -pub fn pad_seed(seed: &str) -> Seed { - let mut s: [u8; 32] = [' ' as u8; 32]; - - let was_hex = if seed.len() == 66 && &seed[0..2] == "0x" { - if let Ok(d) = hex::decode(&seed[2..]) { - s.copy_from_slice(&d); - true - } else { false } - } else { false }; - - if !was_hex { - let len = ::std::cmp::min(32, seed.len()); - &mut s[..len].copy_from_slice(&seed.as_bytes()[..len]); - } - - s + additional: HashMap, } impl Store { @@ -156,40 +69,36 @@ impl Store { /// Generate a new key, placing it into the store. pub fn generate(&self, password: &str) -> Result { - let (pair, pkcs_bytes) = Pair::generate_with_pkcs8(); - let key_file = EncryptedKey::encrypt(&pkcs_bytes, password, KEY_ITERATIONS as u32); - + let (pair, phrase) = Pair::generate_with_phrase(Some(password)); let mut file = File::create(self.key_file_path(&pair.public()))?; - ::serde_json::to_writer(&file, &key_file)?; - + ::serde_json::to_writer(&file, &phrase)?; file.flush()?; - Ok(pair) } /// Create a new key from seed. Do not place it into the store. - /// Only the first 32 bytes of the sead are used. This is meant to be used for testing only. - // FIXME: remove this - https://github.com/paritytech/substrate/issues/1063 pub fn generate_from_seed(&mut self, seed: &str) -> Result { - let padded_seed = pad_seed(seed); - let pair = Pair::from_seed(&padded_seed); - self.additional.insert(pair.public(), padded_seed); + let pair = Pair::from_string(seed, None) + .map_err(|_| Error::from(ErrorKind::InvalidSeed))?; + self.additional.insert(pair.public(), pair.clone()); Ok(pair) } /// Load a key file with given public key. pub fn load(&self, public: &Public, password: &str) -> Result { - if let Some(ref seed) = self.additional.get(public) { - let pair = Pair::from_seed(seed); - return Ok(pair); + if let Some(pair) = self.additional.get(public) { + return Ok(pair.clone()); } let path = self.key_file_path(public); let file = File::open(path)?; - let encrypted_key: EncryptedKey = ::serde_json::from_reader(&file)?; - let pkcs_bytes = encrypted_key.decrypt(password)?; - - Pair::from_pkcs8(&pkcs_bytes[..]).map_err(|_| ErrorKind::InvalidPKCS8.into()) + let phrase: String = ::serde_json::from_reader(&file)?; + let pair = Pair::from_phrase(&phrase, Some(password)) + .map_err(|_| Error::from(ErrorKind::InvalidPhrase))?; + if &pair.public() != public { + bail!(ErrorKind::InvalidPassword); + } + Ok(pair) } /// Get public keys of all stored keys. @@ -230,34 +139,6 @@ mod tests { use super::*; use tempdir::TempDir; - #[test] - fn encrypt_and_decrypt() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); - - let decrypted_key = encrypted_key.decrypt("thepassword").unwrap(); - - assert_eq!(&plain[..], &decrypted_key[..]); - } - - #[test] - fn decrypt_wrong_password_fails() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); - - assert!(encrypted_key.decrypt("thepassword2").is_err()); - } - - #[test] - fn decrypt_wrong_iterations_fails() { - let plain = [1; PKCS_LEN]; - let mut encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", KEY_ITERATIONS as u32); - - encrypted_key.iterations -= 64; - - assert!(encrypted_key.decrypt("thepassword").is_err()); - } - #[test] fn basic_store() { let temp_dir = TempDir::new("keystore").unwrap(); @@ -280,16 +161,7 @@ mod tests { let temp_dir = TempDir::new("keystore").unwrap(); let mut store = Store::open(temp_dir.path().to_owned()).unwrap(); - let pair = store.generate_from_seed("0x1").unwrap(); - assert_eq!("5GqhgbUd2S9uc5Tm7hWhw29Tw2jBnuHshmTV1fDF4V1w3G2z", pair.public().to_ss58check()); - let pair = store.generate_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc").unwrap(); assert_eq!("5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HBL8", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("12345678901234567890123456789022").unwrap(); - assert_eq!("5DscZvfjnM5im7oKRXXP9xtCG1SEwfMb8J5eGLmw5EHhoHR3", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("1").unwrap(); - assert_eq!("5DYnksEZFc7kgtfyNM1xK2eBtW142gZ3Ho3NQubrF2S6B2fq", pair.public().to_ss58check()); } } diff --git a/core/network-libp2p/Cargo.toml b/core/network-libp2p/Cargo.toml index 6b0fb9af40177bbb232bd24c4de52d203b4d0c86..ab784ac9783fc8bdd2bad8d52203c5a9c252304c 100644 --- a/core/network-libp2p/Cargo.toml +++ b/core/network-libp2p/Cargo.toml @@ -5,25 +5,25 @@ license = "GPL-3.0" name = "substrate-network-libp2p" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] +byteorder = "1.3" bytes = "0.4" error-chain = { version = "0.12", default-features = false } fnv = "1.0" futures = "0.1" -libp2p = { git = "https://github.com/libp2p/rust-libp2p", rev = "d961e656a74d1bab5366d371a06f9e10d5f4a6c5", default-features = false, features = ["secio-rsa", "secio-secp256k1"] } -parking_lot = "0.5" -libc = "0.2" +libp2p = { version = "0.4.0", default-features = false, features = ["secio-secp256k1", "libp2p-websocket"] } +parking_lot = "0.7.1" +lazy_static = "1.2" log = "0.4" -rand = "0.5.0" +rand = "0.6" serde = "1.0.70" serde_derive = "1.0.70" serde_json = "1.0.24" +smallvec = "0.6" tokio = "0.1" tokio-io = "0.1" tokio-timer = "0.2" unsigned-varint = { version = "0.2.1", features = ["codec"] } - -[dev-dependencies] -assert_matches = "1.2" -parity-bytes = "0.1" +void = "1.0" diff --git a/core/network-libp2p/src/behaviour.rs b/core/network-libp2p/src/behaviour.rs new file mode 100644 index 0000000000000000000000000000000000000000..ba79e0ef3207bde049f185cb4f582fc4c7f61218 --- /dev/null +++ b/core/network-libp2p/src/behaviour.rs @@ -0,0 +1,447 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::custom_proto::{CustomProtos, CustomProtosOut, RegisteredProtocols}; +use crate::{NetworkConfiguration, ProtocolId}; +use futures::prelude::*; +use libp2p::NetworkBehaviour; +use libp2p::core::{Multiaddr, PeerId, ProtocolsHandler, PublicKey}; +use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction}; +use libp2p::core::swarm::{NetworkBehaviourEventProcess, PollParameters}; +use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo}; +use libp2p::kad::{Kademlia, KademliaOut, KadConnectionType}; +use libp2p::ping::{Ping, PingEvent}; +use log::{debug, trace, warn}; +use std::{cmp, io, time::Duration, time::Instant}; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer::Delay; +use void; + +/// General behaviour of the network. +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "BehaviourOut", poll_method = "poll")] +pub struct Behaviour { + /// Periodically ping nodes, and close the connection if it's unresponsive. + ping: Ping, + /// Custom protocols (dot, bbq, sub, etc.). + custom_protocols: CustomProtos, + /// Discovers nodes of the network. Defined below. + discovery: DiscoveryBehaviour, + /// Periodically identifies the remote and responds to incoming requests. + identify: Identify, + + /// Queue of events to produce for the outside. + #[behaviour(ignore)] + events: Vec>, +} + +impl Behaviour { + /// Builds a new `Behaviour`. + // TODO: redundancy between config and local_public_key (https://github.com/libp2p/rust-libp2p/issues/745) + pub fn new(config: &NetworkConfiguration, local_public_key: PublicKey, protocols: RegisteredProtocols) -> Self { + let identify = { + let proto_version = "/substrate/1.0".to_string(); + let user_agent = format!("{} ({})", config.client_version, config.node_name); + Identify::new(proto_version, user_agent, local_public_key.clone()) + }; + + let local_peer_id = local_public_key.into_peer_id(); + let custom_protocols = CustomProtos::new(config, &local_peer_id, protocols); + + Behaviour { + ping: Ping::new(), + custom_protocols, + discovery: DiscoveryBehaviour::new(local_peer_id), + identify, + events: Vec::new(), + } + } + + /// Sends a message to a peer using the given custom protocol. + /// + /// Has no effect if the custom protocol is not open with the given peer. + /// + /// Also note that even we have a valid open substream, it may in fact be already closed + /// without us knowing, in which case the packet will not be received. + #[inline] + pub fn send_custom_message(&mut self, target: &PeerId, protocol_id: ProtocolId, data: TMessage) { + self.custom_protocols.send_packet(target, protocol_id, data) + } + + /// Returns the number of peers in the topology. + pub fn num_topology_peers(&self) -> usize { + self.custom_protocols.num_topology_peers() + } + + /// Flushes the topology to the disk. + pub fn flush_topology(&mut self) -> Result<(), io::Error> { + self.custom_protocols.flush_topology() + } + + /// Perform a cleanup pass, removing all obsolete addresses and peers. + /// + /// This should be done from time to time. + pub fn cleanup(&mut self) { + self.custom_protocols.cleanup(); + } + + /// Returns the list of reserved nodes. + pub fn reserved_peers(&self) -> impl Iterator { + self.custom_protocols.reserved_peers() + } + + /// Try to add a reserved peer. + pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.custom_protocols.add_reserved_peer(peer_id, addr) + } + + /// Try to remove a reserved peer. + /// + /// If we are in reserved mode and we were connected to a node with this peer ID, then this + /// method will disconnect it and return its index. + pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { + self.custom_protocols.remove_reserved_peer(peer_id) + } + + /// Returns true if we only accept reserved nodes. + pub fn is_reserved_only(&self) -> bool { + self.custom_protocols.is_reserved_only() + } + + /// Start accepting all peers again if we weren't. + pub fn accept_unreserved_peers(&mut self) { + self.custom_protocols.accept_unreserved_peers() + } + + /// Start refusing non-reserved nodes. Returns the list of nodes that have been disconnected. + pub fn deny_unreserved_peers(&mut self) { + self.custom_protocols.deny_unreserved_peers() + } + + /// Disconnects a peer and bans it for a little while. + /// + /// Same as `drop_node`, except that the same peer will not be able to reconnect later. + #[inline] + pub fn ban_node(&mut self, peer_id: PeerId) { + self.custom_protocols.ban_peer(peer_id) + } + + /// Returns a list of all the peers that are banned, and until when. + pub fn banned_nodes(&self) -> impl Iterator { + self.custom_protocols.banned_peers() + } + + /// Returns true if we try to open protocols with the given peer. + pub fn is_enabled(&self, peer_id: &PeerId) -> bool { + self.custom_protocols.is_enabled(peer_id) + } + + /// Returns the list of protocols we have open with the given peer. + pub fn open_protocols<'a>(&'a self, peer_id: &'a PeerId) -> impl Iterator + 'a { + self.custom_protocols.open_protocols(peer_id) + } + + /// Disconnects the custom protocols from a peer. + /// + /// The peer will still be able to use Kademlia or other protocols, but will get disconnected + /// after a few seconds of inactivity. + /// + /// This is asynchronous and does not instantly close the custom protocols. + /// Corresponding closing events will be generated once the closing actually happens. + /// + /// Has no effect if we're not connected to the `PeerId`. + #[inline] + pub fn drop_node(&mut self, peer_id: &PeerId) { + self.custom_protocols.disconnect_peer(peer_id) + } + + /// Returns the list of peers in the topology. + pub fn known_peers(&self) -> impl Iterator { + self.custom_protocols.known_peers() + } + + /// Returns a list of addresses known for this peer, and their reputation score. + pub fn known_addresses(&mut self, peer_id: &PeerId) -> impl Iterator { + self.custom_protocols.known_addresses(peer_id) + } +} + +/// Event that can be emitted by the behaviour. +#[derive(Debug)] +pub enum BehaviourOut { + /// Opened a custom protocol with the remote. + CustomProtocolOpen { + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Version of the protocol that has been opened. + version: u8, + /// Id of the node we have opened a connection with. + peer_id: PeerId, + /// Endpoint used for this custom protocol. + endpoint: ConnectedPoint, + }, + + /// Closed a custom protocol with the remote. + CustomProtocolClosed { + /// Id of the peer we were connected to. + peer_id: PeerId, + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). + result: io::Result<()>, + }, + + /// Receives a message on a custom protocol substream. + CustomMessage { + /// Id of the peer the message came from. + peer_id: PeerId, + /// Protocol which generated the message. + protocol_id: ProtocolId, + /// Message that has been received. + message: TMessage, + }, + + /// A substream with a remote is clogged. We should avoid sending more data to it if possible. + Clogged { + /// Id of the peer the message came from. + peer_id: PeerId, + /// Protocol which generated the message. + protocol_id: ProtocolId, + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec, + }, + + /// We have obtained debug information from a peer. + Identified { + /// Id of the peer that has been identified. + peer_id: PeerId, + /// Information about the peer. + info: IdentifyInfo, + }, + + /// We have successfully pinged a peer. + PingSuccess { + /// Id of the peer that has been pinged. + peer_id: PeerId, + /// Time it took for the ping to come back. + ping_time: Duration, + }, +} + +impl From> for BehaviourOut { + fn from(other: CustomProtosOut) -> BehaviourOut { + match other { + CustomProtosOut::CustomProtocolOpen { protocol_id, version, peer_id, endpoint } => { + BehaviourOut::CustomProtocolOpen { protocol_id, version, peer_id, endpoint } + } + CustomProtosOut::CustomProtocolClosed { protocol_id, peer_id, result } => { + BehaviourOut::CustomProtocolClosed { protocol_id, peer_id, result } + } + CustomProtosOut::CustomMessage { protocol_id, peer_id, message } => { + BehaviourOut::CustomMessage { protocol_id, peer_id, message } + } + CustomProtosOut::Clogged { protocol_id, peer_id, messages } => { + BehaviourOut::Clogged { protocol_id, peer_id, messages } + } + } + } +} + +impl NetworkBehaviourEventProcess for Behaviour { + fn inject_event(&mut self, event: void::Void) { + void::unreachable(event) + } +} + +impl NetworkBehaviourEventProcess> for Behaviour { + fn inject_event(&mut self, event: CustomProtosOut) { + self.events.push(event.into()); + } +} + +impl NetworkBehaviourEventProcess for Behaviour { + fn inject_event(&mut self, event: IdentifyEvent) { + match event { + IdentifyEvent::Identified { peer_id, mut info, .. } => { + trace!(target: "sub-libp2p", "Identified {:?} => {:?}", peer_id, info); + // TODO: ideally we would delay the first identification to when we open the custom + // protocol, so that we only report id info to the service about the nodes we + // care about (https://github.com/libp2p/rust-libp2p/issues/876) + if !info.protocol_version.contains("substrate") { + warn!(target: "sub-libp2p", "Connected to a non-Substrate node: {:?}", info); + } + if info.listen_addrs.len() > 30 { + warn!(target: "sub-libp2p", "Node {:?} id reported more than 30 addresses", + peer_id); + info.listen_addrs.truncate(30); + } + for addr in &info.listen_addrs { + self.discovery.kademlia.add_connected_address(&peer_id, addr.clone()); + } + self.custom_protocols.add_discovered_addrs( + &peer_id, + info.listen_addrs.iter().map(|addr| (addr.clone(), true)) + ); + self.events.push(BehaviourOut::Identified { peer_id, info }); + } + IdentifyEvent::Error { .. } => {} + IdentifyEvent::SendBack { result: Err(ref err), ref peer_id } => + debug!(target: "sub-libp2p", "Error when sending back identify info \ + to {:?} => {}", peer_id, err), + IdentifyEvent::SendBack { .. } => {} + } + } +} + +impl NetworkBehaviourEventProcess for Behaviour { + fn inject_event(&mut self, out: KademliaOut) { + match out { + KademliaOut::Discovered { peer_id, addresses, ty } => { + self.custom_protocols.add_discovered_addrs( + &peer_id, + addresses.into_iter().map(|addr| (addr, ty == KadConnectionType::Connected)) + ); + } + KademliaOut::FindNodeResult { key, closer_peers } => { + trace!(target: "sub-libp2p", "Kademlia query for {:?} yielded {:?} results", + key, closer_peers.len()); + if closer_peers.is_empty() { + warn!(target: "sub-libp2p", "Kademlia random query has yielded empty results"); + } + } + // We never start any GET_PROVIDERS query. + KademliaOut::GetProvidersResult { .. } => () + } + } +} + +impl NetworkBehaviourEventProcess for Behaviour { + fn inject_event(&mut self, event: PingEvent) { + match event { + PingEvent::PingSuccess { peer, time } => { + trace!(target: "sub-libp2p", "Ping time with {:?}: {:?}", peer, time); + self.events.push(BehaviourOut::PingSuccess { peer_id: peer, ping_time: time }); + } + } + } +} + +impl Behaviour { + fn poll(&mut self) -> Async>> { + if !self.events.is_empty() { + return Async::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0))) + } + + Async::NotReady + } +} + +/// Implementation of `NetworkBehaviour` that discovers the nodes on the network. +pub struct DiscoveryBehaviour { + /// Kademlia requests and answers. + kademlia: Kademlia, + /// Stream that fires when we need to perform the next random Kademlia query. + next_kad_random_query: Delay, + /// After `next_kad_random_query` triggers, the next one triggers after this duration. + duration_to_next_kad: Duration, +} + +impl DiscoveryBehaviour { + fn new(local_peer_id: PeerId) -> Self { + DiscoveryBehaviour { + kademlia: Kademlia::without_init(local_peer_id), + next_kad_random_query: Delay::new(Instant::now()), + duration_to_next_kad: Duration::from_secs(1), + } + } +} + +impl NetworkBehaviour for DiscoveryBehaviour +where + TSubstream: AsyncRead + AsyncWrite, +{ + type ProtocolsHandler = as NetworkBehaviour>::ProtocolsHandler; + type OutEvent = as NetworkBehaviour>::OutEvent; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + NetworkBehaviour::new_handler(&mut self.kademlia) + } + + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + self.kademlia.addresses_of_peer(peer_id) + } + + fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { + NetworkBehaviour::inject_connected(&mut self.kademlia, peer_id, endpoint) + } + + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + NetworkBehaviour::inject_disconnected(&mut self.kademlia, peer_id, endpoint) + } + + fn inject_replaced(&mut self, peer_id: PeerId, closed: ConnectedPoint, opened: ConnectedPoint) { + NetworkBehaviour::inject_replaced(&mut self.kademlia, peer_id, closed, opened) + } + + fn inject_node_event( + &mut self, + peer_id: PeerId, + event: ::OutEvent, + ) { + NetworkBehaviour::inject_node_event(&mut self.kademlia, peer_id, event) + } + + fn poll( + &mut self, + params: &mut PollParameters, + ) -> Async< + NetworkBehaviourAction< + ::InEvent, + Self::OutEvent, + >, + > { + // Poll Kademlia. + match self.kademlia.poll(params) { + Async::Ready(action) => return Async::Ready(action), + Async::NotReady => (), + } + + // Poll the stream that fires when we need to start a random Kademlia query. + loop { + match self.next_kad_random_query.poll() { + Ok(Async::NotReady) => break, + Ok(Async::Ready(_)) => { + let random_peer_id = PeerId::random(); + debug!(target: "sub-libp2p", "Starting random Kademlia request for {:?}", + random_peer_id); + self.kademlia.find_node(random_peer_id); + + // Reset the `Delay` to the next random. + self.next_kad_random_query.reset(Instant::now() + self.duration_to_next_kad); + self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2, + Duration::from_secs(60)); + }, + Err(err) => { + warn!(target: "sub-libp2p", "Kad query timer errored: {:?}", err); + break + } + } + } + + Async::NotReady + } +} + diff --git a/core/network-libp2p/src/custom_proto.rs b/core/network-libp2p/src/custom_proto.rs deleted file mode 100644 index fd76581d3ed716c55dcb588de3e4c0e307e01528..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/custom_proto.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use bytes::Bytes; -use libp2p::core::{ConnectionUpgrade, Endpoint}; -use libp2p::tokio_codec::Framed; -use std::{collections::VecDeque, io, vec::IntoIter as VecIntoIter}; -use futures::{prelude::*, future, stream, task}; -use tokio_io::{AsyncRead, AsyncWrite}; -use unsigned_varint::codec::UviBytes; -use ProtocolId; - -/// Connection upgrade for a single protocol. -/// -/// Note that "a single protocol" here refers to `par` for example. However -/// each protocol can have multiple different versions for networking purposes. -#[derive(Clone)] -pub struct RegisteredProtocol { - /// Id of the protocol for API purposes. - id: ProtocolId, - /// Base name of the protocol as advertised on the network. - /// Ends with `/` so that we can append a version number behind. - base_name: Bytes, - /// List of protocol versions that we support. - /// Ordered in descending order so that the best comes first. - supported_versions: Vec, -} - -impl RegisteredProtocol { - /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be - /// passed inside the `RegisteredProtocolOutput`. - pub fn new(protocol: ProtocolId, versions: &[u8]) - -> Self { - let mut base_name = Bytes::from_static(b"/substrate/"); - base_name.extend_from_slice(&protocol); - base_name.extend_from_slice(b"/"); - - RegisteredProtocol { - base_name, - id: protocol, - supported_versions: { - let mut tmp = versions.to_vec(); - tmp.sort_unstable_by(|a, b| b.cmp(&a)); - tmp - }, - } - } - - /// Returns the ID of the protocol. - #[inline] - pub fn id(&self) -> ProtocolId { - self.id - } -} - -/// Output of a `RegisteredProtocol` upgrade. -pub struct RegisteredProtocolSubstream { - /// If true, we are in the process of closing the sink. - is_closing: bool, - /// Buffer of packets to send. - send_queue: VecDeque, - /// If true, we should call `poll_complete` on the inner sink. - requires_poll_complete: bool, - /// The underlying substream. - inner: stream::Fuse>>, - /// Id of the protocol. - protocol_id: ProtocolId, - /// Version of the protocol that was negotiated. - protocol_version: u8, - /// Task to notify when something is changed and we need to be polled. - to_notify: Option, -} - -impl RegisteredProtocolSubstream { - /// Returns the protocol id. - #[inline] - pub fn protocol_id(&self) -> ProtocolId { - self.protocol_id - } - - /// Returns the version of the protocol that was negotiated. - #[inline] - pub fn protocol_version(&self) -> u8 { - self.protocol_version - } - - /// Starts a graceful shutdown process on this substream. - /// - /// Note that "graceful" means that we sent a closing message. We don't wait for any - /// confirmation from the remote. - /// - /// After calling this, the stream is guaranteed to finish soon-ish. - pub fn shutdown(&mut self) { - self.is_closing = true; - if let Some(task) = self.to_notify.take() { - task.notify(); - } - } - - /// Sends a message to the substream. - pub fn send_message(&mut self, data: Bytes) { - self.send_queue.push_back(data); - - // If the length of the queue goes over a certain arbitrary threshold, we print a warning. - if self.send_queue.len() >= 2048 { - warn!(target: "sub-libp2p", "Queue of packets to send over substream is pretty \ - large: {}", self.send_queue.len()); - } - - if let Some(task) = self.to_notify.take() { - task.notify(); - } - } -} - -impl Stream for RegisteredProtocolSubstream -where TSubstream: AsyncRead + AsyncWrite, -{ - type Item = Bytes; - type Error = io::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - // If we are closing, close as soon as the Sink is closed. - if self.is_closing { - return Ok(self.inner.close()?.map(|()| None)); - } - - // Flushing the local queue. - while let Some(packet) = self.send_queue.pop_front() { - match self.inner.start_send(packet)? { - AsyncSink::NotReady(packet) => { - self.send_queue.push_front(packet); - break; - }, - AsyncSink::Ready => self.requires_poll_complete = true, - } - } - - // Flushing if necessary. - if self.requires_poll_complete { - if let Async::Ready(()) = self.inner.poll_complete()? { - self.requires_poll_complete = false; - } - } - - // Receiving incoming packets. - // Note that `inner` is wrapped in a `Fuse`, therefore we can poll it forever. - loop { - match self.inner.poll()? { - Async::Ready(Some(data)) => - return Ok(Async::Ready(Some(data.freeze()))), - Async::Ready(None) => - if !self.requires_poll_complete && self.send_queue.is_empty() { - return Ok(Async::Ready(None)) - } else { - break - }, - Async::NotReady => break, - } - } - - self.to_notify = Some(task::current()); - Ok(Async::NotReady) - } -} - -impl ConnectionUpgrade for RegisteredProtocol -where TSubstream: AsyncRead + AsyncWrite, -{ - type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; - type UpgradeIdentifier = u8; // Protocol version - - #[inline] - fn protocol_names(&self) -> Self::NamesIter { - // Report each version as an individual protocol. - self.supported_versions.iter().map(|&ver| { - let num = ver.to_string(); - let mut name = self.base_name.clone(); - name.extend_from_slice(num.as_bytes()); - (name, ver) - }).collect::>().into_iter() - } - - type Output = RegisteredProtocolSubstream; - type Future = future::FutureResult; - - #[allow(deprecated)] - fn upgrade( - self, - socket: TSubstream, - protocol_version: Self::UpgradeIdentifier, - _: Endpoint - ) -> Self::Future { - let framed = Framed::new(socket, UviBytes::default()); - - future::ok(RegisteredProtocolSubstream { - is_closing: false, - send_queue: VecDeque::new(), - requires_poll_complete: false, - inner: framed.fuse(), - protocol_id: self.id, - protocol_version, - to_notify: None, - }) - } -} - -// Connection upgrade for all the protocols contained in it. -#[derive(Clone)] -pub struct RegisteredProtocols(pub Vec); - -impl RegisteredProtocols { - /// Returns the number of protocols. - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } - - /// Finds a protocol in the list by its id. - pub fn find_protocol(&self, protocol: ProtocolId) - -> Option<&RegisteredProtocol> { - self.0.iter().find(|p| p.id == protocol) - } - - /// Returns true if the given protocol is in the list. - pub fn has_protocol(&self, protocol: ProtocolId) -> bool { - self.0.iter().any(|p| p.id == protocol) - } -} - -impl Default for RegisteredProtocols { - fn default() -> Self { - RegisteredProtocols(Vec::new()) - } -} - -impl ConnectionUpgrade for RegisteredProtocols -where TSubstream: AsyncRead + AsyncWrite, -{ - type NamesIter = VecIntoIter<(Bytes, Self::UpgradeIdentifier)>; - type UpgradeIdentifier = (usize, - >::UpgradeIdentifier); - - fn protocol_names(&self) -> Self::NamesIter { - // We concat the lists of `RegisteredProtocol::protocol_names` for - // each protocol. - self.0.iter().enumerate().flat_map(|(n, proto)| - ConnectionUpgrade::::protocol_names(proto) - .map(move |(name, id)| (name, (n, id))) - ).collect::>().into_iter() - } - - type Output = >::Output; - type Future = >::Future; - - #[inline] - fn upgrade( - self, - socket: TSubstream, - upgrade_identifier: Self::UpgradeIdentifier, - endpoint: Endpoint - ) -> Self::Future { - let (protocol_index, inner_proto_id) = upgrade_identifier; - self.0.into_iter() - .nth(protocol_index) - .expect("invalid protocol index ; programmer logic error") - .upgrade(socket, inner_proto_id, endpoint) - } -} diff --git a/core/network-libp2p/src/custom_proto/behaviour.rs b/core/network-libp2p/src/custom_proto/behaviour.rs new file mode 100644 index 0000000000000000000000000000000000000000..1332dfd0df2fbc7b059c17f8b0efa706dce8b197 --- /dev/null +++ b/core/network-libp2p/src/custom_proto/behaviour.rs @@ -0,0 +1,703 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::custom_proto::handler::{CustomProtosHandler, CustomProtosHandlerOut, CustomProtosHandlerIn}; +use crate::custom_proto::topology::NetTopology; +use crate::custom_proto::upgrade::{CustomMessage, RegisteredProtocols}; +use crate::{NetworkConfiguration, NonReservedPeerMode, ProtocolId}; +use crate::parse_str_addr; +use fnv::{FnvHashMap, FnvHashSet}; +use futures::prelude::*; +use libp2p::core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use libp2p::core::{protocols_handler::ProtocolsHandler, Endpoint, Multiaddr, PeerId}; +use log::{debug, trace, warn}; +use smallvec::SmallVec; +use std::{cmp, error, io, marker::PhantomData, path::Path, time::Duration, time::Instant}; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer::Delay; + +// File where the network topology is stored. +const NODES_FILE: &str = "nodes.json"; +// Duration during which a peer is disabled. +const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); + +/// Network behaviour that handles opening substreams for custom protocols with other nodes. +pub struct CustomProtos { + /// List of protocols to open with peers. Never modified. + registered_protocols: RegisteredProtocols, + + /// Topology of the network. + topology: NetTopology, + + /// List of custom protocols that we have open with remotes. + open_protocols: Vec<(PeerId, ProtocolId)>, + + /// List of peer handlers that were enabled. + /// + /// Note that it is possible for a peer to be in the shutdown process, in which case it will + /// not be in this list but will be present in `open_protocols`. + /// It is also possible that we have *just* enabled a peer, in which case it will be in this + /// list but not in `open_protocols`. + enabled_peers: FnvHashSet, + + /// Maximum number of incoming non-reserved connections, taken from the config. Never modified. + max_incoming_connections: usize, + + /// Maximum number of outgoing non-reserved connections, taken from the config. Never modified. + max_outgoing_connections: usize, + + /// If true, only reserved peers can connect. + reserved_only: bool, + + /// List of the IDs of the peers we are connected to, and whether we're dialing or listening. + connected_peers: FnvHashMap, + + /// List of the IDs of the reserved peers. We always try to maintain a connection these peers. + reserved_peers: FnvHashSet, + + /// List of the IDs of peers that are forbidden, and the moment their ban expires. + banned_peers: Vec<(PeerId, Instant)>, + + /// When this delay expires, we need to synchronize our active connectons with the + /// network topology. + next_connect_to_nodes: Delay, + + /// Events to produce from `poll()`. + events: SmallVec<[NetworkBehaviourAction, CustomProtosOut>; 4]>, + + /// Marker to pin the generics. + marker: PhantomData, +} + +/// Event that can be emitted by the `CustomProtos`. +#[derive(Debug)] +pub enum CustomProtosOut { + /// Opened a custom protocol with the remote. + CustomProtocolOpen { + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Version of the protocol that has been opened. + version: u8, + /// Id of the node we have opened a connection with. + peer_id: PeerId, + /// Endpoint used for this custom protocol. + endpoint: ConnectedPoint, + }, + + /// Closed a custom protocol with the remote. + CustomProtocolClosed { + /// Id of the peer we were connected to. + peer_id: PeerId, + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). + result: io::Result<()>, + }, + + /// Receives a message on a custom protocol substream. + CustomMessage { + /// Id of the peer the message came from. + peer_id: PeerId, + /// Protocol which generated the message. + protocol_id: ProtocolId, + /// Message that has been received. + message: TMessage, + }, + + /// The substream used by the protocol is pretty large. We should print avoid sending more + /// messages on it if possible. + Clogged { + /// Id of the peer which is clogged. + peer_id: PeerId, + /// Protocol which has a problem. + protocol_id: ProtocolId, + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec, + }, +} + +impl CustomProtos { + /// Creates a `CustomProtos`. + pub fn new(config: &NetworkConfiguration, local_peer_id: &PeerId, registered_protocols: RegisteredProtocols) -> Self { + // Initialize the topology of the network. + let mut topology = if let Some(ref path) = config.net_config_path { + let path = Path::new(path).join(NODES_FILE); + debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); + NetTopology::from_file(local_peer_id.clone(), path) + } else { + debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); + NetTopology::memory(local_peer_id.clone()) + }; + + // Add the bootstrap nodes to the topology. + for bootnode in config.boot_nodes.iter() { + if let Ok((peer_id, addr)) = parse_str_addr(bootnode) { + topology.add_bootstrap_addr(&peer_id, addr.clone()); + } + } + + let max_incoming_connections = config.in_peers as usize; + let max_outgoing_connections = config.out_peers as usize; + + // Expected maximum number of connections. + let connec_cap = max_incoming_connections + .saturating_add(max_outgoing_connections) + .saturating_add(4); // We add an arbitrary number for reserved peers slots + + // Expected maximum number of substreams. + let open_protos_cap = connec_cap.saturating_mul(registered_protocols.len()); + + CustomProtos { + registered_protocols, + topology, + max_incoming_connections, + max_outgoing_connections, + reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, + connected_peers: Default::default(), + reserved_peers: Default::default(), + banned_peers: Vec::new(), + open_protocols: Vec::with_capacity(open_protos_cap), + enabled_peers: FnvHashSet::with_capacity_and_hasher(connec_cap, Default::default()), + next_connect_to_nodes: Delay::new(Instant::now()), + events: SmallVec::new(), + marker: PhantomData, + } + } + + /// Returns the list of reserved nodes. + pub fn reserved_peers(&self) -> impl Iterator { + self.reserved_peers.iter() + } + + /// Adds a reserved peer. + pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.topology.add_bootstrap_addr(&peer_id, addr); + self.reserved_peers.insert(peer_id); + + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } + + /// Removes a reserved peer. + /// + /// If we are in reserved mode and we were connected to a node with this peer ID, then this + /// method will disconnect it and return its index. + pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { + self.reserved_peers.remove(&peer_id); + } + + /// Returns true if we only accept reserved nodes. + pub fn is_reserved_only(&self) -> bool { + self.reserved_only + } + + /// Start accepting all peers again if we weren't. + pub fn accept_unreserved_peers(&mut self) { + if !self.reserved_only { + return + } + + self.reserved_only = false; + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } + + /// Start refusing non-reserved nodes. + pub fn deny_unreserved_peers(&mut self) { + if self.reserved_only { + return + } + + self.reserved_only = true; + + // Disconnecting nodes that are connected to us and that aren't reserved + let reserved_peers = &mut self.reserved_peers; + let events = &mut self.events; + self.enabled_peers.retain(move |peer_id| { + if reserved_peers.contains(peer_id) { + return true + } + events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); + false + }) + } + + /// Disconnects the given peer if we are connected to it. + pub fn disconnect_peer(&mut self, peer: &PeerId) { + if self.reserved_peers.contains(peer) { + warn!(target: "sub-libp2p", "Ignored attempt to disconnect reserved peer {:?}", peer); + return; + } + + if self.enabled_peers.remove(peer) { + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer.clone(), + event: CustomProtosHandlerIn::Disable, + }); + } + } + + /// Disconnects the given peer if we are connected to it and disables it for a little while. + pub fn ban_peer(&mut self, peer_id: PeerId) { + if self.reserved_peers.contains(&peer_id) { + warn!(target: "sub-libp2p", "Ignored attempt to ban reserved peer {:?}", peer_id); + return; + } + + // Peer is already banned + if let Some(pos) = self.banned_peers.iter().position(|(p, _)| p == &peer_id) { + if self.banned_peers[pos].1 > Instant::now() { + return + } else { + self.banned_peers.remove(pos); + } + } + + self.banned_peers.push((peer_id.clone(), Instant::now() + PEER_DISABLE_DURATION)); + if self.enabled_peers.remove(&peer_id) { + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id, + event: CustomProtosHandlerIn::Disable, + }); + } + } + + /// Returns a list of all the peers that are banned, and until when. + pub fn banned_peers(&self) -> impl Iterator { + self.banned_peers.iter().map(|&(ref id, until)| (id, until)) + } + + /// Returns true if we try to open protocols with the given peer. + pub fn is_enabled(&self, peer_id: &PeerId) -> bool { + self.enabled_peers.contains(peer_id) + } + + /// Returns the list of protocols we have open with the given peer. + pub fn open_protocols<'a>(&'a self, peer_id: &'a PeerId) -> impl Iterator + 'a { + self.open_protocols + .iter() + .filter(move |(p, _)| p == peer_id) + .map(|(_, proto)| *proto) + } + + /// Sends a message to a peer using the given custom protocol. + /// + /// Has no effect if the custom protocol is not open with the given peer. + /// + /// Also note that even we have a valid open substream, it may in fact be already closed + /// without us knowing, in which case the packet will not be received. + pub fn send_packet(&mut self, target: &PeerId, protocol_id: ProtocolId, message: TMessage) { + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: target.clone(), + event: CustomProtosHandlerIn::SendCustomMessage { + protocol: protocol_id, + message, + } + }); + } + + /// Indicates to the topology that we have discovered new addresses for a given node. + pub fn add_discovered_addrs( + &mut self, + peer_id: &PeerId, + addrs: I, + ) where I: Iterator { + if self.topology.add_discovered_addrs(peer_id, addrs) { + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + } + } + + /// Returns the number of peers in the topology. + pub fn num_topology_peers(&self) -> usize { + self.topology.num_peers() + } + + /// Flushes the topology to the disk. + pub fn flush_topology(&mut self) -> Result<(), io::Error> { + self.topology.flush_to_disk() + } + + /// Perform a cleanup pass, removing all obsolete addresses and peers. + /// + /// This should be done from time to time. + pub fn cleanup(&mut self) { + self.topology.cleanup(); + } + + /// Returns the list of peers in the topology. + pub fn known_peers(&self) -> impl Iterator { + self.topology.known_peers() + } + + /// Returns a list of addresses known for this peer, and their reputation score. + pub fn known_addresses(&mut self, peer_id: &PeerId) -> impl Iterator { + self.topology.addresses_of_peer(peer_id, true) + } + + /// Updates the attempted connections to nodes. + /// + /// Also updates `next_connect_to_nodes` with the earliest known moment when we need to + /// update connections again. + fn connect_to_nodes(&mut self, params: &mut PollParameters) { + // Value of `Instant::now()` grabbed once at the beginning. + let now = Instant::now(); + + // Make sure we are connected or connecting to all the reserved nodes. + for reserved in self.reserved_peers.iter() { + // TODO: don't generate an event if we're already in a pending connection (https://github.com/libp2p/rust-libp2p/issues/697) + if !self.enabled_peers.contains(&reserved) { + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: reserved.clone() }); + } + } + + // We're done with reserved node; return early if there's nothing more to do. + if self.reserved_only { + // We set a timeout to 60 seconds for trying to connect again, however in practice + // a round will happen as soon as we fail to dial, disconnect from a node, allow + // unreserved nodes, and so on. + self.next_connect_to_nodes.reset(now + Duration::from_secs(60)); + return + } + + // Counter of number of connections to open, decreased when we open one. + let mut num_to_open = { + let num_outgoing_connections = self.enabled_peers + .iter() + .filter(|p| self.connected_peers.get(p).map(|c| c.is_dialer()).unwrap_or(false)) + .filter(|p| !self.reserved_peers.contains(p)) + .count(); + self.max_outgoing_connections - num_outgoing_connections + }; + trace!(target: "sub-libp2p", "Connect-to-nodes round; attempting to fill {:?} slots", + num_to_open); + + // We first try to enable existing connections. + for peer_id in self.connected_peers.keys() { + if num_to_open == 0 { + break + } + + if self.enabled_peers.contains(peer_id) { + continue; + } + + if let Some((_, expire)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { + if *expire >= now { + continue; + } + } + + trace!(target: "sub-libp2p", "Enabling custom protocols with {:?} (active)", peer_id); + num_to_open -= 1; + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Enable(Endpoint::Dialer), + }); + } + + // Then, try to open new connections. + let local_peer_id = params.local_peer_id().clone(); + let (to_try, will_change) = self.topology.addrs_to_attempt(); + for (peer_id, _) in to_try { + if num_to_open == 0 { + break + } + + if peer_id == &local_peer_id { + continue + } + + if self.connected_peers.contains_key(&peer_id) { + continue + } + + if let Some((_, ban_end)) = self.banned_peers.iter().find(|(p, _)| p == peer_id) { + if *ban_end > now { + continue + } + } + + num_to_open -= 1; + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); + } + + // Next round is when we expect the topology will change. + self.next_connect_to_nodes.reset(cmp::min(will_change, now + Duration::from_secs(60))); + } +} + +impl NetworkBehaviour for CustomProtos +where + TSubstream: AsyncRead + AsyncWrite, + TMessage: CustomMessage, +{ + type ProtocolsHandler = CustomProtosHandler; + type OutEvent = CustomProtosOut; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + CustomProtosHandler::new(self.registered_protocols.clone()) + } + + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + self.topology.addresses_of_peer(peer_id, false).map(|(a, _)| a.clone()).collect() + } + + fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { + // When a peer connects, its handler is initially in the disabled state. We make sure that + // the peer is allowed, and if so we put it in the enabled state. + + self.connected_peers.insert(peer_id.clone(), endpoint.clone()); + + let is_reserved = self.reserved_peers.contains(&peer_id); + if self.reserved_only && !is_reserved { + debug!(target: "sub-libp2p", "Ignoring {:?} because we're in reserved mode", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); + return + } + + // Check whether peer is banned. + if !is_reserved { + if let Some((_, expire)) = self.banned_peers.iter().find(|(p, _)| p == &peer_id) { + if *expire >= Instant::now() { + debug!(target: "sub-libp2p", "Ignoring banned peer {:?}", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); + return + } + } + } + + // Check the limits on the ingoing and outgoing connections. + match endpoint { + ConnectedPoint::Dialer { .. } => { + let num_outgoing = self.enabled_peers.iter() + .filter(|p| self.connected_peers.get(p).map(|c| c.is_dialer()).unwrap_or(false)) + .filter(|p| !self.reserved_peers.contains(p)) + .count(); + + debug_assert!(num_outgoing <= self.max_outgoing_connections); + if num_outgoing == self.max_outgoing_connections { + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); + return + } + } + ConnectedPoint::Listener { .. } => { + let num_ingoing = self.enabled_peers.iter() + .filter(|p| self.connected_peers.get(p).map(|c| c.is_listener()).unwrap_or(false)) + .filter(|p| !self.reserved_peers.contains(p)) + .count(); + + debug_assert!(num_ingoing <= self.max_incoming_connections); + if num_ingoing == self.max_incoming_connections { + debug!(target: "sub-libp2p", "Ignoring incoming connection from {:?} because \ + we're full", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Disable, + }); + return + } + } + } + + // If everything is fine, enable the node. + debug_assert!(!self.enabled_peers.contains(&peer_id)); + // We ask the handler to actively open substreams only if we are the dialer; otherwise + // the two nodes will race to be the first to open the unique allowed substream. + if endpoint.is_dialer() { + trace!(target: "sub-libp2p", "Enabling custom protocols with {:?} (active)", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Enable(Endpoint::Dialer), + }); + } else { + trace!(target: "sub-libp2p", "Enabling custom protocols with {:?} (passive)", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtosHandlerIn::Enable(Endpoint::Listener), + }); + } + + self.topology.set_connected(&peer_id, &endpoint); + self.enabled_peers.insert(peer_id); + } + + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + let was_connected = self.connected_peers.remove(&peer_id); + debug_assert!(was_connected.is_some()); + + self.topology.set_disconnected(peer_id, &endpoint); + + while let Some(pos) = self.open_protocols.iter().position(|(p, _)| p == peer_id) { + let (_, protocol_id) = self.open_protocols.remove(pos); + + let event = CustomProtosOut::CustomProtocolClosed { + protocol_id, + peer_id: peer_id.clone(), + result: Ok(()), + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + + self.enabled_peers.remove(peer_id); + } + + fn inject_dial_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { + if let Some(peer_id) = peer_id.as_ref() { + debug!(target: "sub-libp2p", "Failed to reach peer {:?} through {} => {:?}", peer_id, addr, error); + self.topology.set_unreachable(addr); + + // Trigger a `connect_to_nodes` round. + self.next_connect_to_nodes = Delay::new(Instant::now()); + + } else { + // This code path is only reached if `peer_id` is None, which means that we dialed an + // address without knowing the `PeerId` to expect. We don't currently do that, except + // in one situation: for convenience, we accept bootstrap node addresses in the format + // `IP:PORT`. + // There is no reason this trigger a `connect_to_nodes` round in that situation. + debug!(target: "sub-libp2p", "Failed to reach {} => {:?}", addr, error); + self.topology.set_unreachable(addr); + } + } + + fn inject_node_event( + &mut self, + source: PeerId, + event: ::OutEvent, + ) { + match event { + CustomProtosHandlerOut::CustomProtocolClosed { protocol_id, result } => { + let pos = self.open_protocols.iter().position(|(s, p)| + s == &source && p == &protocol_id + ); + + if let Some(pos) = pos { + self.open_protocols.remove(pos); + } else { + debug_assert!(false, "Couldn't find protocol in open_protocols"); + } + + let event = CustomProtosOut::CustomProtocolClosed { + protocol_id, + result, + peer_id: source, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + CustomProtosHandlerOut::CustomProtocolOpen { protocol_id, version } => { + debug_assert!(!self.open_protocols.iter().any(|(s, p)| + s == &source && p == &protocol_id + )); + self.open_protocols.push((source.clone(), protocol_id)); + + let endpoint = self.connected_peers.get(&source) + .expect("We only receive events from connected nodes; QED").clone(); + let event = CustomProtosOut::CustomProtocolOpen { + protocol_id, + version, + peer_id: source, + endpoint, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + CustomProtosHandlerOut::CustomMessage { protocol_id, message } => { + debug_assert!(self.open_protocols.iter().any(|(s, p)| + s == &source && p == &protocol_id + )); + let event = CustomProtosOut::CustomMessage { + peer_id: source, + protocol_id, + message, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + CustomProtosHandlerOut::Clogged { protocol_id, messages } => { + debug_assert!(self.open_protocols.iter().any(|(s, p)| + s == &source && p == &protocol_id + )); + warn!(target: "sub-libp2p", "Queue of packets to send to {:?} (protocol: {:?}) is \ + pretty large", source, protocol_id); + self.events.push(NetworkBehaviourAction::GenerateEvent(CustomProtosOut::Clogged { + peer_id: source, + protocol_id, + messages, + })); + } + CustomProtosHandlerOut::ProtocolError { protocol_id, error, is_severe } => { + if is_severe { + warn!(target: "sub-libp2p", "Network misbehaviour from {:?} with protocol \ + {:?}: {:?}", source, protocol_id, error); + self.ban_peer(source); + } else { + debug!(target: "sub-libp2p", "Network misbehaviour from {:?} with protocol \ + {:?}: {:?}", source, protocol_id, error); + self.disconnect_peer(&source); + } + } + } + } + + fn poll( + &mut self, + params: &mut PollParameters, + ) -> Async< + NetworkBehaviourAction< + ::InEvent, + Self::OutEvent, + >, + > { + loop { + match self.next_connect_to_nodes.poll() { + Ok(Async::Ready(())) => self.connect_to_nodes(params), + Ok(Async::NotReady) => break, + Err(err) => { + warn!(target: "sub-libp2p", "Connect-to-nodes timer errored: {:?}", err); + break + } + } + } + + // Clean up `banned_peers` + self.banned_peers.retain(|(_, end)| *end > Instant::now()); + self.banned_peers.shrink_to_fit(); + + if !self.events.is_empty() { + return Async::Ready(self.events.remove(0)) + } + + Async::NotReady + } +} diff --git a/core/network-libp2p/src/custom_proto/handler.rs b/core/network-libp2p/src/custom_proto/handler.rs new file mode 100644 index 0000000000000000000000000000000000000000..bb326923e14bfee5a1483b885dd01deece6007c9 --- /dev/null +++ b/core/network-libp2p/src/custom_proto/handler.rs @@ -0,0 +1,1028 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::ProtocolId; +use crate::custom_proto::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol, RegisteredProtocols}; +use crate::custom_proto::upgrade::{RegisteredProtocolEvent, RegisteredProtocolSubstream}; +use futures::prelude::*; +use libp2p::core::{ + Endpoint, ProtocolsHandler, ProtocolsHandlerEvent, + protocols_handler::KeepAlive, + protocols_handler::ProtocolsHandlerUpgrErr, + upgrade::{InboundUpgrade, OutboundUpgrade} +}; +use log::{debug, error, warn}; +use smallvec::{smallvec, SmallVec}; +use std::{error, fmt, io, mem, time::Duration, time::Instant}; +use tokio_io::{AsyncRead, AsyncWrite}; +use tokio_timer::Delay; +use void::Void; + +/// Implements the `ProtocolsHandler` trait of libp2p. +/// +/// Every time a connection with a remote is established, an instance of this struct is created and +/// sent to a background task dedicated to this connection. It handles all communications that are +/// specific to Substrate. +/// +/// Note that there can be multiple instance of this struct simultaneously for same peer. However +/// if that happens, only one main instance can communicate with the outer layers of the code. +/// +/// ## How it works +/// +/// For backwards compatibility reasons, the behaviour of the handler is quite complicated. After +/// enough nodes have upgraded, it should be simplified by using helpers provided by libp2p. +/// +/// When the handler is created, it is initially in the `Init` state and waits for either a +/// `Disable` or an `Enable` message from the outer layer. At any time, the outer layer is free to +/// toggle the handler between the disabled and enabled states. +/// +/// When the handler is enabled for the first time, if it is the dialer of the connection, it tries +/// to open a substream. The substream negotiates either a protocol named `/substrate/xxx` or a +/// protocol named `/substrate/multi/xxx`. If it is the former, then we are in +/// "backwards-compatibility mode". If it is the latter, we are in normal operation mode. +/// +/// In "backwards-compatibility mode", we have one unique substream where bidirectional +/// communications happen. If the remote closes the substream, we consider that we are now +/// disconnected. Re-enabling is performed by re-opening the substream. +/// +/// In normal operation mode, each request gets sent over a different substream where the response +/// is then sent back. If the remote refuses one of our substream open request, or if an error +/// happens on one substream, we consider that we are disconnected. Re-enabling is performed by +/// opening an outbound substream. +/// +pub struct CustomProtosHandler { + /// Fields individual to each protocol that we support. + protocols: SmallVec<[PerProtocol; 1]>, + + /// Queue of events to send to the outside. + /// + /// This queue must only ever be modified to insert elements at the back, or remove the first + /// element. + events_queue: SmallVec<[ProtocolsHandlerEvent, ProtocolId, CustomProtosHandlerOut>; 16]>, + + /// We have a warm-up period after creating the handler during which we don't shut down the + /// connection. + warm_up_end: Instant, +} + +/// Fields individual to each protocol that we support. +struct PerProtocol { + /// Configuration for the protocol upgrade to negotiate. + protocol: RegisteredProtocol, + + /// State of the communications with the remote. + state: PerProtocolState, +} + +/// State of the handler for a specific protocol. +enum PerProtocolState { + /// Waiting for the behaviour to tell the handler whether it is enabled or disabled. + Init { + /// List of substreams opened by the remote but that haven't been processed yet. + substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, + /// Deadline after which the initialization is abnormally long. + init_deadline: Delay, + }, + + /// Handler is opening a substream in order to activate itself. + /// If we are in this state, we haven't sent any `CustomProtocolOpen` yet. + Opening { + /// Deadline after which the opening is abnormally long. + deadline: Delay, + }, + + /// Backwards-compatible mode. Contains the unique substream that is open. + /// If we are in this state, we have sent a `CustomProtocolOpen` message to the outside. + BackCompat { + /// The unique substream where bidirectional communications happen. + substream: RegisteredProtocolSubstream, + /// Contains substreams which are being shut down. + shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, + }, + + /// Normal functionning. Contains the substreams that are open. + /// If we are in this state, we have sent a `CustomProtocolOpen` message to the outside. + Normal(PerProtocolNormalState), + + /// We are disabled. Contains substreams that are being closed. + /// If we are in this state, either we have sent a `CustomProtocolClosed` message to the + /// outside or we have never sent any `CustomProtocolOpen` in the first place. + Disabled { + /// List of substreams to shut down. + shutdown: SmallVec<[RegisteredProtocolSubstream; 6]>, + + /// If true, we should reactivate the handler after all the substreams in `shutdown` have + /// been closed. + /// + /// Since we don't want to mix old and new substreams, we wait for all old substreams to + /// be closed before opening any new one. + reenable: bool, + }, + + /// We are trying to shut down the connection and thus should refuse any incoming connection. + /// Contains substreams that are being closed. Once all the substreams are closed, we close + /// the connection. + ShuttingDown(SmallVec<[RegisteredProtocolSubstream; 6]>), + + /// We sometimes temporarily switch to this state during processing. If we are in this state + /// at the beginning of a method, that means something bad happend in the source code. + Poisoned, +} + +/// Normal functionning mode for a protocol. +struct PerProtocolNormalState { + /// Optional substream that we opened. + outgoing_substream: Option>, + + /// Substreams that have been opened by the remote. We are waiting for a packet from it. + incoming_substreams: SmallVec<[RegisteredProtocolSubstream; 4]>, + + /// For each request that has been sent to the remote, contains the substream where we + /// expect a response. + pending_response: SmallVec<[(u64, RegisteredProtocolSubstream); 4]>, + + /// For each request received by the remote, contains the substream where to send back our + /// response. Once a response has been sent, the substream closes. + pending_send_back: SmallVec<[(u64, RegisteredProtocolSubstream); 4]>, + + /// List of messages waiting for a substream to open in order to be sent. + pending_messages: SmallVec<[TMessage; 6]>, + + /// Contains substreams which are being shut down. + shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, +} + +impl PerProtocol +where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { + /// Enables the protocol. Returns an optional event to emit. + /// Must be passed the endpoint of the connection. + #[must_use] + fn enable(&mut self, endpoint: Endpoint) + -> Option, ProtocolId, CustomProtosHandlerOut>> { + + let return_value; + + self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { + PerProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler is in poisoned state"); + return_value = None; + PerProtocolState::Poisoned + } + + PerProtocolState::Init { substreams: incoming, .. } => { + if incoming.is_empty() { + if let Endpoint::Dialer = endpoint { + return_value = Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: self.protocol.clone(), + info: self.protocol.id(), + }); + } else { + return_value = None; + } + PerProtocolState::Opening { + deadline: Delay::new(Instant::now() + Duration::from_secs(60)) + } + + } else if incoming.iter().any(|s| s.is_multiplex()) { + let event = CustomProtosHandlerOut::CustomProtocolOpen { + protocol_id: self.protocol.id(), + version: incoming[0].protocol_version() + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::Normal(PerProtocolNormalState { + outgoing_substream: None, + incoming_substreams: incoming.into_iter().collect(), + pending_response: SmallVec::new(), + pending_send_back: SmallVec::new(), + pending_messages: SmallVec::new(), + shutdown: SmallVec::new(), + }) + + } else { + let event = CustomProtosHandlerOut::CustomProtocolOpen { + protocol_id: self.protocol.id(), + version: incoming[0].protocol_version() + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::BackCompat { + substream: incoming.into_iter().next() + .expect("We have a check above that incoming isn't empty; QED"), + shutdown: SmallVec::new() + } + } + } + + st @ PerProtocolState::Opening { .. } => { return_value = None; st } + st @ PerProtocolState::BackCompat { .. } => { return_value = None; st } + st @ PerProtocolState::Normal { .. } => { return_value = None; st } + PerProtocolState::Disabled { shutdown, .. } => { + return_value = None; + PerProtocolState::Disabled { shutdown, reenable: true } + } + PerProtocolState::ShuttingDown(list) => { + return_value = None; + PerProtocolState::ShuttingDown(list) + } + }; + + return_value + } + + /// Disables the protocol. Returns `true` if the protocol was closed, `false` if it was already + /// closed or not open yet. + fn disable(&mut self) -> bool { + let mut return_value = false; + + self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { + PerProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler is in poisoned state"); + PerProtocolState::Poisoned + } + + PerProtocolState::Init { substreams: mut shutdown, .. } => { + for s in &mut shutdown { + s.shutdown(); + } + PerProtocolState::Disabled { shutdown, reenable: false } + } + + PerProtocolState::Opening { .. } => { + PerProtocolState::Disabled { shutdown: SmallVec::new(), reenable: false } + } + + PerProtocolState::BackCompat { mut substream, mut shutdown } => { + substream.shutdown(); + shutdown.push(substream); + return_value = true; + PerProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + + PerProtocolState::Normal(state) => { + let mut out: SmallVec<[_; 6]> = SmallVec::new(); + out.extend(state.outgoing_substream.into_iter()); + out.extend(state.incoming_substreams.into_iter()); + out.extend(state.pending_response.into_iter().map(|(_, s)| s)); + out.extend(state.pending_send_back.into_iter().map(|(_, s)| s)); + for s in &mut out { + s.shutdown(); + } + out.extend(state.shutdown.into_iter()); + return_value = true; + PerProtocolState::Disabled { shutdown: out, reenable: false } + } + + PerProtocolState::Disabled { shutdown, .. } => + PerProtocolState::Disabled { shutdown, reenable: false }, + PerProtocolState::ShuttingDown(list) => + PerProtocolState::ShuttingDown(list), + }; + + return_value + } + + /// Shuts down all the substream. Returns `true` if the protocol was closed, `false` if it was + /// already closed or not open yet. + fn shutdown(&mut self) -> bool { + let mut return_value = false; + self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { + PerProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler is in poisoned state"); + PerProtocolState::Poisoned + } + + PerProtocolState::Init { substreams: mut list, .. } => { + for s in &mut list { s.shutdown(); } + PerProtocolState::ShuttingDown(list) + } + + PerProtocolState::Opening { .. } => { + PerProtocolState::ShuttingDown(SmallVec::new()) + } + + PerProtocolState::BackCompat { mut substream, mut shutdown } => { + substream.shutdown(); + shutdown.push(substream); + return_value = true; + PerProtocolState::ShuttingDown(shutdown.into_iter().collect()) + } + + PerProtocolState::Normal(state) => { + let mut out: SmallVec<[_; 6]> = SmallVec::new(); + out.extend(state.outgoing_substream.into_iter()); + out.extend(state.incoming_substreams.into_iter()); + out.extend(state.pending_response.into_iter().map(|(_, s)| s)); + out.extend(state.pending_send_back.into_iter().map(|(_, s)| s)); + for s in &mut out { + s.shutdown(); + } + out.extend(state.shutdown.into_iter()); + return_value = true; + PerProtocolState::ShuttingDown(out) + } + + PerProtocolState::Disabled { shutdown, .. } => + PerProtocolState::ShuttingDown(shutdown), + PerProtocolState::ShuttingDown(list) => + PerProtocolState::ShuttingDown(list), + }; + return_value + } + + /// Polls the state for events. Optionally returns an event to produce. + #[must_use] + fn poll(&mut self) + -> Option, ProtocolId, CustomProtosHandlerOut>> { + + let return_value; + self.state = match mem::replace(&mut self.state, PerProtocolState::Poisoned) { + PerProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler is in poisoned state; shutting down"); + return_value = Some(ProtocolsHandlerEvent::Shutdown); + PerProtocolState::Poisoned + } + + PerProtocolState::Init { substreams, mut init_deadline } => { + match init_deadline.poll() { + Ok(Async::Ready(())) => + error!(target: "sub-libp2p", "Handler initialization process is too long"), + Ok(Async::NotReady) => {} + Err(_) => error!(target: "sub-libp2p", "Tokio timer has errored") + } + + return_value = None; + PerProtocolState::Init { substreams, init_deadline } + } + + PerProtocolState::Opening { mut deadline } => { + match deadline.poll() { + Ok(Async::Ready(())) => { + deadline.reset(Instant::now() + Duration::from_secs(60)); + let event = CustomProtosHandlerOut::ProtocolError { + protocol_id: self.protocol.id(), + is_severe: false, + error: "Timeout when opening protocol".to_string().into(), + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::Opening { deadline } + }, + Ok(Async::NotReady) => { + return_value = None; + PerProtocolState::Opening { deadline } + }, + Err(_) => { + error!(target: "sub-libp2p", "Tokio timer has errored"); + deadline.reset(Instant::now() + Duration::from_secs(60)); + return_value = None; + PerProtocolState::Opening { deadline } + }, + } + } + + PerProtocolState::BackCompat { mut substream, shutdown } => { + match substream.poll() { + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { + let event = CustomProtosHandlerOut::CustomMessage { + protocol_id: substream.protocol_id(), + message + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::BackCompat { substream, shutdown } + }, + Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages }))) => { + let event = CustomProtosHandlerOut::Clogged { + protocol_id: substream.protocol_id(), + messages, + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::BackCompat { substream, shutdown } + } + Ok(Async::NotReady) => { + return_value = None; + PerProtocolState::BackCompat { substream, shutdown } + } + Ok(Async::Ready(None)) => { + let event = CustomProtosHandlerOut::CustomProtocolClosed { + protocol_id: substream.protocol_id(), + result: Ok(()) + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + Err(err) => { + let event = CustomProtosHandlerOut::CustomProtocolClosed { + protocol_id: substream.protocol_id(), + result: Err(err), + }; + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + PerProtocolState::Disabled { + shutdown: shutdown.into_iter().collect(), + reenable: false + } + } + } + } + + PerProtocolState::Normal(mut norm_state) => { + if let Some(event) = norm_state.poll(self.protocol.id()) { + return_value = Some(ProtocolsHandlerEvent::Custom(event)); + } else { + return_value = None; + } + + PerProtocolState::Normal(norm_state) + } + + PerProtocolState::Disabled { mut shutdown, reenable } => { + shutdown_list(&mut shutdown); + // If `reenable` is `true`, that means we should open the substreams system again + // after all the substreams are closed. + if reenable && shutdown.is_empty() { + return_value = Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: self.protocol.clone(), + info: self.protocol.id(), + }); + PerProtocolState::Opening { + deadline: Delay::new(Instant::now() + Duration::from_secs(60)) + } + } else { + return_value = None; + PerProtocolState::Disabled { shutdown, reenable } + } + } + + PerProtocolState::ShuttingDown(mut list) => { + shutdown_list(&mut list); + return_value = None; + PerProtocolState::ShuttingDown(list) + } + }; + + return_value + } +} + +impl PerProtocolNormalState +where TMessage: CustomMessage, TSubstream: AsyncRead + AsyncWrite { + /// Polls for things that are new. Same API constraints as `Future::poll()`. + /// Optionally returns the event to produce. + /// You must pass the `protocol_id` as we need have to inject it in the returned event. + /// API note: Ideally we wouldn't need to be passed a `ProtocolId`, and we would return a + /// different enum that doesn't contain any `protocol_id`, and the caller would inject + /// the ID itself, but that's a ton of code for not much gain. + fn poll(&mut self, protocol_id: ProtocolId) -> Option> { + for n in (0..self.pending_response.len()).rev() { + let (request_id, mut substream) = self.pending_response.swap_remove(n); + match substream.poll() { + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { + if message.request_id() == CustomMessageId::Response(request_id) { + let event = CustomProtosHandlerOut::CustomMessage { + protocol_id: substream.protocol_id(), + message + }; + self.shutdown.push(substream); + return Some(event); + } else { + self.shutdown.push(substream); + let event = CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe: true, + error: format!("Request ID doesn't match substream: expected {:?}, \ + got {:?}", request_id, message.request_id()).into(), + }; + return Some(event); + } + }, + Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { .. }))) => + unreachable!("Cannot receive Clogged message with new protocol version; QED"), + Ok(Async::NotReady) => + self.pending_response.push((request_id, substream)), + Ok(Async::Ready(None)) => { + self.shutdown.push(substream); + let event = CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe: false, + error: format!("Request ID {:?} didn't receive an answer", request_id).into(), + }; + return Some(event); + } + Err(err) => { + self.shutdown.push(substream); + let event = CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe: false, + error: format!("Error while waiting for an answer for {:?}: {}", + request_id, err).into(), + }; + return Some(event); + } + } + } + + for n in (0..self.incoming_substreams.len()).rev() { + let mut substream = self.incoming_substreams.swap_remove(n); + match substream.poll() { + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { + let protocol_id = substream.protocol_id(); + if let CustomMessageId::Request(id) = message.request_id() { + self.pending_send_back.push((id, substream)); + return Some(CustomProtosHandlerOut::CustomMessage { + protocol_id, + message + }); + } else if let CustomMessageId::OneWay = message.request_id() { + self.shutdown.push(substream); + return Some(CustomProtosHandlerOut::CustomMessage { + protocol_id, + message + }); + } else { + self.shutdown.push(substream); + return Some(CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe: true, + error: format!("Received response in new substream").into(), + }); + } + }, + Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { .. }))) => + unreachable!("Cannot receive Clogged message with new protocol version; QED"), + Ok(Async::NotReady) => + self.incoming_substreams.push(substream), + Ok(Async::Ready(None)) => {} + Err(err) => { + self.shutdown.push(substream); + return Some(CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe: false, + error: format!("Error in incoming substream: {}", err).into(), + }); + } + } + } + + shutdown_list(&mut self.shutdown); + None + } +} + +/// Event that can be received by a `CustomProtosHandler`. +#[derive(Debug)] +pub enum CustomProtosHandlerIn { + /// The node should start using custom protocols. Contains whether we are the dialer or the + /// listener of the connection. + Enable(Endpoint), + + /// The node should stop using custom protocols. + Disable, + + /// Sends a message through a custom protocol substream. + SendCustomMessage { + /// The protocol to use. + protocol: ProtocolId, + /// The message to send. + message: TMessage, + }, +} + +/// Event that can be emitted by a `CustomProtosHandler`. +#[derive(Debug)] +pub enum CustomProtosHandlerOut { + /// Opened a custom protocol with the remote. + CustomProtocolOpen { + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Version of the protocol that has been opened. + version: u8, + }, + + /// Closed a custom protocol with the remote. + CustomProtocolClosed { + /// Identifier of the protocol. + protocol_id: ProtocolId, + /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). + result: io::Result<()>, + }, + + /// Receives a message on a custom protocol substream. + CustomMessage { + /// Protocol which generated the message. + protocol_id: ProtocolId, + /// Message that has been received. + message: TMessage, + }, + + /// A substream to the remote is clogged. The send buffer is very large, and we should print + /// a diagnostic message and/or avoid sending more data. + Clogged { + /// Protocol which is clogged. + protocol_id: ProtocolId, + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec, + }, + + /// An error has happened on the protocol level with this node. + ProtocolError { + /// Protocol for which the error happened. + protocol_id: ProtocolId, + /// If true the error is severe, such as a protocol violation. + is_severe: bool, + /// The error that happened. + error: Box, + }, +} + +impl CustomProtosHandler +where + TSubstream: AsyncRead + AsyncWrite, + TMessage: CustomMessage, +{ + /// Builds a new `CustomProtosHandler`. + pub fn new(protocols: RegisteredProtocols) -> Self { + CustomProtosHandler { + protocols: protocols.0.into_iter().map(|protocol| { + PerProtocol { + protocol, + state: PerProtocolState::Init { + substreams: SmallVec::new(), + init_deadline: Delay::new(Instant::now() + Duration::from_secs(5)) + }, + } + }).collect(), + events_queue: SmallVec::new(), + warm_up_end: Instant::now() + Duration::from_secs(5), + } + } + + /// Enables the handler for all protocols. + fn enable(&mut self, endpoint: Endpoint) { + for protocol in &mut self.protocols { + if let Some(message) = protocol.enable(endpoint) { + self.events_queue.push(message); + } + } + } + + /// Disables the handler for all protocols. + fn disable(&mut self) { + for protocol in &mut self.protocols { + if protocol.disable() { + let event = CustomProtosHandlerOut::CustomProtocolClosed { + protocol_id: protocol.protocol.id(), + result: Ok(()) + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + } + } + } + + /// Called by `inject_fully_negotiated_inbound` and `inject_fully_negotiated_outbound`. + fn inject_fully_negotiated( + &mut self, + mut substream: RegisteredProtocolSubstream + ) { + let state = match self.protocols.iter_mut().find(|p| p.protocol.id() == substream.protocol_id()) { + Some(p) => &mut p.state, + None => { + error!(target: "sub-libp2p", "Found unknown protocol ID {:?}", + substream.protocol_id()); + return + }, + }; + + *state = match mem::replace(state, PerProtocolState::Poisoned) { + PerProtocolState::Poisoned => { + error!(target: "sub-libp2p", "Handler is in poisoned state"); + PerProtocolState::Poisoned + } + + PerProtocolState::Init { mut substreams, init_deadline } => { + if substream.endpoint() == Endpoint::Dialer { + error!(target: "sub-libp2p", "Opened dialing substream before initialization"); + } + substreams.push(substream); + PerProtocolState::Init { substreams, init_deadline } + } + + PerProtocolState::Opening { .. } => { + let event = CustomProtosHandlerOut::CustomProtocolOpen { + protocol_id: substream.protocol_id(), + version: substream.protocol_version() + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + + match (substream.endpoint(), substream.is_multiplex()) { + (Endpoint::Dialer, true) => { + PerProtocolState::Normal(PerProtocolNormalState { + outgoing_substream: Some(substream), + incoming_substreams: SmallVec::new(), + pending_response: SmallVec::new(), + pending_send_back: SmallVec::new(), + pending_messages: SmallVec::new(), + shutdown: SmallVec::new(), + }) + }, + (Endpoint::Listener, true) => { + PerProtocolState::Normal(PerProtocolNormalState { + outgoing_substream: None, + incoming_substreams: smallvec![substream], + pending_response: SmallVec::new(), + pending_send_back: SmallVec::new(), + pending_messages: SmallVec::new(), + shutdown: SmallVec::new(), + }) + }, + (_, false) => { + PerProtocolState::BackCompat { + substream, + shutdown: SmallVec::new() + } + }, + } + } + + PerProtocolState::BackCompat { substream: existing, mut shutdown } => { + warn!(target: "sub-libp2p", "Received extra substream after having already one \ + open in backwards-compatibility mode"); + substream.shutdown(); + shutdown.push(substream); + PerProtocolState::BackCompat { substream: existing, shutdown } + } + + PerProtocolState::Normal(mut state) => { + if substream.endpoint() == Endpoint::Listener { + state.incoming_substreams.push(substream); + } else if !state.pending_messages.is_empty() { + let message = state.pending_messages.remove(0); + let request_id = message.request_id(); + substream.send_message(message); + if let CustomMessageId::Request(request_id) = request_id { + state.pending_response.push((request_id, substream)); + } else { + state.shutdown.push(substream); + } + } else { + debug!(target: "sub-libp2p", "Opened spurious outbound substream"); + substream.shutdown(); + state.shutdown.push(substream); + } + + PerProtocolState::Normal(state) + } + + PerProtocolState::Disabled { mut shutdown, .. } => { + substream.shutdown(); + shutdown.push(substream); + PerProtocolState::Disabled { shutdown, reenable: false } + } + + PerProtocolState::ShuttingDown(mut list) => { + substream.shutdown(); + list.push(substream); + PerProtocolState::ShuttingDown(list) + } + }; + } + + /// Sends a message to the remote. + fn send_message(&mut self, protocol: ProtocolId, message: TMessage) { + let (protocol, state) = match self.protocols.iter_mut().find(|p| p.protocol.id() == protocol) { + Some(p) => (&mut p.protocol, &mut p.state), + None => { + error!(target: "sub-libp2p", "Tried to send message over unknown protocol ID {:?}", + protocol); + return + }, + }; + + match *state { + PerProtocolState::BackCompat { ref mut substream, .. } => + substream.send_message(message), + + PerProtocolState::Normal(ref mut state) => { + if let CustomMessageId::Request(request_id) = message.request_id() { + if let Some(mut outgoing_substream) = state.outgoing_substream.take() { + outgoing_substream.send_message(message); + state.pending_response.push((request_id, outgoing_substream)); + } else { + if state.pending_messages.len() >= 2048 { + let event = CustomProtosHandlerOut::Clogged { + messages: Vec::new(), + protocol_id: protocol.id() + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + } + state.pending_messages.push(message); + self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: protocol.clone(), + info: protocol.id() + }); + } + } else if let CustomMessageId::Response(request_id) = message.request_id() { + if let Some(pos) = state.pending_send_back.iter().position(|(id, _)| *id == request_id) { + let (_, mut substream) = state.pending_send_back.remove(pos); + substream.send_message(message); + state.shutdown.push(substream); + } else { + warn!(target: "sub-libp2p", "Libp2p layer received response to a \ + non-existing request ID {:?}", request_id); + } + } else if let Some(mut outgoing_substream) = state.outgoing_substream.take() { + outgoing_substream.send_message(message); + state.shutdown.push(outgoing_substream); + } else { + if state.pending_messages.len() >= 2048 { + let event = CustomProtosHandlerOut::Clogged { + messages: Vec::new(), + protocol_id: protocol.id() + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + } + state.pending_messages.push(message); + self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest { + upgrade: protocol.clone(), + info: protocol.id() + }); + } + } + + _ => debug!(target: "sub-libp2p", "Tried to send message over closed protocol") + } + } +} + +impl ProtocolsHandler for CustomProtosHandler +where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { + type InEvent = CustomProtosHandlerIn; + type OutEvent = CustomProtosHandlerOut; + type Substream = TSubstream; + type Error = Void; + type InboundProtocol = RegisteredProtocols; + type OutboundProtocol = RegisteredProtocol; + type OutboundOpenInfo = ProtocolId; + + #[inline] + fn listen_protocol(&self) -> Self::InboundProtocol { + RegisteredProtocols(self.protocols.iter().map(|p| p.protocol.clone()).collect()) + } + + fn inject_fully_negotiated_inbound( + &mut self, + proto: >::Output + ) { + self.inject_fully_negotiated(proto); + } + + #[inline] + fn inject_fully_negotiated_outbound( + &mut self, + proto: >::Output, + _: Self::OutboundOpenInfo + ) { + self.inject_fully_negotiated(proto); + } + + fn inject_event(&mut self, message: CustomProtosHandlerIn) { + match message { + CustomProtosHandlerIn::Disable => self.disable(), + CustomProtosHandlerIn::Enable(endpoint) => self.enable(endpoint), + CustomProtosHandlerIn::SendCustomMessage { protocol, message } => + self.send_message(protocol, message), + } + } + + #[inline] + fn inject_inbound_closed(&mut self) {} + + #[inline] + fn inject_dial_upgrade_error(&mut self, protocol_id: Self::OutboundOpenInfo, err: ProtocolsHandlerUpgrErr) { + let is_severe = match err { + ProtocolsHandlerUpgrErr::Upgrade(_) => true, + _ => false, + }; + + self.events_queue.push(ProtocolsHandlerEvent::Custom(CustomProtosHandlerOut::ProtocolError { + protocol_id, + is_severe, + error: Box::new(err), + })); + + // If we failed to open a substream, there is little chance that we manage to open any + // other substream ever again on this connection, and thus we disable the handler. + self.disable(); + } + + fn connection_keep_alive(&self) -> KeepAlive { + if self.warm_up_end >= Instant::now() { + return KeepAlive::Until(self.warm_up_end) + } + + let mut keep_forever = false; + + for protocol in self.protocols.iter() { + match protocol.state { + PerProtocolState::Init { .. } | PerProtocolState::Opening { .. } => {} + PerProtocolState::BackCompat { .. } | PerProtocolState::Normal { .. } => + keep_forever = true, + PerProtocolState::Disabled { .. } | PerProtocolState::ShuttingDown(_) | + PerProtocolState::Poisoned => return KeepAlive::Now, + } + } + + if keep_forever { + KeepAlive::Forever + } else { + KeepAlive::Now + } + } + + fn shutdown(&mut self) { + for protocol in &mut self.protocols { + if protocol.shutdown() { + let event = CustomProtosHandlerOut::CustomProtocolClosed { + protocol_id: protocol.protocol.id(), + result: Ok(()) + }; + self.events_queue.push(ProtocolsHandlerEvent::Custom(event)); + } + } + } + + fn poll( + &mut self, + ) -> Poll< + ProtocolsHandlerEvent, + Self::Error, + > { + // Flush the events queue if necessary. + if !self.events_queue.is_empty() { + let event = self.events_queue.remove(0); + return Ok(Async::Ready(event)) + } + + // Process all the substreams. + for protocol in self.protocols.iter_mut() { + if let Some(event) = protocol.poll() { + return Ok(Async::Ready(event)) + } + } + + // Shut down the node if everything is closed. + let can_shut_down = self.protocols.iter().all(|p| + match p.state { + PerProtocolState::ShuttingDown(ref list) if list.is_empty() => true, + _ => false + }); + if can_shut_down { + return Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) + } + + Ok(Async::NotReady) + } +} + +impl fmt::Debug for CustomProtosHandler +where + TSubstream: AsyncRead + AsyncWrite, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.debug_struct("CustomProtosHandler") + .finish() + } +} + +/// Given a list of substreams, tries to shut them down. The substreams that have been successfully +/// shut down are removed from the list. +fn shutdown_list + (list: &mut SmallVec>>) +where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { + 'outer: for n in (0..list.len()).rev() { + let mut substream = list.swap_remove(n); + loop { + match substream.poll() { + Ok(Async::Ready(Some(_))) => {} + Ok(Async::NotReady) => break, + Err(_) | Ok(Async::Ready(None)) => continue 'outer, + } + } + list.push(substream); + } +} diff --git a/core/network-libp2p/src/custom_proto/mod.rs b/core/network-libp2p/src/custom_proto/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..073ce8360aeea9137ec356108fea24f6a6b654c1 --- /dev/null +++ b/core/network-libp2p/src/custom_proto/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub use self::behaviour::{CustomProtos, CustomProtosOut}; +pub use self::upgrade::{CustomMessage, CustomMessageId, RegisteredProtocol, RegisteredProtocols}; + +mod behaviour; +mod handler; +mod topology; +mod upgrade; diff --git a/core/network-libp2p/src/topology.rs b/core/network-libp2p/src/custom_proto/topology.rs similarity index 65% rename from core/network-libp2p/src/topology.rs rename to core/network-libp2p/src/custom_proto/topology.rs index 061a3d1795687476a6c83f064fd83e779ade2a10..4e498c560c02fa77eaa9c464b6ba4c802c97981d 100644 --- a/core/network-libp2p/src/topology.rs +++ b/core/network-libp2p/src/custom_proto/topology.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,9 +15,9 @@ // along with Substrate. If not, see .? use fnv::FnvHashMap; -use parking_lot::Mutex; -use libp2p::{Multiaddr, PeerId}; -use serde_json; +use libp2p::{core::swarm::ConnectedPoint, Multiaddr, PeerId}; +use log::{debug, info, trace, warn}; +use serde_derive::{Serialize, Deserialize}; use std::{cmp, fs}; use std::io::{Read, Cursor, Error as IoError, ErrorKind as IoErrorKind, Write, BufReader, BufWriter}; use std::path::{Path, PathBuf}; @@ -46,8 +46,6 @@ const KADEMLIA_DISCOVERY_EXPIRATION: Duration = Duration::from_secs(2 * 3600); const EXPIRATION_PUSH_BACK_CONNEC: Duration = Duration::from_secs(2 * 3600); /// Initial score that a bootstrap node receives when registered. const BOOTSTRAP_NODE_SCORE: u32 = 100; -/// Score modifier to apply on a peer that has been determined to be useless. -const USELESS_PEER_SCORE_CHANGE: i32 = -9; /// Time to live of a boostrap node. This only applies if you start the node later *without* /// that bootstrap node configured anymore. const BOOTSTRAP_NODE_EXPIRATION: Duration = Duration::from_secs(24 * 3600); @@ -58,20 +56,15 @@ const FAIL_BACKOFF_MULTIPLIER: u32 = 2; /// We need a maximum value for the backoff, overwise we risk an overflow. const MAX_BACKOFF: Duration = Duration::from_secs(30 * 60); -// TODO: should be merged with the Kademlia k-buckets - /// Stores information about the topology of the network. #[derive(Debug)] pub struct NetTopology { + /// The actual storage. Never contains a key for `local_peer_id`. store: FnvHashMap, + /// Optional path to the file that caches the serialized version of `store`. cache_path: Option, -} - -impl Default for NetTopology { - #[inline] - fn default() -> NetTopology { - NetTopology::memory() - } + /// PeerId of the local node. + local_peer_id: PeerId, } impl NetTopology { @@ -79,10 +72,11 @@ impl NetTopology { /// /// `flush_to_disk()` will be a no-op. #[inline] - pub fn memory() -> NetTopology { + pub fn memory(local_peer_id: PeerId) -> NetTopology { NetTopology { store: Default::default(), cache_path: None, + local_peer_id, } } @@ -92,19 +86,21 @@ impl NetTopology { /// or contains garbage data, the execution still continues. /// /// Calling `flush_to_disk()` in the future writes to the given path. - pub fn from_file>(path: P) -> NetTopology { + pub fn from_file>(local_peer_id: PeerId, path: P) -> NetTopology { let path = path.as_ref(); debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); + let store = try_load(path, &local_peer_id); NetTopology { - store: try_load(path), + store, cache_path: Some(path.to_owned()), + local_peer_id, } } /// Writes the topology into the path passed to `from_file`. /// /// No-op if the object was created with `memory()`. - pub fn flush_to_disk(&self) -> Result<(), IoError> { + pub fn flush_to_disk(&mut self) -> Result<(), IoError> { let path = match self.cache_path { Some(ref p) => p, None => return Ok(()) @@ -112,10 +108,10 @@ impl NetTopology { let file = fs::File::create(path)?; // TODO: the capacity of the BufWriter is kind of arbitrary ; decide better - serialize(BufWriter::with_capacity(1024 * 1024, file), &self.store) + serialize(BufWriter::with_capacity(1024 * 1024, file), &mut self.store) } - /// Returns the number of peers in the topology. + /// Returns the number of peers in the topology, excluding the local peer. #[inline] pub fn num_peers(&self) -> usize { self.store.len() @@ -127,42 +123,15 @@ impl NetTopology { pub fn cleanup(&mut self) { let now_systime = SystemTime::now(); self.store.retain(|_, peer| { - peer.addrs.retain(|a| { - a.expires > now_systime || a.is_connected() - }); + let new_addrs = peer.addrs + .drain(..) + .filter(|a| a.expires > now_systime || a.is_connected()) + .collect(); + peer.addrs = new_addrs; !peer.addrs.is_empty() }); } - /// Returns the known potential addresses of a peer, ordered by score. Excludes backed-off - /// addresses. - /// - /// The boolean associated to each address indicates whether we're connected to it. - pub fn addrs_of_peer(&self, peer: &PeerId) -> impl Iterator { - let peer = if let Some(peer) = self.store.get(peer) { - peer - } else { - // TODO: use an EitherIterator or something - return Vec::new().into_iter(); - }; - - let now_st = SystemTime::now(); - let now_is = Instant::now(); - - let mut list = peer.addrs.iter().filter_map(move |addr| { - let (score, connected) = addr.score_and_is_connected(); - if (addr.expires >= now_st && score > 0 && addr.back_off_until < now_is) || connected { - Some((score, connected, &addr.addr)) - } else { - None - } - }).collect::>(); - list.sort_by(|a, b| a.0.cmp(&b.0)); - // TODO: meh, optimize - let l = list.into_iter().map(|(_, connec, addr)| (addr, connec)).collect::>(); - l.into_iter() - } - /// Returns a list of all the known addresses of peers, ordered by the /// order in which we should attempt to connect to them. /// @@ -170,7 +139,7 @@ impl NetTopology { /// by itself over time. The `Instant` that is returned corresponds to /// the earlier known time when a new entry will be added automatically to /// the list. - pub fn addrs_to_attempt(&self) -> (impl Iterator, Instant) { + pub fn addrs_to_attempt(&mut self) -> (impl Iterator, Instant) { // TODO: optimize let now = Instant::now(); let now_systime = SystemTime::now(); @@ -179,20 +148,20 @@ impl NetTopology { let mut peer_addrs = Vec::new(); - 'peer_loop: for (peer, info) in &self.store { + 'peer_loop: for (peer, info) in &mut self.store { peer_addrs.clear(); - for addr in &info.addrs { + for addr in &mut info.addrs { let (score, is_connected) = addr.score_and_is_connected(); if is_connected { - continue 'peer_loop; + continue 'peer_loop } if score == 0 || addr.expires < now_systime { - continue; + continue } if addr.back_off_until > now { instant = cmp::min(instant, addr.back_off_until); - continue; + continue } peer_addrs.push(((peer, &addr.addr), score)); @@ -211,21 +180,29 @@ impl NetTopology { /// /// We assume that the address is valid, so its score starts very high. pub fn add_bootstrap_addr(&mut self, peer: &PeerId, addr: Multiaddr) { + if *peer == self.local_peer_id { + return + } + let now_systime = SystemTime::now(); let now = Instant::now(); let peer = peer_access(&mut self.store, peer); let mut found = false; - peer.addrs.retain(|a| { - if a.expires < now_systime && !a.is_connected() { - return false; - } - if a.addr == addr { - found = true; - } - true - }); + let new_addrs = peer.addrs + .drain(..) + .filter_map(|a| { + if a.expires < now_systime && !a.is_connected() { + return None + } + if a.addr == addr { + found = true; + } + Some(a) + }) + .collect(); + peer.addrs = new_addrs; if !found { peer.addrs.push(Addr { @@ -233,78 +210,57 @@ impl NetTopology { expires: now_systime + BOOTSTRAP_NODE_EXPIRATION, back_off_until: now, next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: Mutex::new(AddrScore { + score: AddrScore { connected_since: None, score: BOOTSTRAP_NODE_SCORE, latest_score_update: now, - }), + }, }); } } - /// Adds addresses that a node says it is listening on. - /// - /// The addresses are most likely to be valid. + /// Indicates the topology that we have discovered new addresses for a given node. /// /// Returns `true` if the topology has changed in some way. Returns `false` if calling this /// method was a no-op. - #[inline] - pub fn add_self_reported_listen_addrs( - &mut self, - peer_id: &PeerId, - addrs: I, - ) -> bool - where I: Iterator { - self.add_discovered_addrs(peer_id, addrs.map(|a| (a, true))) - } - - /// Adds addresses discovered through the Kademlia DHT. - /// - /// The addresses are not necessarily valid and should expire after a TTL. - /// - /// For each address, incorporates a boolean. If true, that means we have some sort of hint - /// that this address can be reached. - /// - /// Returns `true` if the topology has changed in some way. Returns `false` if calling this - /// method was a no-op. - #[inline] - pub fn add_kademlia_discovered_addrs( + pub fn add_discovered_addrs( &mut self, peer_id: &PeerId, addrs: I, ) -> bool where I: Iterator { - self.add_discovered_addrs(peer_id, addrs) - } + if *peer_id == self.local_peer_id { + return false + } - /// Inner implementaiton of the `add_*_discovered_addrs` methods. - /// Returns `true` if the topology has changed in some way. Returns `false` if calling this - /// method was a no-op. - fn add_discovered_addrs( - &mut self, - peer_id: &PeerId, - addrs: I, - ) -> bool - where I: Iterator { let mut addrs: Vec<_> = addrs.collect(); + + if addrs.len() > 40 { + warn!(target: "sub-libp2p", "Attempt to add more than 40 addresses for {:?}", peer_id); + addrs.truncate(40); + } + let now_systime = SystemTime::now(); let now = Instant::now(); let peer = peer_access(&mut self.store, peer_id); - peer.addrs.retain(|a| { - if a.expires < now_systime && !a.is_connected() { - return false; - } - if let Some(pos) = addrs.iter().position(|&(ref addr, _)| addr == &a.addr) { - addrs.remove(pos); - } - true - }); + let new_addrs = peer.addrs + .drain(..) + .filter(|a| { + if a.expires < now_systime && !a.is_connected() { + return false + } + addrs.retain(|(addr, _)| *addr != a.addr); + true + }) + .collect(); + peer.addrs = new_addrs; let mut anything_changed = false; if !addrs.is_empty() { + anything_changed = true; trace!( target: "sub-libp2p", "Peer store: adding addresses {:?} for {:?}", @@ -322,7 +278,7 @@ impl NetTopology { // Enforce `MAX_ADDRESSES_PER_PEER` before inserting, or skip this entry. while peer.addrs.len() >= MAX_ADDRESSES_PER_PEER { - let pos = peer.addrs.iter().position(|addr| addr.score() <= initial_score); + let pos = peer.addrs.iter_mut().position(|addr| addr.score() <= initial_score); if let Some(pos) = pos { let _ = peer.addrs.remove(pos); } else { @@ -330,29 +286,67 @@ impl NetTopology { } } - anything_changed = true; + // `addrs` can contain duplicates, therefore we would insert the same address twice. + if peer.addrs.iter().any(|a| a.addr == addr) { + continue; + } + peer.addrs.push(Addr { addr, expires: now_systime + KADEMLIA_DISCOVERY_EXPIRATION, back_off_until: now, next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: Mutex::new(AddrScore { + score: AddrScore { connected_since: None, score: initial_score, latest_score_update: now, - }), + }, }); } anything_changed } - /// Indicates the peer store that we're connected to this given address. + /// Returns the list of peers that are stored in the topology. + #[inline] + pub fn known_peers(&self) -> impl Iterator { + self.store.keys() + } + + /// Returns the addresses stored for a specific peer, and their reputation score. /// - /// This increases the score of the address that we connected to. Since we assume that only - /// one peer can be reached with any specific address, we also remove all addresses from other - /// peers that match the one we connected to. - pub fn report_connected(&mut self, addr: &Multiaddr, peer: &PeerId) { + /// If `include_expired` is true, includes expired addresses that shouldn't be taken into + /// account when dialing. + #[inline] + pub fn addresses_of_peer(&mut self, peer: &PeerId, include_expired: bool) + -> impl Iterator { + let now_st = SystemTime::now(); + let now_is = Instant::now(); + + let mut list = self.store.get_mut(peer).into_iter().flat_map(|p| p.addrs.iter_mut()).filter_map(move |addr| { + let (score, connected) = addr.score_and_is_connected(); + if include_expired || (addr.expires >= now_st && score > 0 && addr.back_off_until < now_is) || connected { + Some((score, &addr.addr)) + } else { + None + } + }).collect::>(); + list.sort_by(|a, b| a.0.cmp(&b.0)); + // TODO: meh, optimize + list.into_iter().map(|(score, addr)| (addr, score)) + } + + /// Marks the given peer as connected through the given endpoint. + pub fn set_connected(&mut self, peer: &PeerId, endpoint: &ConnectedPoint) { + if *peer == self.local_peer_id { + return + } + + let addr = match endpoint { + ConnectedPoint::Dialer { address } => address, + ConnectedPoint::Listener { .. } => return + }; + let now = Instant::now(); // Just making sure that we have an entry for this peer in `store`, but don't use it. @@ -364,20 +358,19 @@ impl NetTopology { addr.connected_now(CONNECTED_MINIMUM_SCORE); addr.back_off_until = now; addr.next_back_off = FIRST_CONNECT_FAIL_BACKOFF; - continue; + continue } - // TODO: a else block would be better, but we get borrowck errors info_in_store.addrs.push(Addr { addr: addr.clone(), expires: SystemTime::now() + EXPIRATION_PUSH_BACK_CONNEC, back_off_until: now, next_back_off: FIRST_CONNECT_FAIL_BACKOFF, - score: Mutex::new(AddrScore { + score: AddrScore { connected_since: Some(now), latest_score_update: now, score: CONNECTED_MINIMUM_SCORE, - }), + }, }); } else { @@ -391,19 +384,17 @@ impl NetTopology { } } - /// Indicates the peer store that we're disconnected from an address. - /// - /// There's no need to indicate a peer ID, as each address can only have one peer ID. - /// If we were indeed connected to this addr, then we can find out which peer ID it is. - pub fn report_disconnected(&mut self, addr: &Multiaddr, reason: DisconnectReason) { - let score_diff = match reason { - DisconnectReason::NoSlot => -1, - DisconnectReason::FoundBetterAddr => -5, - DisconnectReason::RemoteClosed => -5, - DisconnectReason::Useless => -5, - DisconnectReason::Banned => -5, + /// Marks the given peer as disconnected. The endpoint is the one we were connected to. + pub fn set_disconnected(&mut self, _: &PeerId, endpoint: &ConnectedPoint) { + let addr = match endpoint { + ConnectedPoint::Dialer { address } => address, + ConnectedPoint::Listener { .. } => return }; + // Note that we used to have different score values here in the past, but there really + // isn't much point in doing so in practice. + let score_diff = -3; + for info in self.store.values_mut() { for a in info.addrs.iter_mut() { if &a.addr == addr { @@ -414,60 +405,35 @@ impl NetTopology { if a.expires < expires_push_back { a.expires = expires_push_back; } - return; + return } } } } - /// Indicates the peer store that we failed to connect to an address. - /// - /// We don't care about which peer is supposed to be behind that address. If we failed to dial - /// it for a specific peer, we would also fail to dial it for all peers that have this - /// address. - pub fn report_failed_to_connect(&mut self, addr: &Multiaddr) { + /// Indicates to the topology that we failed to reach a node when dialing the given address. + pub fn set_unreachable(&mut self, addr: &Multiaddr) { for info in self.store.values_mut() { for a in info.addrs.iter_mut() { - if &a.addr == addr { - a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT); - trace!(target: "sub-libp2p", "Back off for {} = {:?}", addr, a.next_back_off); - a.back_off_until = Instant::now() + a.next_back_off; - a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); + if &a.addr != addr { + continue } - } - } - } - /// Indicates the peer store that the given peer is useless. - /// - /// This decreases the scores of the addresses of that peer. - pub fn report_useless(&mut self, peer: &PeerId) { - for (peer_in_store, info_in_store) in self.store.iter_mut() { - if peer == peer_in_store { - for addr in info_in_store.addrs.iter_mut() { - addr.adjust_score(USELESS_PEER_SCORE_CHANGE); + // It is possible that we are connected to this address, and that the dial failure + // concerns another peer. + if a.is_connected() { + continue } + + a.adjust_score(SCORE_DIFF_ON_FAILED_TO_CONNECT); + trace!(target: "sub-libp2p", "Back off for {} = {:?}", addr, a.next_back_off); + a.back_off_until = Instant::now() + a.next_back_off; + a.next_back_off = cmp::min(a.next_back_off * FAIL_BACKOFF_MULTIPLIER, MAX_BACKOFF); } } } } -/// Reason why we disconnected from a peer. -#[derive(Debug)] -pub enum DisconnectReason { - /// No slot available locally anymore for this peer. - NoSlot, - /// A better way to connect to this peer has been found, therefore we disconnect from - /// the old one. - FoundBetterAddr, - /// The remote closed the connection. - RemoteClosed, - /// This node is considered useless for our needs. This includes time outs. - Useless, - /// The peer has been banned. - Banned, -} - fn peer_access<'a>(store: &'a mut FnvHashMap, peer: &PeerId) -> &'a mut PeerInfo { // TODO: should be optimizable if HashMap gets a better API store.entry(peer.clone()).or_insert_with(Default::default) @@ -488,17 +454,17 @@ struct Addr { next_back_off: Duration, /// Don't try to connect to this node until `Instant`. back_off_until: Instant, - score: Mutex, + score: AddrScore, } impl Clone for Addr { fn clone(&self) -> Addr { Addr { addr: self.addr.clone(), - expires: self.expires.clone(), - next_back_off: self.next_back_off.clone(), - back_off_until: self.back_off_until.clone(), - score: Mutex::new(self.score.lock().clone()), + expires: self.expires, + next_back_off: self.next_back_off, + back_off_until: self.back_off_until, + score: self.score.clone(), } } } @@ -516,58 +482,52 @@ struct AddrScore { impl Addr { /// Sets the addr to connected. If the score is lower than the given value, raises it to this /// value. - fn connected_now(&self, raise_to_min: u32) { - let mut score = self.score.lock(); + fn connected_now(&mut self, raise_to_min: u32) { let now = Instant::now(); - Addr::flush(&mut score, now); - score.connected_since = Some(now); - if score.score < raise_to_min { - score.score = raise_to_min; + Addr::flush(&mut self.score, now); + self.score.connected_since = Some(now); + if self.score.score < raise_to_min { + self.score.score = raise_to_min; } } /// Applies a modification to the score. - fn adjust_score(&self, score_diff: i32) { - let mut score = self.score.lock(); - Addr::flush(&mut score, Instant::now()); + fn adjust_score(&mut self, score_diff: i32) { + Addr::flush(&mut self.score, Instant::now()); if score_diff >= 0 { - score.score = cmp::min(MAX_SCORE, score.score + score_diff as u32); + self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32); } else { - score.score = score.score.saturating_sub(-score_diff as u32); + self.score.score = self.score.score.saturating_sub(-score_diff as u32); } } /// Sets the addr to disconnected and applies a modification to the score. - fn disconnected_now(&self, score_diff: i32) { - let mut score = self.score.lock(); - Addr::flush(&mut score, Instant::now()); - score.connected_since = None; + fn disconnected_now(&mut self, score_diff: i32) { + Addr::flush(&mut self.score, Instant::now()); + self.score.connected_since = None; if score_diff >= 0 { - score.score = cmp::min(MAX_SCORE, score.score + score_diff as u32); + self.score.score = cmp::min(MAX_SCORE, self.score.score + score_diff as u32); } else { - score.score = score.score.saturating_sub(-score_diff as u32); + self.score.score = self.score.score.saturating_sub(-score_diff as u32); } } /// Returns true if we are connected to this addr. fn is_connected(&self) -> bool { - let score = self.score.lock(); - score.connected_since.is_some() + self.score.connected_since.is_some() } /// Returns the score, and true if we are connected to this addr. - fn score_and_is_connected(&self) -> (u32, bool) { - let mut score = self.score.lock(); - Addr::flush(&mut score, Instant::now()); - let is_connected = score.connected_since.is_some(); - (score.score, is_connected) + fn score_and_is_connected(&mut self) -> (u32, bool) { + Addr::flush(&mut self.score, Instant::now()); + let is_connected = self.score.connected_since.is_some(); + (self.score.score, is_connected) } /// Updates `score` and `latest_score_update`, and returns the score. - fn score(&self) -> u32 { - let mut score = self.score.lock(); - Addr::flush(&mut score, Instant::now()); - score.score + fn score(&mut self) -> u32 { + Addr::flush(&mut self.score, Instant::now()); + self.score.score } fn flush(score: &mut AddrScore, now: Instant) { @@ -588,8 +548,8 @@ impl Addr { /// Divides a `Duration` with a `Duration`. This exists in the stdlib but isn't stable yet. // TODO: remove this function once stable fn div_dur_with_dur(a: Duration, b: Duration) -> u32 { - let a_ms = a.as_secs() * 1_000_000 + (a.subsec_nanos() / 1_000) as u64; - let b_ms = b.as_secs() * 1_000_000 + (b.subsec_nanos() / 1_000) as u64; + let a_ms = a.as_secs() * 1_000_000 + u64::from(a.subsec_micros()); + let b_ms = b.as_secs() * 1_000_000 + u64::from(b.subsec_micros()); (a_ms / b_ms) as u32 } @@ -607,8 +567,8 @@ struct SerializedAddr { score: u32, } -impl<'a> From<&'a Addr> for SerializedAddr { - fn from(addr: &'a Addr) -> SerializedAddr { +impl<'a> From<&'a mut Addr> for SerializedAddr { + fn from(addr: &'a mut Addr) -> SerializedAddr { SerializedAddr { addr: addr.addr.to_string(), expires: addr.expires, @@ -618,9 +578,10 @@ impl<'a> From<&'a Addr> for SerializedAddr { } /// Attempts to load storage from a file. +/// Ignores any entry equal to `local_peer_id`. /// Deletes the file and returns an empty map if the file doesn't exist, cannot be opened /// or is corrupted. -fn try_load(path: impl AsRef) -> FnvHashMap { +fn try_load(path: impl AsRef, local_peer_id: &PeerId) -> FnvHashMap { let path = path.as_ref(); if !path.exists() { debug!(target: "sub-libp2p", "Peer storage file {:?} doesn't exist", path); @@ -664,7 +625,8 @@ fn try_load(path: impl AsRef) -> FnvHashMap { let data = Cursor::new(first_byte).chain(file); match serde_json::from_reader::<_, serde_json::Value>(data) { Ok(serde_json::Value::Null) => Default::default(), - Ok(serde_json::Value::Object(map)) => deserialize_tolerant(map.into_iter()), + Ok(serde_json::Value::Object(map)) => + deserialize_tolerant(map.into_iter(), local_peer_id), Ok(_) | Err(_) => { // The `Ok(_)` case means that the file doesn't contain a map. let _ = fs::remove_file(path); @@ -676,9 +638,10 @@ fn try_load(path: impl AsRef) -> FnvHashMap { /// Attempts to turn a deserialized version of the storage into the final version. /// -/// Skips entries that are invalid. +/// Skips entries that are invalid or equal to `local_peer_id`. fn deserialize_tolerant( - iter: impl Iterator + iter: impl Iterator, + local_peer_id: &PeerId ) -> FnvHashMap { let now = Instant::now(); let now_systime = SystemTime::now(); @@ -690,6 +653,10 @@ fn deserialize_tolerant( Err(_) => continue, }; + if &peer == local_peer_id { + continue + } + let info: SerializedPeerInfo = match serde_json::from_value(info) { Ok(i) => i, Err(_) => continue, @@ -711,16 +678,16 @@ fn deserialize_tolerant( expires: addr.expires, next_back_off: FIRST_CONNECT_FAIL_BACKOFF, back_off_until: now, - score: Mutex::new(AddrScore { + score: AddrScore { connected_since: None, score: addr.score, latest_score_update: now, - }), + }, }); } if addrs.is_empty() { - continue; + continue } out.insert(peer, PeerInfo { addrs }); @@ -732,18 +699,21 @@ fn deserialize_tolerant( /// Attempts to turn a deserialized version of the storage into the final version. /// /// Skips entries that are invalid or expired. -fn serialize(out: W, map: &FnvHashMap) -> Result<(), IoError> { +fn serialize(out: W, map: &mut FnvHashMap) -> Result<(), IoError> { let now = SystemTime::now(); - let array: FnvHashMap<_, _> = map.iter().filter_map(|(peer, info)| { + let array: FnvHashMap<_, _> = map.iter_mut().filter_map(|(peer, info)| { if info.addrs.is_empty() { return None } let peer = peer.to_base58(); let info = SerializedPeerInfo { - addrs: info.addrs.iter() - .filter(|a| a.expires > now || a.is_connected()) - .map(Into::into) + addrs: info.addrs.iter_mut() + .filter_map(|a| if a.expires > now || a.is_connected() { + Some(a.into()) + } else { + None + }) .collect(), }; diff --git a/core/network-libp2p/src/custom_proto/upgrade.rs b/core/network-libp2p/src/custom_proto/upgrade.rs new file mode 100644 index 0000000000000000000000000000000000000000..caab8ec9d09eeebbec5b3557380910bea5bb95c8 --- /dev/null +++ b/core/network-libp2p/src/custom_proto/upgrade.rs @@ -0,0 +1,535 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::ProtocolId; +use bytes::Bytes; +use libp2p::core::{Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; +use libp2p::tokio_codec::Framed; +use log::warn; +use std::{collections::VecDeque, io, iter, marker::PhantomData, vec::IntoIter as VecIntoIter}; +use futures::{prelude::*, future, stream}; +use tokio_io::{AsyncRead, AsyncWrite}; +use unsigned_varint::codec::UviBytes; + +/// Connection upgrade for a single protocol. +/// +/// Note that "a single protocol" here refers to `par` for example. However +/// each protocol can have multiple different versions for networking purposes. +pub struct RegisteredProtocol { + /// Id of the protocol for API purposes. + id: ProtocolId, + /// Base name of the protocol as advertised on the network. + /// Ends with `/` so that we can append a version number behind. + base_name: Bytes, + /// List of protocol versions that we support. + /// Ordered in descending order so that the best comes first. + supported_versions: Vec, + /// Marker to pin the generic. + marker: PhantomData, +} + +impl RegisteredProtocol { + /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be + /// passed inside the `RegisteredProtocolOutput`. + pub fn new(protocol: ProtocolId, versions: &[u8]) + -> Self { + let mut base_name = Bytes::from_static(b"/substrate/"); + base_name.extend_from_slice(&protocol); + base_name.extend_from_slice(b"/"); + + RegisteredProtocol { + base_name, + id: protocol, + supported_versions: { + let mut tmp = versions.to_vec(); + tmp.sort_unstable_by(|a, b| b.cmp(&a)); + tmp + }, + marker: PhantomData, + } + } + + /// Returns the ID of the protocol. + #[inline] + pub fn id(&self) -> ProtocolId { + self.id + } +} + +impl Clone for RegisteredProtocol { + fn clone(&self) -> Self { + RegisteredProtocol { + id: self.id, + base_name: self.base_name.clone(), + supported_versions: self.supported_versions.clone(), + marker: PhantomData, + } + } +} + +/// Output of a `RegisteredProtocol` upgrade. +pub struct RegisteredProtocolSubstream { + /// If true, we are in the process of closing the sink. + is_closing: bool, + /// Whether the local node opened this substream (dialer), or we received this substream from + /// the remote (listener). + endpoint: Endpoint, + /// Buffer of packets to send. + send_queue: VecDeque>, + /// If true, we should call `poll_complete` on the inner sink. + requires_poll_complete: bool, + /// The underlying substream. + inner: stream::Fuse>>>, + /// Id of the protocol. + protocol_id: ProtocolId, + /// Version of the protocol that was negotiated. + protocol_version: u8, + /// If true, we have sent a "remote is clogged" event recently and shouldn't send another one + /// unless the buffer empties then fills itself again. + clogged_fuse: bool, + /// If true, then this substream uses the "/multi/" version of the protocol. This is a hint + /// that the handler can behave differently. + is_multiplex: bool, + /// Marker to pin the generic. + marker: PhantomData, +} + +impl RegisteredProtocolSubstream { + /// Returns the protocol id. + #[inline] + pub fn protocol_id(&self) -> ProtocolId { + self.protocol_id + } + + /// Returns the version of the protocol that was negotiated. + #[inline] + pub fn protocol_version(&self) -> u8 { + self.protocol_version + } + + /// Returns whether the local node opened this substream (dialer), or we received this + /// substream from the remote (listener). + pub fn endpoint(&self) -> Endpoint { + self.endpoint + } + + /// Returns true if we negotiated the "multiplexed" version. This means that the handler can + /// open multiple substreams instead of just one. + pub fn is_multiplex(&self) -> bool { + self.is_multiplex + } + + /// Starts a graceful shutdown process on this substream. + /// + /// Note that "graceful" means that we sent a closing message. We don't wait for any + /// confirmation from the remote. + /// + /// After calling this, the stream is guaranteed to finish soon-ish. + pub fn shutdown(&mut self) { + self.is_closing = true; + self.send_queue.clear(); + } + + /// Sends a message to the substream. + pub fn send_message(&mut self, data: TMessage) + where TMessage: CustomMessage { + if self.is_closing { + return + } + + self.send_queue.push_back(data.into_bytes()); + } +} + +/// Implemented on messages that can be sent or received on the network. +pub trait CustomMessage { + /// Turns a message into the raw bytes to send over the network. + fn into_bytes(self) -> Vec; + + /// Tries to parse `bytes` received from the network into a message. + fn from_bytes(bytes: &[u8]) -> Result + where Self: Sized; + + /// Returns a unique ID that is used to match request and responses. + /// + /// The networking layer employs multiplexing in order to have multiple parallel data streams. + /// Transmitting messages over the network uses two kinds of substreams: + /// + /// - Undirectional substreams, where we send a single message then close the substream. + /// - Bidirectional substreams, where we send a message then wait for a response. Once the + /// response has arrived, we close the substream. + /// + /// If `request_id()` returns `OneWay`, then this message will be sent or received over a + /// unidirectional substream. If instead it returns `Request` or `Response`, then we use the + /// value to match a request with its response. + fn request_id(&self) -> CustomMessageId; +} + +/// See the documentation of `CustomMessage::request_id`. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum CustomMessageId { + OneWay, + Request(u64), + Response(u64), +} + +// These trait implementations exist mostly for testing convenience. This should eventually be +// removed. + +impl CustomMessage for Vec { + fn into_bytes(self) -> Vec { + self + } + + fn from_bytes(bytes: &[u8]) -> Result { + Ok(bytes.to_vec()) + } + + fn request_id(&self) -> CustomMessageId { + CustomMessageId::OneWay + } +} + +impl CustomMessage for (Option, Vec) { + fn into_bytes(self) -> Vec { + use byteorder::WriteBytesExt; + use std::io::Write; + let mut out = Vec::new(); + out.write_u64::(self.0.unwrap_or(u64::max_value())) + .expect("Writing to a Vec can never fail"); + out.write_all(&self.1).expect("Writing to a Vec can never fail"); + out + } + + fn from_bytes(bytes: &[u8]) -> Result { + use byteorder::ReadBytesExt; + use std::io::Read; + let mut rdr = std::io::Cursor::new(bytes); + let id = rdr.read_u64::().map_err(|_| ())?; + let mut out = Vec::new(); + rdr.read_to_end(&mut out).map_err(|_| ())?; + let id = if id == u64::max_value() { + None + } else { + Some(id) + }; + Ok((id, out)) + } + + fn request_id(&self) -> CustomMessageId { + if let Some(id) = self.0 { + CustomMessageId::Request(id) + } else { + CustomMessageId::OneWay + } + } +} + +/// Event produced by the `RegisteredProtocolSubstream`. +#[derive(Debug, Clone)] +pub enum RegisteredProtocolEvent { + /// Received a message from the remote. + Message(TMessage), + + /// Diagnostic event indicating that the connection is clogged and we should avoid sending too + /// many messages to it. + Clogged { + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec, + }, +} + +impl Stream for RegisteredProtocolSubstream +where TSubstream: AsyncRead + AsyncWrite, TMessage: CustomMessage { + type Item = RegisteredProtocolEvent; + type Error = io::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + // Flushing the local queue. + while let Some(packet) = self.send_queue.pop_front() { + match self.inner.start_send(packet)? { + AsyncSink::NotReady(packet) => { + self.send_queue.push_front(packet); + break + }, + AsyncSink::Ready => self.requires_poll_complete = true, + } + } + + // If we are closing, close as soon as the Sink is closed. + if self.is_closing { + return Ok(self.inner.close()?.map(|()| None)) + } + + // Indicating that the remote is clogged if that's the case. + if self.send_queue.len() >= 2048 { + if !self.clogged_fuse { + // Note: this fuse is important not just for preventing us from flooding the logs; + // if you remove the fuse, then we will always return early from this function and + // thus never read any message from the network. + self.clogged_fuse = true; + return Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { + messages: self.send_queue.iter() + .map(|m| CustomMessage::from_bytes(&m)) + .filter_map(Result::ok) + .collect(), + }))) + } + } else { + self.clogged_fuse = false; + } + + // Flushing if necessary. + if self.requires_poll_complete { + if let Async::Ready(()) = self.inner.poll_complete()? { + self.requires_poll_complete = false; + } + } + + // Receiving incoming packets. + // Note that `inner` is wrapped in a `Fuse`, therefore we can poll it forever. + match self.inner.poll()? { + Async::Ready(Some(data)) => { + let message = ::from_bytes(&data) + .map_err(|()| { + warn!(target: "sub-libp2p", "Couldn't decode packet sent by the remote: {:?}", data); + io::ErrorKind::InvalidData + })?; + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) + } + Async::Ready(None) => + if !self.requires_poll_complete && self.send_queue.is_empty() { + Ok(Async::Ready(None)) + } else { + Ok(Async::NotReady) + } + Async::NotReady => Ok(Async::NotReady), + } + } +} + +impl UpgradeInfo for RegisteredProtocol { + type Info = RegisteredProtocolName; + type InfoIter = VecIntoIter; + + #[inline] + fn protocol_info(&self) -> Self::InfoIter { + // Report each version as an individual protocol. + self.supported_versions.iter().flat_map(|&version| { + let num = version.to_string(); + + // Note that `name1` is the multiplex version, as we priviledge it over the old one. + let mut name1 = self.base_name.clone(); + name1.extend_from_slice(b"multi/"); + name1.extend_from_slice(num.as_bytes()); + let proto1 = RegisteredProtocolName { + name: name1, + version, + is_multiplex: true, + }; + + let mut name2 = self.base_name.clone(); + name2.extend_from_slice(num.as_bytes()); + let proto2 = RegisteredProtocolName { + name: name2, + version, + is_multiplex: false, + }; + + // Important note: we prioritize the backwards compatible mode for now. + // After some intensive testing has been done, we should switch to the new mode by + // default. + // Then finally we can remove the old mode after everyone has switched. + // See https://github.com/paritytech/substrate/issues/1692 + iter::once(proto2).chain(iter::once(proto1)) + }).collect::>().into_iter() + } +} + +/// Implementation of `ProtocolName` for a custom protocol. +#[derive(Debug, Clone)] +pub struct RegisteredProtocolName { + /// Protocol name, as advertised on the wire. + name: Bytes, + /// Version number. Stored in string form in `name`, but duplicated here for easier retrieval. + version: u8, + /// If true, then this version is the one with the multiplexing. + is_multiplex: bool, +} + +impl ProtocolName for RegisteredProtocolName { + fn protocol_name(&self) -> &[u8] { + &self.name + } +} + +impl InboundUpgrade for RegisteredProtocol +where TSubstream: AsyncRead + AsyncWrite, +{ + type Output = RegisteredProtocolSubstream; + type Future = future::FutureResult; + type Error = io::Error; + + fn upgrade_inbound( + self, + socket: TSubstream, + info: Self::Info, + ) -> Self::Future { + let framed = { + let mut codec = UviBytes::default(); + codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. + Framed::new(socket, codec) + }; + + future::ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Listener, + send_queue: VecDeque::new(), + requires_poll_complete: false, + inner: framed.fuse(), + protocol_id: self.id, + protocol_version: info.version, + clogged_fuse: false, + is_multiplex: info.is_multiplex, + marker: PhantomData, + }) + } +} + +impl OutboundUpgrade for RegisteredProtocol +where TSubstream: AsyncRead + AsyncWrite, +{ + type Output = >::Output; + type Future = >::Future; + type Error = >::Error; + + fn upgrade_outbound( + self, + socket: TSubstream, + info: Self::Info, + ) -> Self::Future { + let framed = Framed::new(socket, UviBytes::default()); + + future::ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Dialer, + send_queue: VecDeque::new(), + requires_poll_complete: false, + inner: framed.fuse(), + protocol_id: self.id, + protocol_version: info.version, + clogged_fuse: false, + is_multiplex: info.is_multiplex, + marker: PhantomData, + }) + } +} + +// Connection upgrade for all the protocols contained in it. +pub struct RegisteredProtocols(pub Vec>); + +impl RegisteredProtocols { + /// Returns the number of protocols. + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl Default for RegisteredProtocols { + fn default() -> Self { + RegisteredProtocols(Vec::new()) + } +} + +impl UpgradeInfo for RegisteredProtocols { + type Info = RegisteredProtocolsName; + type InfoIter = VecIntoIter; + + #[inline] + fn protocol_info(&self) -> Self::InfoIter { + // We concat the lists of `RegisteredProtocol::protocol_names` for + // each protocol. + self.0.iter().enumerate().flat_map(|(n, proto)| + UpgradeInfo::protocol_info(proto) + .map(move |inner| { + RegisteredProtocolsName { + inner, + index: n, + } + }) + ).collect::>().into_iter() + } +} + +impl Clone for RegisteredProtocols { + fn clone(&self) -> Self { + RegisteredProtocols(self.0.clone()) + } +} + +/// Implementation of `ProtocolName` for several custom protocols. +#[derive(Debug, Clone)] +pub struct RegisteredProtocolsName { + /// Inner registered protocol. + inner: RegisteredProtocolName, + /// Index of the protocol in the list of registered custom protocols. + index: usize, +} + +impl ProtocolName for RegisteredProtocolsName { + fn protocol_name(&self) -> &[u8] { + self.inner.protocol_name() + } +} + +impl InboundUpgrade for RegisteredProtocols +where TSubstream: AsyncRead + AsyncWrite, +{ + type Output = as InboundUpgrade>::Output; + type Future = as InboundUpgrade>::Future; + type Error = io::Error; + + #[inline] + fn upgrade_inbound( + self, + socket: TSubstream, + info: Self::Info, + ) -> Self::Future { + self.0.into_iter() + .nth(info.index) + .expect("invalid protocol index ; programmer logic error") + .upgrade_inbound(socket, info.inner) + } +} + +impl OutboundUpgrade for RegisteredProtocols +where TSubstream: AsyncRead + AsyncWrite, +{ + type Output = >::Output; + type Future = >::Future; + type Error = >::Error; + + #[inline] + fn upgrade_outbound( + self, + socket: TSubstream, + info: Self::Info, + ) -> Self::Future { + // Upgrades are symmetrical. + self.upgrade_inbound(socket, info) + } +} diff --git a/core/network-libp2p/src/error.rs b/core/network-libp2p/src/error.rs deleted file mode 100644 index 9de1b9d43fee0c2af2fd75c16a53ed3cdd94fa0e..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/error.rs +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{io, net, fmt}; -use libc::{ENFILE, EMFILE}; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum DisconnectReason -{ - DisconnectRequested, - TCPError, - BadProtocol, - UselessPeer, - TooManyPeers, - DuplicatePeer, - IncompatibleProtocol, - NullIdentity, - ClientQuit, - UnexpectedIdentity, - LocalIdentity, - PingTimeout, - Unknown, -} - -impl DisconnectReason { - pub fn from_u8(n: u8) -> DisconnectReason { - match n { - 0 => DisconnectReason::DisconnectRequested, - 1 => DisconnectReason::TCPError, - 2 => DisconnectReason::BadProtocol, - 3 => DisconnectReason::UselessPeer, - 4 => DisconnectReason::TooManyPeers, - 5 => DisconnectReason::DuplicatePeer, - 6 => DisconnectReason::IncompatibleProtocol, - 7 => DisconnectReason::NullIdentity, - 8 => DisconnectReason::ClientQuit, - 9 => DisconnectReason::UnexpectedIdentity, - 10 => DisconnectReason::LocalIdentity, - 11 => DisconnectReason::PingTimeout, - _ => DisconnectReason::Unknown, - } - } -} - -impl fmt::Display for DisconnectReason { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::DisconnectReason::*; - - let msg = match *self { - DisconnectRequested => "disconnect requested", - TCPError => "TCP error", - BadProtocol => "bad protocol", - UselessPeer => "useless peer", - TooManyPeers => "too many peers", - DuplicatePeer => "duplicate peer", - IncompatibleProtocol => "incompatible protocol", - NullIdentity => "null identity", - ClientQuit => "client quit", - UnexpectedIdentity => "unexpected identity", - LocalIdentity => "local identity", - PingTimeout => "ping timeout", - Unknown => "unknown", - }; - - f.write_str(msg) - } -} - -error_chain! { - errors { - #[doc = "Error concerning the network address parsing subsystem."] - AddressParse { - description("Failed to parse network address"), - display("Failed to parse network address"), - } - - #[doc = "Error concerning the network address resolution subsystem."] - AddressResolve(err: Option) { - description("Failed to resolve network address"), - display("Failed to resolve network address {}", err.as_ref().map_or("".to_string(), |e| e.to_string())), - } - - #[doc = "Authentication failure"] - Auth { - description("Authentication failure"), - display("Authentication failure"), - } - - #[doc = "Unrecognised protocol"] - BadProtocol { - description("Bad protocol"), - display("Bad protocol"), - } - - #[doc = "Expired message"] - Expired { - description("Expired message"), - display("Expired message"), - } - - #[doc = "Peer not found"] - PeerNotFound { - description("Peer not found"), - display("Peer not found"), - } - - #[doc = "Peer is disconnected"] - Disconnect(reason: DisconnectReason) { - description("Peer disconnected"), - display("Peer disconnected: {}", reason), - } - - #[doc = "Invalid node id"] - InvalidNodeId { - description("Invalid node id"), - display("Invalid node id"), - } - - #[doc = "Packet size is over the protocol limit"] - OversizedPacket { - description("Packet is too large"), - display("Packet is too large"), - } - - #[doc = "Reached system resource limits for this process"] - ProcessTooManyFiles { - description("Too many open files in process."), - display("Too many open files in this process. Check your resource limits and restart parity"), - } - - #[doc = "Reached system wide resource limits"] - SystemTooManyFiles { - description("Too many open files on system."), - display("Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity."), - } - - #[doc = "An unknown IO error occurred."] - Io(err: io::Error) { - description("IO Error"), - display("Unexpected IO error: {}", err), - } - } -} - -impl From for Error { - fn from(err: io::Error) -> Self { - match err.raw_os_error() { - Some(ENFILE) => ErrorKind::ProcessTooManyFiles.into(), - Some(EMFILE) => ErrorKind::SystemTooManyFiles.into(), - _ => Error::from_kind(ErrorKind::Io(err)) - } - } -} - - -impl From for Error { - fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() } -} - -#[test] -fn test_errors() { - assert_eq!(DisconnectReason::ClientQuit, DisconnectReason::from_u8(8)); - let mut r = DisconnectReason::DisconnectRequested; - for i in 0 .. 20 { - r = DisconnectReason::from_u8(i); - } - assert_eq!(DisconnectReason::Unknown, r); -} - -#[test] -fn test_io_errors() { - use libc::{EMFILE, ENFILE}; - - assert_matches!( - >::from( - io::Error::from_raw_os_error(ENFILE) - ).kind(), - ErrorKind::ProcessTooManyFiles); - - assert_matches!( - >::from( - io::Error::from_raw_os_error(EMFILE) - ).kind(), - ErrorKind::SystemTooManyFiles); - - assert_matches!( - >::from( - io::Error::from_raw_os_error(0) - ).kind(), - ErrorKind::Io(_)); -} diff --git a/core/network-libp2p/src/lib.rs b/core/network-libp2p/src/lib.rs index 8c5df15c4954e5cef96ba2af856e0d3f8eb1ed98..a6336e41635ba3f26eba394d3cdbba477e013766 100644 --- a/core/network-libp2p/src/lib.rs +++ b/core/network-libp2p/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,66 +14,154 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Substrate libp2p implementation of the ethcore network library - -#![recursion_limit = "128"] - -extern crate parking_lot; -extern crate fnv; -extern crate futures; -extern crate tokio; -extern crate tokio_io; -extern crate tokio_timer; -extern crate libc; -#[macro_use] -extern crate libp2p; -extern crate rand; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate bytes; -extern crate unsigned_varint; - -#[macro_use] -extern crate error_chain; -#[macro_use] -extern crate log; -#[cfg(test)] #[macro_use] -extern crate assert_matches; +//! Networking layer of Substrate. +mod behaviour; mod custom_proto; -mod error; -mod node_handler; mod secret; mod service_task; -mod swarm; -mod topology; mod traits; mod transport; -pub use custom_proto::RegisteredProtocol; -pub use error::{Error, ErrorKind, DisconnectReason}; -pub use libp2p::{Multiaddr, multiaddr::{Protocol}, multiaddr, PeerId}; -pub use secret::obtain_private_key; -pub use service_task::{start_service, Service, ServiceEvent}; -pub use traits::{NetworkConfiguration, NodeIndex, NodeId, NonReservedPeerMode}; -pub use traits::{ProtocolId, Secret, Severity}; - -/// Check if node url is valid -pub fn validate_node_url(url: &str) -> Result<(), Error> { - match url.parse::() { - Ok(_) => Ok(()), - Err(_) => Err(ErrorKind::InvalidNodeId.into()), - } -} +pub use crate::custom_proto::{CustomMessage, CustomMessageId, RegisteredProtocol}; +pub use crate::secret::obtain_private_key; +pub use crate::service_task::{start_service, Service, ServiceEvent}; +pub use crate::traits::{NetworkConfiguration, NodeIndex, NodeId, NonReservedPeerMode}; +pub use crate::traits::{ProtocolId, Secret, Severity}; +pub use libp2p::{Multiaddr, multiaddr::Error as MultiaddrError, multiaddr::Protocol, build_multiaddr, PeerId, core::PublicKey}; + +use libp2p::core::nodes::ConnectedPoint; +use serde_derive::Serialize; +use std::{collections::{HashMap, HashSet}, error, fmt, time::Duration}; /// Parses a string address and returns the component, if valid. -pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), Error> { - let mut addr: Multiaddr = addr_str.parse().map_err(|_| ErrorKind::AddressParse)?; +pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { + let mut addr: Multiaddr = addr_str.parse()?; + let who = match addr.pop() { - Some(Protocol::P2p(key)) => - PeerId::from_multihash(key).map_err(|_| ErrorKind::AddressParse)?, - _ => return Err(ErrorKind::AddressParse.into()), + Some(Protocol::P2p(key)) => PeerId::from_multihash(key) + .map_err(|_| ParseErr::InvalidPeerId)?, + _ => return Err(ParseErr::PeerIdMissing), }; + Ok((who, addr)) } + +/// Error that can be generated by `parse_str_addr`. +#[derive(Debug)] +pub enum ParseErr { + /// Error while parsing the multiaddress. + MultiaddrParse(MultiaddrError), + /// Multihash of the peer ID is invalid. + InvalidPeerId, + /// The peer ID is missing from the address. + PeerIdMissing, +} + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParseErr::MultiaddrParse(err) => write!(f, "{}", err), + ParseErr::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"), + ParseErr::PeerIdMissing => write!(f, "Peer id is missing from the address"), + } + } +} + +impl error::Error for ParseErr { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + ParseErr::MultiaddrParse(err) => Some(err), + ParseErr::InvalidPeerId => None, + ParseErr::PeerIdMissing => None, + } + } +} + +impl From for ParseErr { + fn from(err: MultiaddrError) -> ParseErr { + ParseErr::MultiaddrParse(err) + } +} + +/// Returns general information about the networking. +/// +/// Meant for general diagnostic purposes. +/// +/// **Warning**: This API is not stable. +#[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NetworkState { + /// PeerId of the local node. + pub peer_id: String, + /// List of addresses the node is currently listening on. + pub listened_addresses: HashSet, + // TODO (https://github.com/libp2p/rust-libp2p/issues/978): external_addresses: Vec, + /// If true, we only accept reserved peers. + pub is_reserved_only: bool, + /// PeerIds of the nodes that are marked as reserved. + pub reserved_peers: HashSet, + /// PeerIds of the nodes that are banned, and how long in the seconds the ban remains. + pub banned_peers: HashMap, + /// List of node we're connected to. + pub connected_peers: HashMap, + /// List of node that we know of but that we're not connected to. + pub not_connected_peers: HashMap, + /// Downloaded bytes per second averaged over the past few seconds. + pub average_download_per_sec: u64, + /// Uploaded bytes per second averaged over the past few seconds. + pub average_upload_per_sec: u64, +} + +#[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NetworkStatePeer { + /// How we are connected to the node. + pub endpoint: NetworkStatePeerEndpoint, + /// Node information, as provided by the node itself. Can be empty if not known yet. + pub version_string: Option, + /// Latest ping duration with this node. + pub latest_ping_time: Option, + /// If true, the peer is "enabled", which means that we try to open Substrate-related protocols + /// with this peer. If false, we stick to Kademlia and/or other network-only protocols. + pub enabled: bool, + /// List of protocols that we have open with the given peer. + pub open_protocols: HashSet, + /// List of addresses known for this node, with its reputation score. + pub known_addresses: HashMap, +} + +#[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct NetworkStateNotConnectedPeer { + /// List of addresses known for this node, with its reputation score. + pub known_addresses: HashMap, +} + +#[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum NetworkStatePeerEndpoint { + /// We are dialing the given address. + Dialing(Multiaddr), + /// We are listening. + Listening { + /// Address we're listening on that received the connection. + listen_addr: Multiaddr, + /// Address data is sent back to. + send_back_addr: Multiaddr, + }, +} + +impl From for NetworkStatePeerEndpoint { + fn from(endpoint: ConnectedPoint) -> Self { + match endpoint { + ConnectedPoint::Dialer { address } => + NetworkStatePeerEndpoint::Dialing(address), + ConnectedPoint::Listener { listen_addr, send_back_addr } => + NetworkStatePeerEndpoint::Listening { + listen_addr: listen_addr, + send_back_addr: send_back_addr + } + } + } +} diff --git a/core/network-libp2p/src/node_handler.rs b/core/network-libp2p/src/node_handler.rs deleted file mode 100644 index ad1f4b7504a6288b689110c8edaf3d931dabb1ce..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/node_handler.rs +++ /dev/null @@ -1,863 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use bytes::Bytes; -use custom_proto::{RegisteredProtocols, RegisteredProtocolSubstream}; -use futures::{prelude::*, task}; -use libp2p::core::{ConnectionUpgrade, Endpoint, PeerId, PublicKey, upgrade}; -use libp2p::core::nodes::handled_node::{NodeHandler, NodeHandlerEndpoint, NodeHandlerEvent}; -use libp2p::kad::{KadConnecConfig, KadFindNodeRespond, KadIncomingRequest, KadConnecController}; -use libp2p::{identify, ping}; -use parking_lot::Mutex; -use std::io::{Error as IoError, ErrorKind as IoErrorKind}; -use std::sync::Arc; -use std::time::{Duration, Instant}; -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_timer::{Delay, Interval}; -use {Multiaddr, ProtocolId}; - -/// Duration after which we consider that a ping failed. -const PING_TIMEOUT: Duration = Duration::from_secs(30); -/// After a ping succeeded, wait this long before the next ping. -const DELAY_TO_NEXT_PING: Duration = Duration::from_secs(15); -/// Period at which we identify the remote. -const PERIOD_IDENTIFY: Duration = Duration::from_secs(5 * 60); -/// Delay between the moment we connect and the first time we ping. -const DELAY_TO_FIRST_PING: Duration = Duration::from_secs(5); -/// Delay between the moment we connect and the first time we identify. -const DELAY_TO_FIRST_IDENTIFY: Duration = Duration::from_secs(2); - -/// This struct handles the open substreams of a specific node. -/// -/// It doesn't handle opening the substreams, but only what to do with substreams that have been -/// opened. -/// -/// The node will be pinged at a regular interval to determine whether it's still alive. We will -/// also regularly query the remote for identification information, for statistics purposes. -pub struct SubstrateNodeHandler { - /// List of registered custom protocols. - registered_custom: Arc, - /// Substreams open for "custom" protocols (eg. dot). - custom_protocols_substreams: Vec>, - - /// Substream open for Kademlia, if any. - kademlia_substream: Option<(KadConnecController, Box + Send>)>, - /// If true, we need to send back a `KadOpen` event on the stream (if Kademlia is open). - need_report_kad_open: bool, - - /// Substream open for sending pings, if any. - ping_out_substream: Option>, - /// Active pinging attempt with the moment it expires. - active_ping_out: Option, - /// Substreams open for receiving pings. - ping_in_substreams: Vec>, - /// Future that fires when we need to ping the node again. - /// - /// Every time we receive a pong, we reset the timer to the next time. - next_ping: Delay, - - /// Substreams for sending back our identify info to the remote. - /// - /// This is in an `Arc` in order to avoid borrowing issues with the future. - identify_send_back: Arc + Send>>>>, - /// Stream that fires when we need to identify the node again. - next_identify: Interval, - - /// Substreams being upgraded on the listening side. - upgrades_in_progress_listen: Vec, Error = IoError> + Send>>, - /// Substreams being upgraded on the dialing side. Contrary to `upgrades_in_progress_listen`, - /// these have a known purpose. - upgrades_in_progress_dial: Vec<(UpgradePurpose, Box, Error = IoError> + Send>)>, - /// The substreams we want to open. - queued_dial_upgrades: Vec, - /// Number of outbound substreams the outside should open for us. - num_out_user_must_open: usize, - - /// The node has started its shutdown process. - is_shutting_down: bool, - - /// Task to notify if we add an element to one of the lists from the public API. - to_notify: Option, -} - -/// Purpose of an upgrade in progress on the dialing side. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum UpgradePurpose { - Custom(ProtocolId), - Kad, - Identify, - Ping, -} - -/// Event that can happen on the `SubstrateNodeHandler`. -pub enum SubstrateOutEvent { - /// The node has been determined to be unresponsive. - Unresponsive, - - /// The node works but we can't do anything useful with it. - Useless, - - /// Started pinging the remote. This can be used to print a diagnostic message in the logs. - PingStart, - - /// The node has successfully responded to a ping. - PingSuccess(Duration), - - /// Opened a custom protocol with the remote. - CustomProtocolOpen { - /// Identifier of the protocol. - protocol_id: ProtocolId, - /// Version of the protocol that has been opened. - version: u8, - }, - - /// Closed a custom protocol with the remote. - CustomProtocolClosed { - /// Identifier of the protocol. - protocol_id: ProtocolId, - /// Reason why the substream closed. If `Ok`, then it's a graceful exit (EOF). - result: Result<(), IoError>, - }, - - /// Receives a message on a custom protocol substream. - CustomMessage { - /// Protocol which generated the message. - protocol_id: ProtocolId, - /// Data that has been received. - data: Bytes, - }, - - /// We obtained identification information from the remote - Identified { - /// Information of the remote. - info: identify::IdentifyInfo, - /// Address the remote observes us as. - observed_addr: Multiaddr, - }, - - /// The remote wants us to send back identification information. - /// - /// The `IdentificationRequest` object should be used to send the information. - IdentificationRequest(IdentificationRequest), - - /// Opened a Kademlia substream with the node. - KadOpen(KadConnecController), - - /// The remote wants us to answer a Kademlia `FIND_NODE` request. - /// - /// The `responder` should be used to answer that query. - // TODO: this API with the "responder" is bad, but changing it requires modifications in libp2p - KadFindNode { - /// The value being searched. - searched: PeerId, - /// Object to use to respond to the request. - responder: KadFindNodeRespond, - }, - - /// The Kademlia substream has been closed. - /// - /// The parameter contains the reason why it has been closed. `Ok` means that it's been closed - /// gracefully. - KadClosed(Result<(), IoError>), - - /// An error happened while upgrading a substream. - /// - /// This can be used to print a diagnostic message. - SubstreamUpgradeFail(IoError), -} - -/// The remote wants us to send back information. -pub struct IdentificationRequest { - /// Where to store the future that sends back the information. - identify_send_back: Arc + Send>>>>, - /// Object that sends back the information. - sender: identify::IdentifySender, - /// Protocol names that we support, to send back. - protocols: Vec, -} - -impl IdentificationRequest { - /// Responds to the request. - /// - /// - `local_key` must contain our local public key. - /// - `listen_addrs` must contain the list of addresses we're listening on (preferably after - /// NAT traversal). - /// - `remote_addr` must be the address of the remote from our local point of view. - /// - pub fn respond( - self, - local_key: PublicKey, - listen_addrs: Vec, - remote_addr: &Multiaddr - ) where TSubstream: AsyncRead + AsyncWrite + Send + 'static { - // TODO: what to return for `protocol_version` and `agent_version`? - let sender = self.sender.send( - identify::IdentifyInfo { - public_key: local_key, - protocol_version: concat!("substrate/", env!("CARGO_PKG_VERSION")).to_owned(), - agent_version: concat!("substrate/", env!("CARGO_PKG_VERSION")).to_owned(), - listen_addrs, - protocols: self.protocols, - }, - remote_addr - ); - - self.identify_send_back.lock().push(sender); - } -} - -/// Event that can be received by a `SubstrateNodeHandler`. -#[derive(Debug, Clone)] -pub enum SubstrateInEvent { - /// Before anything happens on the node, we wait for an `Accept` event. This is used to deny - /// nodes based on their peer ID. - Accept, - - /// Sends a message through a custom protocol substream. - SendCustomMessage { - protocol: ProtocolId, - data: Vec, - }, - - /// Requests to open a Kademlia substream. - // TODO: document better - OpenKademlia, -} - -/// Ideally we would have a method on `SubstrateNodeHandler` that builds this type, but in practice it's a -/// bit tedious to express, even with the `impl Trait` syntax. -/// Therefore we simply use a macro instead. -macro_rules! listener_upgrade { - ($self:expr) => ( - upgrade::or(upgrade::or(upgrade::or( - upgrade::map((*$self.registered_custom).clone(), move |c| FinalUpgrade::Custom(c)), - upgrade::map(KadConnecConfig::new(), move |(c, s)| FinalUpgrade::Kad(c, s))), - upgrade::map(ping::protocol::Ping::default(), move |p| FinalUpgrade::from(p))), - upgrade::map(identify::IdentifyProtocolConfig, move |i| FinalUpgrade::from(i))) - // TODO: meh for cloning a Vec here - ) -} - -impl SubstrateNodeHandler -where TSubstream: AsyncRead + AsyncWrite + Send + 'static, -{ - /// Creates a new node handler. - #[inline] - pub fn new(registered_custom: Arc) -> Self { - let registered_custom_len = registered_custom.len(); - let queued_dial_upgrades = registered_custom.0 - .iter() - .map(|proto| UpgradePurpose::Custom(proto.id())) - .collect(); - - SubstrateNodeHandler { - custom_protocols_substreams: Vec::with_capacity(registered_custom_len), - kademlia_substream: None, - need_report_kad_open: false, - identify_send_back: Arc::new(Mutex::new(Vec::with_capacity(1))), - ping_in_substreams: Vec::with_capacity(1), - ping_out_substream: None, - active_ping_out: None, - registered_custom, - upgrades_in_progress_listen: Vec::with_capacity(registered_custom_len + 3), - upgrades_in_progress_dial: Vec::with_capacity(registered_custom_len + 3), - next_ping: Delay::new(Instant::now() + DELAY_TO_FIRST_PING), - next_identify: Interval::new(Instant::now() + DELAY_TO_FIRST_IDENTIFY, PERIOD_IDENTIFY), - queued_dial_upgrades, - num_out_user_must_open: registered_custom_len, - is_shutting_down: false, - to_notify: None, - } - } -} - -impl NodeHandler for SubstrateNodeHandler -where TSubstream: AsyncRead + AsyncWrite + Send + 'static, -{ - type InEvent = SubstrateInEvent; - type OutEvent = SubstrateOutEvent; - type OutboundOpenInfo = (); - type Substream = TSubstream; - - fn inject_substream(&mut self, substream: TSubstream, endpoint: NodeHandlerEndpoint) { - // For listeners, propose all the possible upgrades. - if endpoint == NodeHandlerEndpoint::Listener { - let listener_upgrade = listener_upgrade!(self); - let upgrade = upgrade::apply(substream, listener_upgrade, Endpoint::Listener); - self.upgrades_in_progress_listen.push(Box::new(upgrade) as Box<_>); - // Since we pushed to `upgrades_in_progress_listen`, we have to notify the task. - if let Some(task) = self.to_notify.take() { - task.notify(); - } - return; - } - - // If we're the dialer, we have to decide which upgrade we want. - let purpose = if self.queued_dial_upgrades.is_empty() { - // Since we sometimes remove elements from `queued_dial_upgrades` before they succeed - // but after the outbound substream has started opening, it is possible that the queue - // is empty when we receive a substream. This is not an error. - // Example: we want to open a Kademlia substream, we start opening one, but in the - // meanwhile the remote opens a Kademlia substream. When we receive the new substream, - // we don't need it anymore. - return; - } else { - self.queued_dial_upgrades.remove(0) - }; - - match purpose { - UpgradePurpose::Custom(id) => { - let wanted = if let Some(proto) = self.registered_custom.find_protocol(id) { - // TODO: meh for cloning - upgrade::map(proto.clone(), move |c| FinalUpgrade::Custom(c)) - } else { - error!(target: "sub-libp2p", "Logic error: wrong custom protocol id for \ - opened substream"); - return; - }; - - let upgrade = upgrade::apply(substream, wanted, Endpoint::Dialer); - self.upgrades_in_progress_dial.push((purpose, Box::new(upgrade) as Box<_>)); - } - UpgradePurpose::Kad => { - let wanted = upgrade::map(KadConnecConfig::new(), move |(c, s)| FinalUpgrade::Kad(c, s)); - let upgrade = upgrade::apply(substream, wanted, Endpoint::Dialer); - self.upgrades_in_progress_dial.push((purpose, Box::new(upgrade) as Box<_>)); - } - UpgradePurpose::Identify => { - let wanted = upgrade::map(identify::IdentifyProtocolConfig, move |i| FinalUpgrade::from(i)); - let upgrade = upgrade::apply(substream, wanted, Endpoint::Dialer); - self.upgrades_in_progress_dial.push((purpose, Box::new(upgrade) as Box<_>)); - } - UpgradePurpose::Ping => { - let wanted = upgrade::map(ping::protocol::Ping::default(), move |p| FinalUpgrade::from(p)); - let upgrade = upgrade::apply(substream, wanted, Endpoint::Dialer); - self.upgrades_in_progress_dial.push((purpose, Box::new(upgrade) as Box<_>)); - } - }; - - // Since we pushed to `upgrades_in_progress_dial`, we have to notify the task. - if let Some(task) = self.to_notify.take() { - task.notify(); - } - } - - #[inline] - fn inject_inbound_closed(&mut self) { - } - - #[inline] - fn inject_outbound_closed(&mut self, _: Self::OutboundOpenInfo) { - } - - fn inject_event(&mut self, event: Self::InEvent) { - match event { - SubstrateInEvent::SendCustomMessage { protocol, data } => { - self.send_custom_message(protocol, data); - }, - SubstrateInEvent::OpenKademlia => self.open_kademlia(), - SubstrateInEvent::Accept => { - // TODO: implement - }, - } - } - - fn shutdown(&mut self) { - // TODO: close gracefully - self.is_shutting_down = true; - - for custom_proto in &mut self.custom_protocols_substreams { - custom_proto.shutdown(); - } - - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - } - - fn poll(&mut self) -> Poll>, IoError> { - if self.is_shutting_down { - // TODO: finish only when everything is closed - return Ok(Async::Ready(None)); - } - - match self.poll_upgrades_in_progress()? { - Async::Ready(value) => return Ok(Async::Ready(value.map(NodeHandlerEvent::Custom))), - Async::NotReady => (), - }; - - match self.poll_custom_protocols()? { - Async::Ready(value) => return Ok(Async::Ready(value.map(NodeHandlerEvent::Custom))), - Async::NotReady => (), - }; - - match self.poll_kademlia()? { - Async::Ready(value) => return Ok(Async::Ready(value.map(NodeHandlerEvent::Custom))), - Async::NotReady => (), - }; - - match self.poll_ping()? { - Async::Ready(value) => return Ok(Async::Ready(value.map(NodeHandlerEvent::Custom))), - Async::NotReady => (), - }; - - match self.poll_identify()? { - Async::Ready(value) => return Ok(Async::Ready(value.map(NodeHandlerEvent::Custom))), - Async::NotReady => (), - }; - - // Request new outbound substreams from the user if necessary. - if self.num_out_user_must_open >= 1 { - self.num_out_user_must_open -= 1; - return Ok(Async::Ready(Some(NodeHandlerEvent::OutboundSubstreamRequest(())))); - } - - // Nothing happened. Register our task to be notified and return. - self.to_notify = Some(task::current()); - Ok(Async::NotReady) - } -} - -impl SubstrateNodeHandler -where TSubstream: AsyncRead + AsyncWrite + Send + 'static, -{ - /// Sends a message on a custom protocol substream. - fn send_custom_message( - &mut self, - protocol: ProtocolId, - data: Vec, - ) { - debug_assert!(self.registered_custom.has_protocol(protocol), - "invalid protocol id requested in the API of the libp2p networking"); - let proto = match self.custom_protocols_substreams.iter_mut().find(|p| p.protocol_id() == protocol) { - Some(proto) => proto, - None => { - // We are processing a message event before we could report to the outside that - // we disconnected from the protocol. This is not an error. - return - }, - }; - - proto.send_message(data.into()); - } - - /// The node will try to open a Kademlia substream and produce a `KadOpen` event containing the - /// controller. If a Kademlia substream is already open, produces the event immediately. - fn open_kademlia(&mut self) { - if self.kademlia_substream.is_some() { - self.need_report_kad_open = true; - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - } else if self.has_upgrade_purpose(&UpgradePurpose::Kad) { - // We are currently upgrading a substream to Kademlia ; nothing more to do except wait. - } else { - // Opening a new substream for Kademlia. - self.queued_dial_upgrades.push(UpgradePurpose::Kad); - self.num_out_user_must_open += 1; - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - } - } - - /// Returns true if we are currently upgrading to the given protocol. - fn has_upgrade_purpose(&self, purpose: &UpgradePurpose) -> bool { - self.upgrades_in_progress_dial.iter().any(|&(ref p, _)| p == purpose) || - self.queued_dial_upgrades.iter().any(|p| p == purpose) - } - - /// Cancels a dialing upgrade in progress. - /// - /// Useful when the listener opened the protocol we wanted. - fn cancel_dial_upgrade(&mut self, purpose: &UpgradePurpose) { - self.upgrades_in_progress_dial.retain(|&(purp, _)| &purp != purpose); - self.queued_dial_upgrades.retain(|u| u != purpose); - } - - /// Returns the names of the protocols that we supporitt. - fn supported_protocol_names(&self) -> Vec { - let list = listener_upgrade!(self); - ConnectionUpgrade::::protocol_names(&list) - .filter_map(|(n, _)| String::from_utf8(n.to_vec()).ok()) - .collect() - } - - /// Inject a fully negotiated substream into the state. - /// - /// Optionally produces an event to dispatch. - fn inject_fully_negotiated( - &mut self, - upgrade: FinalUpgrade - ) -> Option> { - match upgrade { - FinalUpgrade::IdentifyListener(sender) => - Some(SubstrateOutEvent::IdentificationRequest(IdentificationRequest { - sender, - identify_send_back: self.identify_send_back.clone(), - protocols: self.supported_protocol_names(), - })), - FinalUpgrade::IdentifyDialer(info, observed_addr) => { - self.cancel_dial_upgrade(&UpgradePurpose::Identify); - Some(SubstrateOutEvent::Identified { info, observed_addr }) - }, - FinalUpgrade::PingDialer(ping_dialer) => { - self.cancel_dial_upgrade(&UpgradePurpose::Ping); - // We always open the ping substream for a reason, which is to immediately ping. - self.ping_out_substream = Some(ping_dialer); - self.active_ping_out = None; - if self.ping_remote() { - Some(SubstrateOutEvent::PingStart) - } else { - None - } - }, - FinalUpgrade::PingListener(ping_listener) => { - self.ping_in_substreams.push(ping_listener); - None - }, - FinalUpgrade::Kad(controller, stream) => { - // Remove all upgrades in the progress for Kademlia. - self.cancel_dial_upgrade(&UpgradePurpose::Kad); - // Refuse the substream if we already have Kademlia substream open. - if self.kademlia_substream.is_none() { - self.kademlia_substream = Some((controller.clone(), stream)); - Some(SubstrateOutEvent::KadOpen(controller)) - } else { - None - } - }, - FinalUpgrade::Custom(proto) => { - self.cancel_dial_upgrade(&UpgradePurpose::Custom(proto.protocol_id())); - if self.custom_protocols_substreams.iter().any(|p| p.protocol_id() == proto.protocol_id()) { - // Skipping protocol that's already open. - return None; - } - - let event = SubstrateOutEvent::CustomProtocolOpen { - protocol_id: proto.protocol_id(), - version: proto.protocol_version(), - }; - - self.custom_protocols_substreams.push(proto); - Some(event) - }, - } - } - - /// Start the process of identifying the remote. - fn identify_remote(&mut self) { - if !self.has_upgrade_purpose(&UpgradePurpose::Identify) { - self.queued_dial_upgrades.push(UpgradePurpose::Identify); - self.num_out_user_must_open += 1; - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - } - } - - /// Start the process of pinging the remote. - /// - /// Doesn't do anything if a ping attempt is already in progress. - /// - /// Returns true if this actually starts a ping, false is this just opens a substream or does - /// nothing. - fn ping_remote(&mut self) -> bool { - // Ignore if we are already actively pinging. - if self.active_ping_out.is_some() { - return false; - } - - // If we have a ping open, ping it! - if let Some(ref mut pinger) = self.ping_out_substream { - let now = Instant::now(); - pinger.ping(now); - let future = Delay::new(now + PING_TIMEOUT); - self.active_ping_out = Some(future); - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - return true; - } - - // Otherwise, ensure we have an upgrade for a ping substream in queue. - if !self.has_upgrade_purpose(&UpgradePurpose::Ping) { - self.queued_dial_upgrades.push(UpgradePurpose::Ping); - self.num_out_user_must_open += 1; - // We also start the unresponsiveness counter when opening the substream, as a - // peer may not respond to our opening request. - let future = Delay::new(Instant::now() + PING_TIMEOUT); - self.active_ping_out = Some(future); - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - } - - false - } - - /// Polls the upgrades in progress. - fn poll_upgrades_in_progress(&mut self) -> Poll>, IoError> { - // Continue negotiation of newly-opened substreams on the listening side. - // We remove each element from `upgrades_in_progress_listen` one by one and add them back - // if not ready. - for n in (0 .. self.upgrades_in_progress_listen.len()).rev() { - let mut in_progress = self.upgrades_in_progress_listen.swap_remove(n); - match in_progress.poll() { - Ok(Async::Ready(upgrade)) => { - if let Some(event) = self.inject_fully_negotiated(upgrade) { - return Ok(Async::Ready(Some(event))); - } - }, - Ok(Async::NotReady) => { - self.upgrades_in_progress_listen.push(in_progress); - }, - Err(err) => { - return Ok(Async::Ready(Some(SubstrateOutEvent::SubstreamUpgradeFail(err)))); - }, - } - } - - // Continue negotiation of newly-opened substreams. - // We remove each element from `upgrades_in_progress_dial` one by one and add them back if - // not ready. - for n in (0 .. self.upgrades_in_progress_dial.len()).rev() { - let (purpose, mut in_progress) = self.upgrades_in_progress_dial.swap_remove(n); - match in_progress.poll() { - Ok(Async::Ready(upgrade)) => { - if let Some(event) = self.inject_fully_negotiated(upgrade) { - return Ok(Async::Ready(Some(event))); - } - }, - Ok(Async::NotReady) => - self.upgrades_in_progress_dial.push((purpose, in_progress)), - Err(err) => { - // TODO: dispatch depending on actual error ; right now we assume that - // error == not supported, which is not necessarily true in theory - if let UpgradePurpose::Custom(_) = purpose { - return Ok(Async::Ready(Some(SubstrateOutEvent::Useless))); - } else { - let msg = format!("While upgrading to {:?}: {:?}", purpose, err); - let err = IoError::new(IoErrorKind::Other, msg); - return Ok(Async::Ready(Some(SubstrateOutEvent::SubstreamUpgradeFail(err)))); - } - }, - } - } - - Ok(Async::NotReady) - } - - /// Polls the upgrades in progress. - fn poll_custom_protocols(&mut self) -> Poll>, IoError> { - // Poll for messages on the custom protocol stream. - for n in (0 .. self.custom_protocols_substreams.len()).rev() { - let mut custom_proto = self.custom_protocols_substreams.swap_remove(n); - match custom_proto.poll() { - Ok(Async::NotReady) => self.custom_protocols_substreams.push(custom_proto), - Ok(Async::Ready(Some(data))) => { - let protocol_id = custom_proto.protocol_id(); - self.custom_protocols_substreams.push(custom_proto); - return Ok(Async::Ready(Some(SubstrateOutEvent::CustomMessage { - protocol_id, - data, - }))); - }, - Ok(Async::Ready(None)) => { - // Trying to reopen the protocol. - self.queued_dial_upgrades.push(UpgradePurpose::Custom(custom_proto.protocol_id())); - self.num_out_user_must_open += 1; - return Ok(Async::Ready(Some(SubstrateOutEvent::CustomProtocolClosed { - protocol_id: custom_proto.protocol_id(), - result: Ok(()), - }))) - }, - Err(err) => { - // Trying to reopen the protocol. - self.queued_dial_upgrades.push(UpgradePurpose::Custom(custom_proto.protocol_id())); - self.num_out_user_must_open += 1; - return Ok(Async::Ready(Some(SubstrateOutEvent::CustomProtocolClosed { - protocol_id: custom_proto.protocol_id(), - result: Err(err), - }))) - }, - } - } - - Ok(Async::NotReady) - } - - /// Polls the open Kademlia substream, if any. - fn poll_kademlia(&mut self) -> Poll>, IoError> { - // Produce a `KadOpen` event if necessary. - if self.need_report_kad_open { - self.need_report_kad_open = false; - if let Some((ref kad_ctrl, _)) = self.kademlia_substream { - return Ok(Async::Ready(Some(SubstrateOutEvent::KadOpen(kad_ctrl.clone())))); - } - } - - // Poll for Kademlia events. - if let Some((controller, mut stream)) = self.kademlia_substream.take() { - loop { - match stream.poll() { - Ok(Async::Ready(Some(KadIncomingRequest::FindNode { searched, responder }))) => { - self.kademlia_substream = Some((controller, stream)); - return Ok(Async::Ready(Some(SubstrateOutEvent::KadFindNode { searched, responder }))); - }, - // We don't care about Kademlia pings, they are unused. - Ok(Async::Ready(Some(KadIncomingRequest::PingPong))) => {}, - // Other Kademlia messages are unimplemented. - Ok(Async::Ready(Some(KadIncomingRequest::GetProviders { .. }))) => {}, - Ok(Async::Ready(Some(KadIncomingRequest::AddProvider { .. }))) => {}, - Ok(Async::NotReady) => { - self.kademlia_substream = Some((controller, stream)); - break; - }, - Ok(Async::Ready(None)) => return Ok(Async::Ready(Some(SubstrateOutEvent::KadClosed(Ok(()))))), - Err(err) => return Ok(Async::Ready(Some(SubstrateOutEvent::KadClosed(Err(err))))), - } - } - } - - Ok(Async::NotReady) - } - - /// Polls the ping substreams. - fn poll_ping(&mut self) -> Poll>, IoError> { - // Poll the future that fires when we need to ping the node again. - match self.next_ping.poll() { - Ok(Async::NotReady) => {}, - Ok(Async::Ready(())) => { - // We reset `next_ping` to a very long time in the future so that we can poll - // it again without having an accident. - self.next_ping.reset(Instant::now() + Duration::from_secs(5 * 60)); - if self.ping_remote() { - return Ok(Async::Ready(Some(SubstrateOutEvent::PingStart))); - } - }, - Err(err) => { - warn!(target: "sub-libp2p", "Ping timer errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); - } - } - - // Poll for answering pings. - for n in (0 .. self.ping_in_substreams.len()).rev() { - let mut ping = self.ping_in_substreams.swap_remove(n); - match ping.poll() { - Ok(Async::Ready(())) => {}, - Ok(Async::NotReady) => self.ping_in_substreams.push(ping), - Err(err) => warn!(target: "sub-libp2p", "Remote ping substream errored: {:?}", err), - } - } - - // Poll the ping substream. - if let Some(mut ping_dialer) = self.ping_out_substream.take() { - match ping_dialer.poll() { - Ok(Async::Ready(Some(started))) => { - self.active_ping_out = None; - self.next_ping.reset(Instant::now() + DELAY_TO_NEXT_PING); - return Ok(Async::Ready(Some(SubstrateOutEvent::PingSuccess(started.elapsed())))); - }, - Ok(Async::Ready(None)) => { - // Try re-open ping if it got closed. - self.queued_dial_upgrades.push(UpgradePurpose::Ping); - self.num_out_user_must_open += 1; - }, - Ok(Async::NotReady) => self.ping_out_substream = Some(ping_dialer), - Err(_) => {}, - } - } - - // Poll the active ping attempt. - if let Some(mut deadline) = self.active_ping_out.take() { - match deadline.poll() { - Ok(Async::Ready(())) => - return Ok(Async::Ready(Some(SubstrateOutEvent::Unresponsive))), - Ok(Async::NotReady) => self.active_ping_out = Some(deadline), - Err(err) => { - warn!(target: "sub-libp2p", "Active ping deadline errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); - }, - } - } - - Ok(Async::NotReady) - } - - /// Polls the identify substreams. - fn poll_identify(&mut self) -> Poll>, IoError> { - // Poll the future that fires when we need to identify the node again. - loop { - match self.next_identify.poll() { - Ok(Async::NotReady) => break, - Ok(Async::Ready(Some(_))) => self.identify_remote(), - Ok(Async::Ready(None)) => { - warn!(target: "sub-libp2p", "Identify timer closed unexpectedly"); - return Ok(Async::Ready(None)); - } - Err(err) => { - warn!(target: "sub-libp2p", "Identify timer errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); - } - } - } - - // Poll for sending identify information to the remote. - let mut identify_send_back = self.identify_send_back.lock(); - for n in (0 .. identify_send_back.len()).rev() { - let mut id_send_back = identify_send_back.swap_remove(n); - match id_send_back.poll() { - Ok(Async::Ready(())) => {}, - Ok(Async::NotReady) => identify_send_back.push(id_send_back), - Err(err) => warn!(target: "sub-libp2p", "Sending back identify info errored: {:?}", err), - } - } - - Ok(Async::NotReady) - } -} - -/// Enum of all the possible protocols our service handles. -enum FinalUpgrade { - Kad(KadConnecController, Box + Send>), - IdentifyListener(identify::IdentifySender), - IdentifyDialer(identify::IdentifyInfo, Multiaddr), - PingDialer(ping::protocol::PingDialer), - PingListener(ping::protocol::PingListener), - Custom(RegisteredProtocolSubstream), -} - -impl From> for FinalUpgrade { - fn from(out: ping::protocol::PingOutput) -> Self { - match out { - ping::protocol::PingOutput::Ponger(ponger) => FinalUpgrade::PingListener(ponger), - ping::protocol::PingOutput::Pinger(pinger) => FinalUpgrade::PingDialer(pinger), - } - } -} - -impl From> for FinalUpgrade { - fn from(out: identify::IdentifyOutput) -> Self { - match out { - identify::IdentifyOutput::RemoteInfo { info, observed_addr } => - FinalUpgrade::IdentifyDialer(info, observed_addr), - identify::IdentifyOutput::Sender { sender } => - FinalUpgrade::IdentifyListener(sender), - } - } -} diff --git a/core/network-libp2p/src/secret.rs b/core/network-libp2p/src/secret.rs index 093d67f3d96cefec3be90a59e426f225a7e9be75..f7a25d000c4bd87aefba705c26b34be00d0531b7 100644 --- a/core/network-libp2p/src/secret.rs +++ b/core/network-libp2p/src/secret.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,27 +14,35 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use crate::NetworkConfiguration; use libp2p::secio; -use rand::{self, Rng}; -use std::fs; +use log::{trace, warn}; +use rand::Rng; use std::io::{Error as IoError, ErrorKind as IoErrorKind, Read, Write}; -use std::path::Path; -use NetworkConfiguration; +use std::{fs, path::Path}; // File where the private key is stored. const SECRET_FILE: &str = "secret"; /// Obtains or generates the local private key using the configuration. -pub fn obtain_private_key( +pub fn obtain_private_key_from_config( config: &NetworkConfiguration ) -> Result { - if let Some(ref secret) = config.use_secret { + obtain_private_key(&config.use_secret, &config.net_config_path) +} + +/// Obtains or generates the local private key using the configuration. +pub fn obtain_private_key( + secret: &Option<[u8; 32]>, + net_config_path: &Option, +) -> Result { + if let Some(ref secret) = secret { // Key was specified in the configuration. secio::SecioKeyPair::secp256k1_raw_key(&secret[..]) .map_err(|err| IoError::new(IoErrorKind::InvalidData, err)) - } else { - if let Some(ref path) = config.net_config_path { + if let Some(ref path) = net_config_path { + fs::create_dir_all(Path::new(path))?; // Try fetch the key from a the file containing the secret. let secret_path = Path::new(path).join(SECRET_FILE); match load_private_key_from_file(&secret_path) { diff --git a/core/network-libp2p/src/service_task.rs b/core/network-libp2p/src/service_task.rs index 5fd03caa4b20070b933095337380646f45cfd70d..4cab435c8b6924d9d86f433bf6fe121271847525 100644 --- a/core/network-libp2p/src/service_task.rs +++ b/core/network-libp2p/src/service_task.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,190 +14,116 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use bytes::Bytes; -use custom_proto::{RegisteredProtocol, RegisteredProtocols}; -use fnv::{FnvHashMap, FnvHashSet}; -use futures::{prelude::*, task, Stream}; -use futures::sync::{oneshot, mpsc}; -use libp2p::{Multiaddr, PeerId}; -use libp2p::core::{Endpoint, PublicKey}; +use crate::{ + behaviour::Behaviour, behaviour::BehaviourOut, secret::obtain_private_key_from_config, + transport, NetworkState, NetworkStatePeer, NetworkStateNotConnectedPeer +}; +use crate::custom_proto::{CustomMessage, RegisteredProtocol, RegisteredProtocols}; +use crate::{NetworkConfiguration, NodeIndex, ProtocolId, parse_str_addr}; +use fnv::FnvHashMap; +use futures::{prelude::*, Stream}; +use libp2p::{multiaddr::Protocol, Multiaddr, PeerId}; +use libp2p::core::{Swarm, nodes::Substream, transport::boxed::Boxed, muxing::StreamMuxerBox}; use libp2p::core::nodes::ConnectedPoint; -use libp2p::kad::{KadSystem, KadSystemConfig, KadConnecController, KadPeer}; -use libp2p::kad::{KadConnectionType, KadQueryEvent}; -use parking_lot::Mutex; -use rand; -use secret::obtain_private_key; +use log::{debug, error, info, warn}; +use std::collections::hash_map::Entry; use std::fs; use std::io::{Error as IoError, ErrorKind as IoErrorKind}; -use std::iter; -use std::net::SocketAddr; use std::path::Path; use std::sync::Arc; use std::time::{Duration, Instant}; -use swarm::{self, Swarm, SwarmEvent}; -use topology::{DisconnectReason, NetTopology}; -use tokio_timer::{Delay, Interval}; -use {Error, ErrorKind, NetworkConfiguration, NodeIndex, parse_str_addr}; -use {NonReservedPeerMode, ProtocolId}; - -// File where the network topology is stored. -const NODES_FILE: &str = "nodes.json"; -// Duration during which a peer is disabled. -const PEER_DISABLE_DURATION: Duration = Duration::from_secs(5 * 60); +use tokio_timer::Interval; /// Starts the substrate libp2p service. /// /// Returns a stream that must be polled regularly in order for the networking to function. -pub fn start_service( +pub fn start_service( config: NetworkConfiguration, registered_custom: TProtos, -) -> Result -where TProtos: IntoIterator { +) -> Result, IoError> +where TProtos: IntoIterator>, + TMessage: CustomMessage + Send + 'static { if let Some(ref path) = config.net_config_path { - fs::create_dir_all(Path::new(path))?; + fs::create_dir_all(Path::new(path))?; } // Private and public keys configuration. - let local_private_key = obtain_private_key(&config)?; + let local_private_key = obtain_private_key_from_config(&config)?; let local_public_key = local_private_key.to_public_key(); let local_peer_id = local_public_key.clone().into_peer_id(); // Build the swarm. - let registered_custom = RegisteredProtocols(registered_custom.into_iter().collect()); - let mut swarm = swarm::start_swarm(registered_custom, local_private_key)?; + let (mut swarm, bandwidth) = { + let registered_custom = RegisteredProtocols(registered_custom.into_iter().collect()); + let behaviour = Behaviour::new(&config, local_public_key.clone(), registered_custom); + let (transport, bandwidth) = transport::build_transport(local_private_key); + (Swarm::new(transport, behaviour, local_peer_id.clone()), bandwidth) + }; // Listen on multiaddresses. for addr in &config.listen_addresses { - match swarm.listen_on(addr.clone()) { - Ok(new_addr) => debug!(target: "sub-libp2p", "Libp2p listening on {}", new_addr), - Err(_) => { - warn!(target: "sub-libp2p", "Can't listen on {}, protocol not supported", addr); - return Err(ErrorKind::BadProtocol.into()) + match Swarm::listen_on(&mut swarm, addr.clone()) { + Ok(mut new_addr) => { + new_addr.append(Protocol::P2p(local_peer_id.clone().into())); + info!(target: "sub-libp2p", "Local node address is: {}", new_addr); }, + Err(err) => warn!(target: "sub-libp2p", "Can't listen on {} because: {:?}", addr, err) } } - // Register the external addresses provided by the user. + // Add external addresses. for addr in &config.public_addresses { - swarm.add_external_address(addr.clone()); + Swarm::add_external_address(&mut swarm, addr.clone()); } - // Initialize the topology of the network. - let mut topology = if let Some(ref path) = config.net_config_path { - let path = Path::new(path).join(NODES_FILE); - debug!(target: "sub-libp2p", "Initializing peer store for JSON file {:?}", path); - NetTopology::from_file(path) - } else { - debug!(target: "sub-libp2p", "No peers file configured ; peers won't be saved"); - NetTopology::memory() - }; - - // Create the Kademlia system, containing the kbuckets. - let kad_system = KadSystem::without_init(KadSystemConfig { - parallelism: 3, - local_peer_id, - kbuckets_timeout: Duration::from_secs(600), - request_timeout: Duration::from_secs(10), - known_initial_peers: iter::empty(), - }); - - // Add the bootstrap nodes to the topology and connect to them. + // Connect to the bootnodes. for bootnode in config.boot_nodes.iter() { match parse_str_addr(bootnode) { - Ok((peer_id, addr)) => { - topology.add_bootstrap_addr(&peer_id, addr.clone()); - kad_system.update_kbuckets(peer_id.clone()); - if let Err(_) = swarm.ensure_connection(peer_id, addr) { - warn!(target: "sub-libp2p", "Failed to dial boot node: {}", bootnode); - } - }, - Err(_) => { - // If the format of the bootstrap node is not a multiaddr, try to parse it as - // a `SocketAddr`. This corresponds to the format `IP:PORT`. - let addr = match bootnode.parse::() { - Ok(SocketAddr::V4(socket)) => multiaddr![Ip4(*socket.ip()), Tcp(socket.port())], - Ok(SocketAddr::V6(socket)) => multiaddr![Ip6(*socket.ip()), Tcp(socket.port())], - _ => { - warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode); - continue; - } - }; - - debug!(target: "sub-libp2p", "Dialing {} with no peer id", addr); - if let Err(addr) = swarm.dial(addr) { - warn!(target: "sub-libp2p", "Bootstrap address not supported: {}", addr); - } - }, + Ok((peer_id, _)) => Swarm::dial(&mut swarm, peer_id), + Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode), } } // Initialize the reserved peers. - let mut reserved_peers = FnvHashSet::default(); for reserved in config.reserved_nodes.iter() { - match parse_str_addr(reserved) { - Ok((peer_id, addr)) => { - reserved_peers.insert(peer_id.clone()); - topology.add_bootstrap_addr(&peer_id, addr.clone()); - if let Err(_) = swarm.ensure_connection(peer_id, addr) { - warn!(target: "sub-libp2p", "Failed to dial reserved node: {}", reserved); - } - }, - Err(_) => - // TODO: also handle the `IP:PORT` format ; however we need to somehow add the - // reserved ID to `reserved_peers` at some point - warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved), + if let Ok((peer_id, addr)) = parse_str_addr(reserved) { + swarm.add_reserved_peer(peer_id.clone(), addr); + Swarm::dial(&mut swarm, peer_id); + } else { + warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved); } } - debug!(target: "sub-libp2p", "Topology started with {} entries", topology.num_peers()); - - let (kad_new_ctrl_req_tx, kad_new_ctrl_req_rx) = mpsc::unbounded(); + debug!(target: "sub-libp2p", "Topology started with {} entries", + swarm.num_topology_peers()); Ok(Service { swarm, - max_incoming_connections: config.in_peers as usize, - max_outgoing_connections: config.out_peers as usize, - topology, - nodes_addresses: Default::default(), - disabled_peers: Default::default(), - reserved_peers, - reserved_only: config.non_reserved_mode == NonReservedPeerMode::Deny, - kad_system, - kad_pending_ctrls: Default::default(), - kad_new_ctrl_req_tx, - kad_new_ctrl_req_rx, - kad_queries: Vec::with_capacity(1), - next_connect_to_nodes: Delay::new(Instant::now()), - next_kad_random_query: Interval::new(Instant::now() + Duration::from_secs(5), Duration::from_secs(45)), + bandwidth, + nodes_info: Default::default(), + index_by_id: Default::default(), + next_node_id: 1, cleanup: Interval::new_interval(Duration::from_secs(60)), injected_events: Vec::new(), - to_notify: None, }) } /// Event produced by the service. #[derive(Debug)] -pub enum ServiceEvent { - /// Closed connection to a node. - /// - /// It is guaranteed that this node has been opened with a `NewNode` event beforehand. However - /// not all `ClosedCustomProtocol` events have been dispatched. - NodeClosed { - /// Index of the node. - node_index: NodeIndex, - /// List of custom protocols that were still open. - closed_custom_protocols: Vec, - }, - +pub enum ServiceEvent { /// A custom protocol substream has been opened with a node. OpenedCustomProtocol { + /// The Id of the node. + peer_id: PeerId, /// Index of the node. node_index: NodeIndex, /// Protocol that has been opened. protocol: ProtocolId, /// Version of the protocol that was opened. version: u8, + /// Node debug info + debug_info: String, }, /// A custom protocol substream has been closed. @@ -206,6 +132,8 @@ pub enum ServiceEvent { node_index: NodeIndex, /// Protocol that has been closed. protocol: ProtocolId, + /// Node debug info + debug_info: String, }, /// Sustom protocol substreams has been closed. @@ -216,6 +144,8 @@ pub enum ServiceEvent { node_index: NodeIndex, /// Protocols that have been closed. protocols: Vec, + /// Node debug info + debug_info: String, }, /// Receives a message on a custom protocol stream. @@ -224,164 +154,200 @@ pub enum ServiceEvent { node_index: NodeIndex, /// Protocol which generated the message. protocol_id: ProtocolId, - /// Data that has been received. - data: Bytes, + /// Message that has been received. + message: TMessage, + }, + + /// The substream with a node is clogged. We should avoid sending data to it if possible. + Clogged { + /// Index of the node. + node_index: NodeIndex, + /// Protocol which generated the message. + protocol_id: ProtocolId, + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec, }, } /// Network service. Must be polled regularly in order for the networking to work. -pub struct Service { +pub struct Service where TMessage: CustomMessage { /// Stream of events of the swarm. - swarm: Swarm, - - /// Maximum number of incoming non-reserved connections, taken from the config. - max_incoming_connections: usize, + swarm: Swarm, Behaviour>>, - /// Maximum number of outgoing non-reserved connections, taken from the config. - max_outgoing_connections: usize, + /// Bandwidth logging system. Can be queried to know the average bandwidth consumed. + bandwidth: Arc, - /// For each node we're connected to, how we're connected to it. - nodes_addresses: FnvHashMap, + /// Information about all the nodes we're connected to. + nodes_info: FnvHashMap, - /// If true, only reserved peers can connect. - reserved_only: bool, + /// Opposite of `nodes_info`. + index_by_id: FnvHashMap, - /// List of the IDs of the reserved peers. - reserved_peers: FnvHashSet, - - /// List of the IDs of disabled peers, and when the ban expires. - /// Purged at a regular interval. - disabled_peers: FnvHashMap, - - /// Topology of the network. - topology: NetTopology, - - /// Handles the Kademlia queries. - // TODO: put the kbuckets in the topology instead - kad_system: KadSystem, - - /// List of Kademlia controller we want to open. - /// - /// A clone of tihs `Arc` is stored in each Kademlia query stream. - // TODO: use a better container? - kad_pending_ctrls: Arc>>>>, - - /// Sender whenever we inserted an entry in `kad_pending_ctrls`, so that we can process it. - kad_new_ctrl_req_tx: mpsc::UnboundedSender, - /// Receiver side of `kad_new_ctrl_req_tx`. - kad_new_ctrl_req_rx: mpsc::UnboundedReceiver, - - /// Active Kademlia queries. - kad_queries: Vec>, Error = IoError> + Send>>, - - /// Future that will fire when we need to connect to new nodes. - next_connect_to_nodes: Delay, - - /// Stream that fires when we need to perform the next Kademlia query. - next_kad_random_query: Interval, + /// Next index to assign to a node. + next_node_id: NodeIndex, /// Stream that fires when we need to cleanup and flush the topology, and cleanup the disabled /// peers. cleanup: Interval, /// Events to produce on the Stream. - injected_events: Vec, + injected_events: Vec>, +} - /// Task to notify when elements are added to `injected_events`. - to_notify: Option, +/// Information about a node we're connected to. +#[derive(Debug)] +struct NodeInfo { + /// Hash of the public key of the node. + peer_id: PeerId, + /// How we're connected to the node. + endpoint: ConnectedPoint, + /// Version reported by the remote, or `None` if unknown. + client_version: Option, + /// Latest ping time with this node. + latest_ping: Option, } -impl Service { - /// Returns an iterator that produces the list of addresses we're listening on. +impl Service +where TMessage: CustomMessage + Send + 'static { + /// Returns a struct containing tons of useful information about the network. + pub fn state(&mut self) -> NetworkState { + let now = Instant::now(); + + let connected_peers = { + let swarm = &mut self.swarm; + self.nodes_info.values().map(move |info| { + let known_addresses = swarm.known_addresses(&info.peer_id) + .map(|(a, s)| (a.clone(), s)).collect(); + + (info.peer_id.to_base58(), NetworkStatePeer { + endpoint: info.endpoint.clone().into(), + version_string: info.client_version.clone(), + latest_ping_time: info.latest_ping, + enabled: swarm.is_enabled(&info.peer_id), + open_protocols: swarm.open_protocols(&info.peer_id).collect(), + known_addresses, + }) + }).collect() + }; + + let not_connected_peers = { + let swarm = &mut self.swarm; + let index_by_id = &self.index_by_id; + let list = swarm.known_peers().filter(|p| !index_by_id.contains_key(p)) + .cloned().collect::>(); + list.into_iter().map(move |peer_id| { + let known_addresses = swarm.known_addresses(&peer_id) + .map(|(a, s)| (a.clone(), s)).collect(); + (peer_id.to_base58(), NetworkStateNotConnectedPeer { + known_addresses, + }) + }).collect() + }; + + NetworkState { + peer_id: Swarm::local_peer_id(&self.swarm).to_base58(), + listened_addresses: Swarm::listeners(&self.swarm).cloned().collect(), + reserved_peers: self.swarm.reserved_peers().map(|p| p.to_base58()).collect(), + banned_peers: self.swarm.banned_nodes().map(|(p, until)| { + let dur = if until > now { until - now } else { Duration::new(0, 0) }; + (p.to_base58(), dur.as_secs()) + }).collect(), + is_reserved_only: self.swarm.is_reserved_only(), + average_download_per_sec: self.bandwidth.average_download_per_sec(), + average_upload_per_sec: self.bandwidth.average_upload_per_sec(), + connected_peers, + not_connected_peers, + } + } + + /// Returns an iterator that produces the list of addresses we're listening on. #[inline] pub fn listeners(&self) -> impl Iterator { - self.swarm.listeners() + Swarm::listeners(&self.swarm) + } + + /// Returns the downloaded bytes per second averaged over the past few seconds. + #[inline] + pub fn average_download_per_sec(&self) -> u64 { + self.bandwidth.average_download_per_sec() + } + + /// Returns the uploaded bytes per second averaged over the past few seconds. + #[inline] + pub fn average_upload_per_sec(&self) -> u64 { + self.bandwidth.average_upload_per_sec() } /// Returns the peer id of the local node. #[inline] pub fn peer_id(&self) -> &PeerId { - self.kad_system.local_peer_id() + Swarm::local_peer_id(&self.swarm) } /// Returns the list of all the peers we are connected to. #[inline] pub fn connected_peers<'a>(&'a self) -> impl Iterator + 'a { - self.nodes_addresses.keys().cloned() + self.nodes_info.keys().cloned() } /// Try to add a reserved peer. pub fn add_reserved_peer(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.reserved_peers.insert(peer_id.clone()); - self.topology.add_bootstrap_addr(&peer_id, addr.clone()); - let _ = self.swarm.ensure_connection(peer_id, addr); + self.swarm.add_reserved_peer(peer_id, addr); } /// Try to remove a reserved peer. /// /// If we are in reserved mode and we were connected to a node with this peer ID, then this - /// method will disconnect it and return its index. - pub fn remove_reserved_peer(&mut self, peer_id: PeerId) -> Option { - self.reserved_peers.remove(&peer_id); - if self.reserved_only { - if let Some(node_index) = self.swarm.latest_node_by_peer_id(&peer_id) { - self.drop_node_inner(node_index, DisconnectReason::NoSlot, None); - return Some(node_index); - } - } - None + /// method will disconnect it. + pub fn remove_reserved_peer(&mut self, peer_id: PeerId) { + self.swarm.remove_reserved_peer(peer_id); } /// Start accepting all peers again if we weren't. + #[inline] pub fn accept_unreserved_peers(&mut self) { - if self.reserved_only { - self.reserved_only = false; - self.connect_to_nodes(); - } + self.swarm.accept_unreserved_peers(); } - /// Start refusing non-reserved nodes. Returns the list of nodes that have been disconnected. - pub fn deny_unreserved_peers(&mut self) -> Vec { - self.reserved_only = true; - - // Disconnect the nodes that are not reserved. - let to_disconnect: Vec = self.swarm - .nodes() - .filter(|&n| { - let peer_id = self.swarm.peer_id_of_node(n) - .expect("swarm.nodes() always returns valid node indices"); - !self.reserved_peers.contains(peer_id) - }) - .collect(); - - for &node_index in &to_disconnect { - self.drop_node_inner(node_index, DisconnectReason::NoSlot, None); - } - - to_disconnect + /// Start refusing non-reserved nodes. Disconnects the nodes that we are connected to that + /// aren't reserved. + pub fn deny_unreserved_peers(&mut self) { + self.swarm.deny_unreserved_peers(); } /// Returns the `PeerId` of a node. #[inline] pub fn peer_id_of_node(&self, node_index: NodeIndex) -> Option<&PeerId> { - self.swarm.peer_id_of_node(node_index) + self.nodes_info.get(&node_index).map(|info| &info.peer_id) } /// Returns the way we are connected to a node. #[inline] pub fn node_endpoint(&self, node_index: NodeIndex) -> Option<&ConnectedPoint> { - self.nodes_addresses.get(&node_index) + self.nodes_info.get(&node_index).map(|info| &info.endpoint) + } + + /// Returns the client version reported by a node. + pub fn node_client_version(&self, node_index: NodeIndex) -> Option<&str> { + self.nodes_info.get(&node_index) + .and_then(|info| info.client_version.as_ref().map(|s| &s[..])) } /// Sends a message to a peer using the custom protocol. - // TODO: report invalid node index or protocol? + /// + /// Has no effect if the connection to the node has been closed, or if the node index is + /// invalid. pub fn send_custom_message( &mut self, node_index: NodeIndex, protocol: ProtocolId, - data: Vec + message: TMessage ) { - self.swarm.send_custom_message(node_index, protocol, data) + if let Some(peer_id) = self.nodes_info.get(&node_index).map(|info| &info.peer_id) { + self.swarm.send_custom_message(peer_id, protocol, message); + } else { + warn!(target: "sub-libp2p", "Tried to send message to unknown node: {:}", node_index); + } } /// Disconnects a peer and bans it for a little while. @@ -389,11 +355,11 @@ impl Service { /// Same as `drop_node`, except that the same peer will not be able to reconnect later. #[inline] pub fn ban_node(&mut self, node_index: NodeIndex) { - if let Some(peer_id) = self.swarm.peer_id_of_node(node_index) { - info!(target: "sub-libp2p", "Banned {:?}", peer_id); + if let Some(info) = self.nodes_info.get(&node_index) { + info!(target: "sub-libp2p", "Banned {:?} (#{:?}, {:?}, {:?})", info.peer_id, + node_index, info.endpoint, info.client_version); + self.swarm.ban_node(info.peer_id.clone()); } - - self.drop_node_inner(node_index, DisconnectReason::Banned, Some(PEER_DISABLE_DURATION)); } /// Disconnects a peer. @@ -402,569 +368,160 @@ impl Service { /// Corresponding closing events will be generated once the closing actually happens. #[inline] pub fn drop_node(&mut self, node_index: NodeIndex) { - if let Some(peer_id) = self.swarm.peer_id_of_node(node_index) { - info!(target: "sub-libp2p", "Dropped {:?}", peer_id); - } - - self.drop_node_inner(node_index, DisconnectReason::Useless, None); - } - - /// Common implementation of `drop_node` and `ban_node`. - fn drop_node_inner( - &mut self, - node_index: NodeIndex, - reason: DisconnectReason, - disable_duration: Option - ) { - let peer_id = match self.swarm.peer_id_of_node(node_index) { - Some(pid) => pid.clone(), - None => return, // TODO: report? - }; - - // Kill the node from the swarm, and inject an event about it. - let closed_custom_protocols = self.swarm.drop_node(node_index) - .expect("we checked right above that node is valid"); - self.injected_events.push(ServiceEvent::NodeClosed { - node_index, - closed_custom_protocols, - }); - - if let Some(to_notify) = self.to_notify.take() { - to_notify.notify(); - } - - if let Some(ConnectedPoint::Dialer { address }) = self.nodes_addresses.remove(&node_index) { - self.topology.report_disconnected(&address, reason); - } - - if let Some(disable_duration) = disable_duration { - let timeout = Instant::now() + disable_duration; - self.disabled_peers.insert(peer_id, timeout); - } - - self.connect_to_nodes(); - } - - /// Counts the number of non-reserved ingoing connections. - fn num_ingoing_connections(&self) -> usize { - self.swarm.nodes() - .filter(|&i| self.swarm.node_endpoint(i) == Some(Endpoint::Listener) && - !self.reserved_peers.contains(&self.swarm.peer_id_of_node(i).unwrap())) - .count() - } - - /// Counts the number of non-reserved outgoing connections. - fn num_outgoing_connections(&self) -> usize { - self.swarm.nodes() - .filter(|&i| self.swarm.node_endpoint(i) == Some(Endpoint::Dialer) && - !self.reserved_peers.contains(&self.swarm.peer_id_of_node(i).unwrap())) - .count() - } - - /// Updates the attempted connections to nodes. - /// - /// Also updates `next_connect_to_nodes` with the earliest known moment when we need to - /// update connections again. - fn connect_to_nodes(&mut self) { - // Make sure we are connected or connecting to all the reserved nodes. - for reserved in self.reserved_peers.iter() { - let addrs = self.topology.addrs_of_peer(&reserved); - for (addr, _) in addrs { - let _ = self.swarm.ensure_connection(reserved.clone(), addr.clone()); - } - } - - // Counter of number of connections to open, decreased when we open one. - let mut num_to_open = self.max_outgoing_connections - self.num_outgoing_connections(); - - let (to_try, will_change) = self.topology.addrs_to_attempt(); - for (peer_id, addr) in to_try { - if num_to_open == 0 { - break; - } - - if peer_id == self.kad_system.local_peer_id() { - continue; - } - - if self.disabled_peers.contains_key(&peer_id) { - continue; - } - - // It is possible that we are connected to this peer, but the topology doesn't know - // about that because it is an incoming connection. - match self.swarm.ensure_connection(peer_id.clone(), addr.clone()) { - Ok(true) => (), - Ok(false) => num_to_open -= 1, - Err(_) => () - } + if let Some(info) = self.nodes_info.get(&node_index) { + debug!(target: "sub-libp2p", "Dropping {:?} on purpose (#{:?}, {:?}, {:?})", + info.peer_id, node_index, info.endpoint, info.client_version); + self.swarm.drop_node(&info.peer_id); } - - self.next_connect_to_nodes.reset(will_change); - } - - /// Starts a random Kademlia query in order to fill the topology. - /// - /// Query the node IDs that are closest to a random ID. - /// Note that the randomness doesn't have to be secure, as this only influences which nodes we - /// end up being connected to. - fn perform_kad_random_query(&mut self) { - let random_key = PublicKey::Ed25519((0 .. 32) - .map(|_| -> u8 { rand::random() }).collect()); - let random_peer_id = random_key.into_peer_id(); - debug!(target: "sub-libp2p", "Start random Kademlia query for {:?}", random_peer_id); - - let kad_pending_ctrls = self.kad_pending_ctrls.clone(); - let kad_new_ctrl_req_tx = self.kad_new_ctrl_req_tx.clone(); - let stream = self.kad_system - .find_node(random_peer_id, move |who| { - let (tx, rx) = oneshot::channel(); - let mut kad_pending_ctrls = kad_pending_ctrls.lock(); - kad_pending_ctrls.entry(who.clone()).or_insert(Vec::new()).push(tx); - let _ = kad_new_ctrl_req_tx.unbounded_send(who.clone()); - rx.map_err(|_| IoError::new(IoErrorKind::Other, "Couldn't reach peer")) - }); - - self.kad_queries.push(Box::new(stream)); - } - - /// If a remote performs a `FIND_NODE` Kademlia request for `searched`, this function builds - /// the response to send back. - fn build_kademlia_response(&self, searched: &PeerId) -> Vec { - self.kad_system - .known_closest_peers(searched) - .map(|who| { - if who == *self.kad_system.local_peer_id() { - KadPeer { - node_id: who.clone(), - multiaddrs: self.swarm.external_addresses().cloned().collect(), - connection_ty: KadConnectionType::Connected, - } - } else { - let mut addrs = self.topology.addrs_of_peer(&who) - .map(|(a, c)| (a.clone(), c)) - .collect::>(); - let connected = addrs.iter().any(|&(_, conn)| conn); - // The Kademlia protocol of libp2p doesn't allow specifying which address is valid - // and which is outdated, therefore in order to stay honest towards the network - // we only report the addresses we're connected to if we're connected to any. - if connected { - addrs.retain(|&(_, connected)| connected); - } - - KadPeer { - node_id: who.clone(), - multiaddrs: addrs.into_iter().map(|(a, _)| a).collect(), - connection_ty: if connected { - KadConnectionType::Connected - } else { - KadConnectionType::NotConnected - }, - } - } - }) - // TODO: we really want to remove nodes with no multiaddress from - // the results, but a flaw in the Kad protocol of libp2p makes it - // impossible to return empty results ; therefore we must at least - // return ourselves - .filter(|p| p.node_id == *self.kad_system.local_peer_id() || !p.multiaddrs.is_empty()) - .take(20) - .collect::>() } - /// Adds a list of peers to the network topology. - fn add_discovered_peers(&mut self, list: impl IntoIterator) { - let mut topology_has_changed = false; - - for peer in list { - let connected = match peer.connection_ty { - KadConnectionType::NotConnected => false, - KadConnectionType::Connected => true, - KadConnectionType::CanConnect => true, - KadConnectionType::CannotConnect => continue, - }; - - let changed = self.topology.add_kademlia_discovered_addrs( - &peer.node_id, - peer.multiaddrs.iter().map(|a| (a.clone(), connected)) - ); - - if changed { - topology_has_changed = true; - } - } - - // Potentially connect to the newly-discovered nodes. - if topology_has_changed { - self.connect_to_nodes(); - } - } - - /// Handles the swarm opening a connection to the given peer. - /// - /// > **Note**: Must be called from inside `poll()`, otherwise it will panic. - fn handle_connection( - &mut self, - node_index: NodeIndex, - peer_id: PeerId, - endpoint: ConnectedPoint - ) { - // Reject connections to our own node, which can happen if the DHT contains `127.0.0.1` - // for example. - if &peer_id == self.kad_system.local_peer_id() { - debug!(target: "sub-libp2p", "Rejected connection to/from ourself: {:?}", endpoint); - assert_eq!(self.swarm.drop_node(node_index), Ok(Vec::new())); - if let ConnectedPoint::Dialer { ref address } = endpoint { - self.topology.report_failed_to_connect(address); - } - return; - } - - // Reject non-reserved nodes if we're in reserved mode. - let is_reserved = self.reserved_peers.contains(&peer_id); - if self.reserved_only && !is_reserved { - debug!(target: "sub-libp2p", "Rejected non-reserved peer {:?}", peer_id); - assert_eq!(self.swarm.drop_node(node_index), Ok(Vec::new())); - if let ConnectedPoint::Dialer { ref address } = endpoint { - self.topology.report_failed_to_connect(address); - } - return; - } - - // Reject connections from disabled peers. - if let Some(expires) = self.disabled_peers.get(&peer_id) { - if expires > &Instant::now() { - info!(target: "sub-libp2p", "Rejected connection from disabled peer: {:?}", peer_id); - assert_eq!(self.swarm.drop_node(node_index), Ok(Vec::new())); - if let ConnectedPoint::Dialer { ref address } = endpoint { - self.topology.report_failed_to_connect(address); - } - return; - } - } - - match endpoint { - ConnectedPoint::Listener { ref listen_addr, ref send_back_addr } => { - if is_reserved || self.num_ingoing_connections() < self.max_incoming_connections { - debug!(target: "sub-libp2p", "Connected to {:?} through {} on listener {}", - peer_id, send_back_addr, listen_addr); - } else { - info!(target: "sub-libp2p", "Rejected incoming peer {:?} because we are full", peer_id); - assert_eq!(self.swarm.drop_node(node_index), Ok(Vec::new())); - return; - } + /// Get debug info for a given peer. + pub fn peer_debug_info(&self, who: NodeIndex) -> String { + if let Some(info) = self.nodes_info.get(&who) { + format!("{:?} (version: {:?}) through {:?}", info.peer_id, info.client_version, info.endpoint) + } else { + "unknown".to_string() + } + } + + /// Returns the `NodeIndex` of a peer, or assigns one if none exists. + fn index_of_peer_or_assign(&mut self, peer: PeerId, endpoint: ConnectedPoint) -> NodeIndex { + match self.index_by_id.entry(peer) { + Entry::Occupied(entry) => { + let id = *entry.get(); + self.nodes_info.insert(id, NodeInfo { + peer_id: entry.key().clone(), + endpoint, + client_version: None, + latest_ping: None, + }); + id }, - ConnectedPoint::Dialer { ref address } => { - if is_reserved || self.num_outgoing_connections() < self.max_outgoing_connections { - debug!(target: "sub-libp2p", "Connected to {:?} through {}", peer_id, address); - self.topology.report_connected(address, &peer_id); - } else { - debug!(target: "sub-libp2p", "Rejected dialed peer {:?} because we are full", peer_id); - assert_eq!(self.swarm.drop_node(node_index), Ok(Vec::new())); - return; - } + Entry::Vacant(entry) => { + let id = self.next_node_id; + self.next_node_id += 1; + self.nodes_info.insert(id, NodeInfo { + peer_id: entry.key().clone(), + endpoint, + client_version: None, + latest_ping: None, + }); + entry.insert(id); + id }, - }; - - if let Err(_) = self.swarm.accept_node(node_index) { - error!(target: "sub-libp2p", "accept_node returned an error"); - } - - // We are finally sure that we're connected. - - if let ConnectedPoint::Dialer { ref address } = endpoint { - self.topology.report_connected(address, &peer_id); - } - self.nodes_addresses.insert(node_index, endpoint.clone()); - - // If we're waiting for a Kademlia substream for this peer id, open one. - let kad_pending_ctrls = self.kad_pending_ctrls.lock(); - if kad_pending_ctrls.contains_key(&peer_id) { - let res = self.swarm.open_kademlia(node_index); - debug_assert!(res.is_ok()); } } - /// Processes an event received by the swarm. - /// - /// Optionally returns an event to report back to the outside. - /// - /// > **Note**: Must be called from inside `poll()`, otherwise it will panic. - fn process_network_event( - &mut self, - event: SwarmEvent - ) -> Option { - match event { - SwarmEvent::NodePending { node_index, peer_id, endpoint } => { - self.handle_connection(node_index, peer_id, endpoint); - None - }, - SwarmEvent::Reconnected { node_index, endpoint, closed_custom_protocols } => { - if let Some(ConnectedPoint::Dialer { address }) = self.nodes_addresses.remove(&node_index) { - self.topology.report_disconnected(&address, DisconnectReason::FoundBetterAddr); + /// Polls for what happened on the network. + fn poll_swarm(&mut self) -> Poll>, IoError> { + loop { + match self.swarm.poll() { + Ok(Async::Ready(Some(BehaviourOut::CustomProtocolOpen { protocol_id, peer_id, version, endpoint }))) => { + debug!(target: "sub-libp2p", "Opened custom protocol with {:?}", peer_id); + let node_index = self.index_of_peer_or_assign(peer_id.clone(), endpoint); + break Ok(Async::Ready(Some(ServiceEvent::OpenedCustomProtocol { + peer_id, + node_index, + protocol: protocol_id, + version, + debug_info: self.peer_debug_info(node_index), + }))) } - if let ConnectedPoint::Dialer { ref address } = endpoint { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - self.topology.report_connected(address, peer_id); + Ok(Async::Ready(Some(BehaviourOut::CustomProtocolClosed { protocol_id, peer_id, result }))) => { + debug!(target: "sub-libp2p", "Custom protocol with {:?} closed: {:?}", peer_id, result); + let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + break Ok(Async::Ready(Some(ServiceEvent::ClosedCustomProtocol { + node_index, + protocol: protocol_id, + debug_info: self.peer_debug_info(node_index), + }))) } - self.nodes_addresses.insert(node_index, endpoint); - Some(ServiceEvent::ClosedCustomProtocols { - node_index, - protocols: closed_custom_protocols, - }) - }, - SwarmEvent::NodeClosed { node_index, peer_id, closed_custom_protocols } => { - debug!(target: "sub-libp2p", "Connection to {:?} closed gracefully", peer_id); - if let Some(ConnectedPoint::Dialer { ref address }) = self.nodes_addresses.get(&node_index) { - self.topology.report_disconnected(address, DisconnectReason::RemoteClosed); - } - self.connect_to_nodes(); - Some(ServiceEvent::NodeClosed { - node_index, - closed_custom_protocols, - }) - }, - SwarmEvent::DialFail { address, error } => { - debug!(target: "sub-libp2p", "Failed to dial address {}: {:?}", address, error); - self.topology.report_failed_to_connect(&address); - self.connect_to_nodes(); - None - }, - SwarmEvent::UnresponsiveNode { node_index } => { - let closed_custom_protocols = self.swarm.drop_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - if let Some(ConnectedPoint::Dialer { address }) = self.nodes_addresses.remove(&node_index) { - self.topology.report_disconnected(&address, DisconnectReason::Useless); + Ok(Async::Ready(Some(BehaviourOut::CustomMessage { protocol_id, peer_id, message }))) => { + let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + break Ok(Async::Ready(Some(ServiceEvent::CustomMessage { + node_index, + protocol_id, + message, + }))) } - Some(ServiceEvent::NodeClosed { - node_index, - closed_custom_protocols, - }) - }, - SwarmEvent::UselessNode { node_index } => { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices") - .clone(); - let closed_custom_protocols = self.swarm.drop_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - self.topology.report_useless(&peer_id); - if let Some(ConnectedPoint::Dialer { address }) = self.nodes_addresses.remove(&node_index) { - self.topology.report_disconnected(&address, DisconnectReason::Useless); + Ok(Async::Ready(Some(BehaviourOut::Clogged { protocol_id, peer_id, messages }))) => { + let node_index = *self.index_by_id.get(&peer_id).expect("index_by_id is always kept in sync with the state of the behaviour"); + break Ok(Async::Ready(Some(ServiceEvent::Clogged { + node_index, + protocol_id, + messages, + }))) } - Some(ServiceEvent::NodeClosed { - node_index, - closed_custom_protocols, - }) - }, - SwarmEvent::NodeInfos { node_index, listen_addrs, .. } => { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - self.topology.add_self_reported_listen_addrs( - peer_id, - listen_addrs.into_iter() - ); - None - }, - SwarmEvent::KadFindNode { searched, responder, .. } => { - let response = self.build_kademlia_response(&searched); - responder.respond(response); - None - }, - SwarmEvent::KadOpen { node_index, controller } => { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - trace!(target: "sub-libp2p", "Opened Kademlia substream with {:?}", peer_id); - if let Some(list) = self.kad_pending_ctrls.lock().remove(&peer_id) { - for tx in list { - let _ = tx.send(controller.clone()); + Ok(Async::Ready(Some(BehaviourOut::Identified { peer_id, info }))) => { + // Contrary to the other events, this one can happen even on nodes which don't + // have any open custom protocol slot. Therefore it is not necessarily in the + // list. + if let Some(id) = self.index_by_id.get(&peer_id) { + if let Some(n) = self.nodes_info.get_mut(id) { + n.client_version = Some(info.agent_version); + } else { + error!(target: "sub-libp2p", + "State inconsistency between index_by_id and nodes_info"); + } } } - None - }, - SwarmEvent::KadClosed { .. } => { - None - }, - SwarmEvent::OpenedCustomProtocol { node_index, protocol, version } => { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - self.kad_system.update_kbuckets(peer_id.clone()); - Some(ServiceEvent::OpenedCustomProtocol { - node_index, - protocol, - version, - }) - }, - SwarmEvent::ClosedCustomProtocol { node_index, protocol } => - Some(ServiceEvent::ClosedCustomProtocol { - node_index, - protocol, - }), - SwarmEvent::CustomMessage { node_index, protocol_id, data } => { - let peer_id = self.swarm.peer_id_of_node(node_index) - .expect("the swarm always produces events containing valid node indices"); - self.kad_system.update_kbuckets(peer_id.clone()); - Some(ServiceEvent::CustomMessage { - node_index, - protocol_id, - data, - }) - }, - } - } - - /// Handles a Kademlia query requesting a Kademlia controller with the given peer. - fn handle_kad_ctrl_request(&mut self, peer_id: PeerId) { - if let Some(node_index) = self.swarm.latest_node_by_peer_id(&peer_id) { - if let Err(_) = self.swarm.open_kademlia(node_index) { - self.kad_pending_ctrls.lock().remove(&peer_id); - } - } else { - let addrs = self.topology.addrs_of_peer(&peer_id); - let mut one_worked = false; - for (addr, _) in addrs { - if let Ok(_) = self.swarm.ensure_connection(peer_id.clone(), addr.clone()) { - one_worked = true; - } - } - if !one_worked { - debug!(target: "sub-libp2p", "Couldn't open Kad substream with {:?} \ - because no address is known", peer_id); - // Closing the senders in order to generate errors on the Kad query. - self.kad_pending_ctrls.lock().remove(&peer_id); - } - } - } - - /// Polls for what happened on the main network side. - fn poll_swarm(&mut self) -> Poll, IoError> { - loop { - match self.swarm.poll() { - Ok(Async::Ready(Some(event))) => - if let Some(event) = self.process_network_event(event) { - return Ok(Async::Ready(Some(event))); - } - Ok(Async::NotReady) => return Ok(Async::NotReady), - Ok(Async::Ready(None)) => unreachable!("The Swarm stream never ends"), - // TODO: this `Err` contains a `Void` ; remove variant when Rust allows that - Err(_) => unreachable!("The Swarm stream never errors"), - } - } - } - - /// Polls the Kademlia system. - fn poll_kademlia(&mut self) -> Poll, IoError> { - // Polls the active Kademlia queries. - // We remove each element from `kad_queries` one by one and add them back if not ready. - for n in (0 .. self.kad_queries.len()).rev() { - let mut query = self.kad_queries.swap_remove(n); - loop { - match query.poll() { - Ok(Async::Ready(Some(KadQueryEvent::PeersReported(list)))) => - self.add_discovered_peers(list), - // We don't actually care about the results - Ok(Async::Ready(Some(KadQueryEvent::Finished(_out)))) => { - if _out.is_empty() { - warn!(target: "sub-libp2p", "Random Kademlia request has yielded \ - empty results"); + Ok(Async::Ready(Some(BehaviourOut::PingSuccess { peer_id, ping_time }))) => { + // Contrary to the other events, this one can happen even on nodes which don't + // have any open custom protocol slot. Therefore it is not necessarily in the + // list. + if let Some(id) = self.index_by_id.get(&peer_id) { + if let Some(n) = self.nodes_info.get_mut(id) { + n.latest_ping = Some(ping_time); + } else { + error!(target: "sub-libp2p", + "State inconsistency between index_by_id and nodes_info"); } - break - }, - Ok(Async::Ready(None)) => break, - Ok(Async::NotReady) => { - self.kad_queries.push(query); - break; - }, - Err(err) => { - warn!(target: "sub-libp2p", "Kademlia query failed: {:?}", err); - break; - }, - } - } - } - - // Poll the future that fires when we need to reply to a Kademlia query. - loop { - match self.kad_new_ctrl_req_rx.poll() { - Ok(Async::NotReady) => break, - Ok(Async::Ready(Some(peer_id))) => self.handle_kad_ctrl_request(peer_id), - Ok(Async::Ready(None)) => unreachable!("The tx is in self"), - Err(()) => unreachable!("An UnboundedReceiver never errors"), - } - } - - // Poll the future that fires when we need to perform a random Kademlia query. - loop { - match self.next_kad_random_query.poll() { - Ok(Async::NotReady) => break, - Ok(Async::Ready(Some(_))) => self.perform_kad_random_query(), - Ok(Async::Ready(None)) => { - warn!(target: "sub-libp2p", "Kad query timer closed unexpectedly"); - return Ok(Async::Ready(None)); - } - Err(err) => { - warn!(target: "sub-libp2p", "Kad query timer errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); - } - } - } - - Ok(Async::NotReady) - } - - // Polls the future that fires when we need to refresh our connections. - fn poll_next_connect_refresh(&mut self) -> Poll, IoError> { - loop { - match self.next_connect_to_nodes.poll() { - Ok(Async::Ready(())) => self.connect_to_nodes(), - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(err) => { - warn!(target: "sub-libp2p", "Connect to nodes timer errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); + } } + Ok(Async::NotReady) => break Ok(Async::NotReady), + Ok(Async::Ready(None)) => unreachable!("The Swarm stream never ends"), + Err(_) => unreachable!("The Swarm never errors"), } } } /// Polls the stream that fires when we need to cleanup and flush the topology. - fn poll_cleanup(&mut self) -> Poll, IoError> { + fn poll_cleanup(&mut self) -> Poll>, IoError> { loop { match self.cleanup.poll() { Ok(Async::NotReady) => return Ok(Async::NotReady), Ok(Async::Ready(Some(_))) => { debug!(target: "sub-libp2p", "Cleaning and flushing topology"); - self.topology.cleanup(); - if let Err(err) = self.topology.flush_to_disk() { + self.swarm.cleanup(); + if let Err(err) = self.swarm.flush_topology() { warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err); } - let now = Instant::now(); - self.disabled_peers.retain(move |_, v| *v < now); debug!(target: "sub-libp2p", "Topology now contains {} nodes", - self.topology.num_peers()); - }, + self.swarm.num_topology_peers()); + } Ok(Async::Ready(None)) => { warn!(target: "sub-libp2p", "Topology flush stream ended unexpectedly"); - return Ok(Async::Ready(None)); + return Ok(Async::Ready(None)) } Err(err) => { warn!(target: "sub-libp2p", "Topology flush stream errored: {:?}", err); - return Err(IoError::new(IoErrorKind::Other, err)); + return Err(IoError::new(IoErrorKind::Other, err)) } } } } } -impl Drop for Service { +impl Drop for Service where TMessage: CustomMessage { fn drop(&mut self) { - if let Err(err) = self.topology.flush_to_disk() { + if let Err(err) = self.swarm.flush_topology() { warn!(target: "sub-libp2p", "Failed to flush topology: {:?}", err); } } } -impl Stream for Service { - type Item = ServiceEvent; +impl Stream for Service where TMessage: CustomMessage + Send + 'static { + type Item = ServiceEvent; type Error = IoError; fn poll(&mut self) -> Poll, Self::Error> { @@ -977,16 +534,6 @@ impl Stream for Service { Async::NotReady => (), } - match self.poll_kademlia()? { - Async::Ready(value) => return Ok(Async::Ready(value)), - Async::NotReady => (), - } - - match self.poll_next_connect_refresh()? { - Async::Ready(value) => return Ok(Async::Ready(value)), - Async::NotReady => (), - } - match self.poll_cleanup()? { Async::Ready(value) => return Ok(Async::Ready(value)), Async::NotReady => (), @@ -994,7 +541,6 @@ impl Stream for Service { // The only way we reach this is if we went through all the `NotReady` paths above, // ensuring the current task is registered everywhere. - self.to_notify = Some(task::current()); Ok(Async::NotReady) } } diff --git a/core/network-libp2p/src/swarm.rs b/core/network-libp2p/src/swarm.rs deleted file mode 100644 index 0a6bfaa9949389379e85eb569176cd3495f70f0f..0000000000000000000000000000000000000000 --- a/core/network-libp2p/src/swarm.rs +++ /dev/null @@ -1,672 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use bytes::Bytes; -use custom_proto::RegisteredProtocols; -use fnv::FnvHashMap; -use futures::{prelude::*, Stream}; -use libp2p::{Multiaddr, multiaddr::Protocol, PeerId}; -use libp2p::core::{muxing, Endpoint, PublicKey}; -use libp2p::core::nodes::{ConnectedPoint, RawSwarm, RawSwarmEvent, Peer as SwarmPeer, Substream}; -use libp2p::core::transport::boxed::Boxed; -use libp2p::kad::{KadConnecController, KadFindNodeRespond}; -use libp2p::secio; -use node_handler::{SubstrateOutEvent, SubstrateNodeHandler, SubstrateInEvent, IdentificationRequest}; -use std::{io, mem, sync::Arc}; -use transport; -use {Error, NodeIndex, ProtocolId}; - -/// Starts a swarm. -/// -/// Returns a stream that must be polled regularly in order for the networking to function. -pub fn start_swarm( - registered_custom: RegisteredProtocols, - local_private_key: secio::SecioKeyPair, -) -> Result { - // Private and public keys. - let local_public_key = local_private_key.to_public_key(); - let local_peer_id = local_public_key.clone().into_peer_id(); - - // Build the transport layer. This is what allows us to listen or to reach nodes. - let transport = transport::build_transport(local_private_key); - - // Build the underlying libp2p swarm. - let swarm = RawSwarm::new(transport); - - Ok(Swarm { - swarm, - registered_custom: Arc::new(registered_custom), - local_public_key, - local_peer_id, - listening_addrs: Vec::new(), - node_by_peer: Default::default(), - nodes_info: Default::default(), - next_node_index: 0, - }) -} - -/// Event produced by the swarm. -pub enum SwarmEvent { - /// We have successfully connected to a node. - /// - /// The node is in pending node, and should be accepted by calling `accept_node(node_index)` - /// or denied by calling `drop_node(node_index)`. - NodePending { - /// Index of the node. - node_index: NodeIndex, - /// Public key of the node as a peer id. - peer_id: PeerId, - /// Whether we dialed the node or if it came to us. - endpoint: ConnectedPoint, - }, - - /// The connection to a peer has changed. - Reconnected { - /// Index of the node. - node_index: NodeIndex, - /// The new endpoint. - endpoint: ConnectedPoint, - /// List of custom protocols that were closed in the process. - closed_custom_protocols: Vec, - }, - - /// Closed connection to a node, either gracefully or because of an error. - /// - /// It is guaranteed that this node has been opened with a `NewNode` event beforehand. However - /// not all `ClosedCustomProtocol` events have been dispatched. - NodeClosed { - /// Index of the node. - node_index: NodeIndex, - /// Peer id we were connected to. - peer_id: PeerId, - /// List of custom protocols that were still open. - closed_custom_protocols: Vec, - }, - - /// Failed to dial an address. - DialFail { - /// Address that failed. - address: Multiaddr, - /// Reason why we failed. - error: io::Error, - }, - - /// Report information about the node. - NodeInfos { - /// Index of the node. - node_index: NodeIndex, - /// The client version. Note that it can be anything and should not be trusted. - client_version: String, - /// Multiaddresses the node is listening on. - listen_addrs: Vec, - }, - - /// A custom protocol substream has been opened with a node. - OpenedCustomProtocol { - /// Index of the node. - node_index: NodeIndex, - /// Protocol that has been opened. - protocol: ProtocolId, - /// Version of the protocol that was opened. - version: u8, - }, - - /// A custom protocol substream has been closed. - ClosedCustomProtocol { - /// Index of the node. - node_index: NodeIndex, - /// Protocol that has been closed. - protocol: ProtocolId, - }, - - /// Receives a message on a custom protocol stream. - CustomMessage { - /// Index of the node. - node_index: NodeIndex, - /// Protocol which generated the message. - protocol_id: ProtocolId, - /// Data that has been received. - data: Bytes, - }, - - /// The node has been determined to be unresponsive. - UnresponsiveNode { - /// Index of the node. - node_index: NodeIndex, - }, - - /// The node works but we can't do anything useful with it. - UselessNode { - /// Index of the node. - node_index: NodeIndex, - }, - - /// Opened a Kademlia substream with the node. - // TODO: the controller API is bad, but we need to make changes in libp2p to improve that - KadOpen { - /// Index of the node. - node_index: NodeIndex, - /// The Kademlia controller. Allows making queries. - controller: KadConnecController, - }, - - /// The remote wants us to answer a Kademlia `FIND_NODE` request. - /// - /// The `responder` should be used to answer that query. - // TODO: this API with the "responder" is bad, but changing it requires modifications in libp2p - KadFindNode { - /// Index of the node that wants an answer. - node_index: NodeIndex, - /// The value being searched. - searched: PeerId, - /// Object to use to respond to the request. - responder: KadFindNodeRespond, - }, - - /// A Kademlia substream has been closed. - KadClosed { - /// Index of the node. - node_index: NodeIndex, - /// Reason why it has been closed. `Ok` means that it's been closed gracefully. - result: Result<(), io::Error>, - }, -} - -/// Network swarm. Must be polled regularly in order for the networking to work. -pub struct Swarm { - /// Stream of events of the swarm. - swarm: RawSwarm< - Boxed<(PeerId, Muxer)>, - SubstrateInEvent, - SubstrateOutEvent>, - SubstrateNodeHandler> - >, - - /// List of registered protocols. Used when we open or receive a new connection. - registered_custom: Arc, - - /// Public key of the local node. - local_public_key: PublicKey, - - /// Peer id of the local node. - local_peer_id: PeerId, - - /// Addresses we know we're listening on. Only includes NAT traversed addresses. - listening_addrs: Vec, - - /// For each peer id, the corresponding node index. - node_by_peer: FnvHashMap, - - /// All the nodes tasks. Must be maintained consistent with `node_by_peer`. - nodes_info: FnvHashMap, - - /// Next key to use when we insert a new entry in `nodes_info`. - next_node_index: NodeIndex, -} - -/// Local information about a peer. -struct NodeInfo { - /// The peer id. Must be maintained consistent with the rest of the state. - peer_id: PeerId, - - /// Whether we opened the connection or the remote opened it. - endpoint: Endpoint, - - /// List of custom protocol substreams that are open. - open_protocols: Vec, -} - -/// The muxer used by the transport. -type Muxer = muxing::StreamMuxerBox; - -impl Swarm { - /// Start listening on a multiaddr. - #[inline] - pub fn listen_on(&mut self, addr: Multiaddr) -> Result { - match self.swarm.listen_on(addr) { - Ok(mut addr) => { - addr.append(Protocol::P2p(self.local_peer_id.clone().into())); - info!(target: "sub-libp2p", "Local node address is: {}", addr); - Ok(addr) - }, - Err(addr) => Err(addr) - } - } - - /// Returns an iterator that produces the list of addresses we're listening on. - #[inline] - pub fn listeners(&self) -> impl Iterator { - self.swarm.listeners() - } - - /// Adds an external address. Sent to other nodes when they query it. - #[inline] - pub fn add_external_address(&mut self, addr: Multiaddr) { - self.listening_addrs.push(addr); - } - - /// Returns an iterator to our known external addresses. - #[inline] - pub fn external_addresses(&self) -> impl Iterator { - self.listening_addrs.iter() - } - - /// Returns all the nodes that are currently active. - #[inline] - pub fn nodes<'a>(&'a self) -> impl Iterator + 'a { - self.nodes_info.keys().cloned() - } - - /// Returns the latest node connected to this peer ID. - #[inline] - pub fn latest_node_by_peer_id(&self, peer_id: &PeerId) -> Option { - self.node_by_peer.get(peer_id).map(|&i| i) - } - - /// Endpoint of the node. - /// - /// Returns `None` if the index is invalid. - #[inline] - pub fn node_endpoint(&self, node_index: NodeIndex) -> Option { - self.nodes_info.get(&node_index).map(|i| i.endpoint) - } - - /// Sends a message to a peer using the custom protocol. - // TODO: report invalid node index or protocol? - pub fn send_custom_message( - &mut self, - node_index: NodeIndex, - protocol: ProtocolId, - data: Vec - ) { - if let Some(info) = self.nodes_info.get_mut(&node_index) { - if let Some(mut connected) = self.swarm.peer(info.peer_id.clone()).as_connected() { - connected.send_event(SubstrateInEvent::SendCustomMessage { protocol, data }); - } else { - error!(target: "sub-libp2p", "Tried to send message to {:?}, but we're not \ - connected to it", info.peer_id); - } - } else { - error!(target: "sub-libp2p", "Tried to send message to invalid node index {:?}", - node_index); - } - } - - /// Returns the peer id of a node we're connected to. - #[inline] - pub fn peer_id_of_node(&self, node_index: NodeIndex) -> Option<&PeerId> { - self.nodes_info.get(&node_index).map(|i| &i.peer_id) - } - - /// If we're not already dialing the given peer, start dialing it and return false. - /// If we're dialing, adds the address to the queue of addresses to try (if not already) and - /// return false. - /// If we're already connected, do nothing and return true. - /// - /// Returns an error if the address is not supported. - pub fn ensure_connection(&mut self, peer_id: PeerId, addr: Multiaddr) -> Result { - match self.swarm.peer(peer_id.clone()) { - SwarmPeer::Connected(_) => Ok(true), - SwarmPeer::PendingConnect(mut peer) => { - peer.append_multiaddr_attempt(addr); - Ok(false) - }, - SwarmPeer::NotConnected(peer) => { - trace!(target: "sub-libp2p", "Starting to connect to {:?} through {}", - peer_id, addr); - match peer.connect(addr, SubstrateNodeHandler::new(self.registered_custom.clone())) { - Ok(_) => Ok(false), - Err(_) => Err(()), - } - }, - } - } - - /// Start dialing an address, not knowing which peer ID to expect. - #[inline] - pub fn dial(&mut self, addr: Multiaddr) -> Result<(), Multiaddr> { - self.swarm.dial(addr, SubstrateNodeHandler::new(self.registered_custom.clone())) - } - - /// After receiving a `NodePending` event, you should call either `accept_node` or `drop_node` - /// with the specified index. - /// - /// Returns an error if the node index is invalid, or if it was already accepted. - pub fn accept_node(&mut self, node_index: NodeIndex) -> Result<(), ()> { - // TODO: detect if already accepted? - let peer_id = match self.nodes_info.get(&node_index) { - Some(info) => &info.peer_id, - None => return Err(()) - }; - - match self.swarm.peer(peer_id.clone()) { - SwarmPeer::Connected(mut peer) => { - peer.send_event(SubstrateInEvent::Accept); - Ok(()) - }, - SwarmPeer::PendingConnect(_) | SwarmPeer::NotConnected(_) => { - error!(target: "sub-libp2p", "State inconsistency detected in accept_node ; \ - nodes_info is not in sync with the underlying swarm"); - Err(()) - }, - } - } - - /// Disconnects a peer. - /// - /// If the peer is connected, this disconnects it. - /// If the peer hasn't been accepted yet, this immediately drops it. - /// - /// Returns the list of custom protocol substreams that were opened. - #[inline] - pub fn drop_node(&mut self, node_index: NodeIndex) -> Result, ()> { - let info = match self.nodes_info.remove(&node_index) { - Some(i) => i, - None => { - error!(target: "sub-libp2p", "Trying to close non-existing node #{}", node_index); - return Err(()); - }, - }; - - let idx_in_hashmap = self.node_by_peer.remove(&info.peer_id); - debug_assert_eq!(idx_in_hashmap, Some(node_index)); - - if let Some(connected) = self.swarm.peer(info.peer_id.clone()).as_connected() { - connected.close(); - } else { - error!(target: "sub-libp2p", "State inconsistency: node_by_peer and nodes_info are \ - not in sync with the underlying swarm"); - } - - Ok(info.open_protocols) - } - - /// Opens a Kademlia substream with the given node. A `KadOpen` event will later be produced - /// for the given node. - /// - /// If a Kademlia substream is already open, also produces a `KadOpen` event. - /// - /// Returns an error if the node index is invalid. - pub fn open_kademlia(&mut self, node_index: NodeIndex) -> Result<(), ()> { - if let Some(info) = self.nodes_info.get_mut(&node_index) { - if let Some(mut connected) = self.swarm.peer(info.peer_id.clone()).as_connected() { - connected.send_event(SubstrateInEvent::OpenKademlia); - Ok(()) - } else { - error!(target: "sub-libp2p", "Tried to open Kademlia with {:?}, but we're not \ - connected to it", info.peer_id); - Err(()) - } - } else { - error!(target: "sub-libp2p", "Tried to open Kademlia with invalid node index {:?}", - node_index); - Err(()) - } - } - - /// Adds an address the given peer observes us as. - fn add_observed_addr(&mut self, peer_id: &PeerId, observed_addr: &Multiaddr) { - for mut addr in self.swarm.nat_traversal(observed_addr) { - // Ignore addresses we already know about. - if self.listening_addrs.iter().any(|a| a == &addr) { - continue; - } - - debug!(target: "sub-libp2p", - "NAT traversal: {:?} observes us as {}; registering {} as one of our own addresses", - peer_id, - observed_addr, - addr - ); - - self.listening_addrs.push(addr.clone()); - addr.append(Protocol::P2p(self.local_peer_id.clone().into())); - info!(target: "sub-libp2p", "New external node address: {}", addr); - } - } - - /// Responds to an answer to send back identification information. - fn respond_to_identify_request( - &mut self, - requester: &PeerId, - responder: IdentificationRequest> - ) { - let peer = match self.swarm.peer(requester.clone()).as_connected() { - Some(p) => p, - None => { - debug!(target: "sub-libp2p", "Ignoring identify request from {:?} because we are \ - disconnected", requester); - return; - } - }; - - let observed_addr = match peer.endpoint() { - &ConnectedPoint::Dialer { ref address } => address, - &ConnectedPoint::Listener { ref send_back_addr, .. } => send_back_addr, - }; - - trace!(target: "sub-libp2p", "Responding to identify request from {:?}", requester); - responder.respond( - self.local_public_key.clone(), - self.listening_addrs.clone(), - &observed_addr, - ); - } - - /// Processes an event obtained by a node in the swarm. - /// - /// Optionally returns an event that the service must emit. - /// - /// > **Note**: The event **must** have been produced by the swarm, otherwise state - /// > inconsistencies will likely happen. - fn handle_node_event( - &mut self, - peer_id: PeerId, - event: SubstrateOutEvent> - ) -> Option { - // Obtain the peer id and whether the node has been closed earlier. - // If the node has been closed, do not generate any additional event about it. - let node_index = *self.node_by_peer.get(&peer_id) - .expect("node_by_peer is always kept in sync with the underlying swarm"); - - match event { - SubstrateOutEvent::Unresponsive => { - debug!(target: "sub-libp2p", "Node {:?} is unresponsive", peer_id); - Some(SwarmEvent::UnresponsiveNode { node_index }) - }, - SubstrateOutEvent::Useless => { - debug!(target: "sub-libp2p", "Node {:?} is useless", peer_id); - Some(SwarmEvent::UselessNode { node_index }) - }, - SubstrateOutEvent::PingStart => { - trace!(target: "sub-libp2p", "Pinging {:?}", peer_id); - None - }, - SubstrateOutEvent::PingSuccess(ping) => { - trace!(target: "sub-libp2p", "Pong from {:?} in {:?}", peer_id, ping); - None - }, - SubstrateOutEvent::Identified { info, observed_addr } => { - self.add_observed_addr(&peer_id, &observed_addr); - trace!(target: "sub-libp2p", "Client version of {:?}: {:?}", peer_id, info.agent_version); - if !info.agent_version.contains("substrate") { - info!(target: "sub-libp2p", "Connected to non-substrate node {:?}: {}", - peer_id, info.agent_version); - } - - Some(SwarmEvent::NodeInfos { - node_index, - client_version: info.agent_version, - listen_addrs: info.listen_addrs, - }) - }, - SubstrateOutEvent::IdentificationRequest(request) => { - self.respond_to_identify_request(&peer_id, request); - None - }, - SubstrateOutEvent::KadFindNode { searched, responder } => { - Some(SwarmEvent::KadFindNode { node_index, searched, responder }) - }, - SubstrateOutEvent::KadOpen(ctrl) => { - trace!(target: "sub-libp2p", "Opened Kademlia substream with {:?}", peer_id); - Some(SwarmEvent::KadOpen { node_index, controller: ctrl }) - }, - SubstrateOutEvent::KadClosed(result) => { - trace!(target: "sub-libp2p", "Closed Kademlia substream with {:?}: {:?}", peer_id, result); - Some(SwarmEvent::KadClosed { node_index, result }) - }, - SubstrateOutEvent::CustomProtocolOpen { protocol_id, version } => { - trace!(target: "sub-libp2p", "Opened custom protocol with {:?}", peer_id); - self.nodes_info.get_mut(&node_index) - .expect("nodes_info is kept in sync with the underlying swarm") - .open_protocols.push(protocol_id); - Some(SwarmEvent::OpenedCustomProtocol { - node_index, - protocol: protocol_id, - version, - }) - }, - SubstrateOutEvent::CustomProtocolClosed { protocol_id, result } => { - trace!(target: "sub-libp2p", "Closed custom protocol with {:?}: {:?}", peer_id, result); - self.nodes_info.get_mut(&node_index) - .expect("nodes_info is kept in sync with the underlying swarm") - .open_protocols.retain(|p| p != &protocol_id); - Some(SwarmEvent::ClosedCustomProtocol { - node_index, - protocol: protocol_id, - }) - }, - SubstrateOutEvent::CustomMessage { protocol_id, data } => { - Some(SwarmEvent::CustomMessage { - node_index, - protocol_id, - data, - }) - }, - SubstrateOutEvent::SubstreamUpgradeFail(err) => { - debug!(target: "sub-libp2p", "Error while negotiating final protocol \ - with {:?}: {:?}", peer_id, err); - None - }, - } - } -} - -impl Stream for Swarm { - type Item = SwarmEvent; - type Error = io::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - loop { - let (peer_id, node_event) = match self.swarm.poll() { - Async::Ready(RawSwarmEvent::Connected { peer_id, endpoint }) => { - let node_index = self.next_node_index.clone(); - self.next_node_index += 1; - self.node_by_peer.insert(peer_id.clone(), node_index); - self.nodes_info.insert(node_index, NodeInfo { - peer_id: peer_id.clone(), - endpoint: match endpoint { - ConnectedPoint::Listener { .. } => Endpoint::Listener, - ConnectedPoint::Dialer { .. } => Endpoint::Dialer, - }, - open_protocols: Vec::new(), - }); - - return Ok(Async::Ready(Some(SwarmEvent::NodePending { - node_index, - peer_id, - endpoint - }))); - } - Async::Ready(RawSwarmEvent::Replaced { peer_id, endpoint, .. }) => { - let node_index = *self.node_by_peer.get(&peer_id) - .expect("node_by_peer is always kept in sync with the inner swarm"); - let infos = self.nodes_info.get_mut(&node_index) - .expect("nodes_info is always kept in sync with the swarm"); - debug_assert_eq!(infos.peer_id, peer_id); - infos.endpoint = match endpoint { - ConnectedPoint::Listener { .. } => Endpoint::Listener, - ConnectedPoint::Dialer { .. } => Endpoint::Dialer, - }; - let closed_custom_protocols = mem::replace(&mut infos.open_protocols, Vec::new()); - - return Ok(Async::Ready(Some(SwarmEvent::Reconnected { - node_index, - endpoint, - closed_custom_protocols, - }))); - }, - Async::Ready(RawSwarmEvent::NodeClosed { peer_id, .. }) => { - debug!(target: "sub-libp2p", "Connection to {:?} closed gracefully", peer_id); - let node_index = self.node_by_peer.remove(&peer_id) - .expect("node_by_peer is always kept in sync with the inner swarm"); - let infos = self.nodes_info.remove(&node_index) - .expect("nodes_info is always kept in sync with the inner swarm"); - debug_assert_eq!(infos.peer_id, peer_id); - return Ok(Async::Ready(Some(SwarmEvent::NodeClosed { - node_index, - peer_id, - closed_custom_protocols: infos.open_protocols, - }))); - }, - Async::Ready(RawSwarmEvent::NodeError { peer_id, error, .. }) => { - debug!(target: "sub-libp2p", "Closing {:?} because of error: {:?}", peer_id, error); - let node_index = self.node_by_peer.remove(&peer_id) - .expect("node_by_peer is always kept in sync with the inner swarm"); - let infos = self.nodes_info.remove(&node_index) - .expect("nodes_info is always kept in sync with the inner swarm"); - debug_assert_eq!(infos.peer_id, peer_id); - return Ok(Async::Ready(Some(SwarmEvent::NodeClosed { - node_index, - peer_id, - closed_custom_protocols: infos.open_protocols, - }))); - }, - Async::Ready(RawSwarmEvent::DialError { multiaddr, error, .. }) => - return Ok(Async::Ready(Some(SwarmEvent::DialFail { - address: multiaddr, - error, - }))), - Async::Ready(RawSwarmEvent::UnknownPeerDialError { multiaddr, error, .. }) => - return Ok(Async::Ready(Some(SwarmEvent::DialFail { - address: multiaddr, - error, - }))), - Async::Ready(RawSwarmEvent::ListenerClosed { listen_addr, result, .. }) => { - warn!(target: "sub-libp2p", "Listener closed for {}: {:?}", listen_addr, result); - continue; - }, - Async::Ready(RawSwarmEvent::NodeEvent { peer_id, event }) => (peer_id, event), - Async::Ready(RawSwarmEvent::IncomingConnection(incoming)) => { - trace!(target: "sub-libp2p", "Incoming connection with {} on listener {}", - incoming.send_back_addr(), incoming.listen_addr()); - incoming.accept(SubstrateNodeHandler::new(self.registered_custom.clone())); - continue; - }, - Async::Ready(RawSwarmEvent::IncomingConnectionError { listen_addr, send_back_addr, error }) => { - trace!(target: "sub-libp2p", "Incoming connection with {} on listener {} \ - errored: {:?}", send_back_addr, listen_addr, error); - continue; - }, - Async::NotReady => return Ok(Async::NotReady), - }; - - if let Some(event) = self.handle_node_event(peer_id, node_event) { - return Ok(Async::Ready(Some(event))); - } - } - } -} diff --git a/core/network-libp2p/src/traits.rs b/core/network-libp2p/src/traits.rs index 7e87ec130138cdbbdec90170fdc295b6b34849cc..63ccda54d1f177d4bcead544e6248d1d4ed6b891 100644 --- a/core/network-libp2p/src/traits.rs +++ b/core/network-libp2p/src/traits.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -52,8 +52,10 @@ pub struct NetworkConfiguration { pub reserved_nodes: Vec, /// The non-reserved peer mode. pub non_reserved_mode: NonReservedPeerMode, - /// Client identifier + /// Client identifier. Sent over the wire for debugging purposes. pub client_version: String, + /// Name of the node. Sent over the wire for debugging purposes. + pub node_name: String, } impl Default for NetworkConfiguration { @@ -68,11 +70,7 @@ impl NetworkConfiguration { NetworkConfiguration { config_path: None, net_config_path: None, - listen_addresses: vec![ - iter::once(Protocol::Ip4(Ipv4Addr::new(0, 0, 0, 0))) - .chain(iter::once(Protocol::Tcp(30333))) - .collect() - ], + listen_addresses: Vec::new(), public_addresses: Vec::new(), boot_nodes: Vec::new(), use_secret: None, @@ -80,7 +78,8 @@ impl NetworkConfiguration { out_peers: 75, reserved_nodes: Vec::new(), non_reserved_mode: NonReservedPeerMode::Accept, - client_version: "Parity-network".into(), // TODO: meh + client_version: "unknown".into(), + node_name: "unknown".into(), } } @@ -97,21 +96,21 @@ impl NetworkConfiguration { } /// The severity of misbehaviour of a peer that is reported. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum Severity<'a> { +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Severity { /// Peer is timing out. Could be bad connectivity of overload of work on either of our sides. Timeout, /// Peer has been notably useless. E.g. unable to answer a request that we might reasonably consider /// it could answer. - Useless(&'a str), + Useless(String), /// Peer has behaved in an invalid manner. This doesn't necessarily need to be Byzantine, but peer /// must have taken concrete action in order to behave in such a way which is wantanly invalid. - Bad(&'a str), + Bad(String), } -impl<'a> fmt::Display for Severity<'a> { +impl fmt::Display for Severity { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { + match self { Severity::Timeout => write!(fmt, "Timeout"), Severity::Useless(r) => write!(fmt, "Useless ({})", r), Severity::Bad(r) => write!(fmt, "Bad ({})", r), diff --git a/core/network-libp2p/src/transport.rs b/core/network-libp2p/src/transport.rs index 89c6757bbcf9fa3784782e5f4c61c72a65678853..de0639a7b5b9da0cb035f0f113890b6735e9fb8e 100644 --- a/core/network-libp2p/src/transport.rs +++ b/core/network-libp2p/src/transport.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,33 +14,48 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use libp2p::{self, PeerId, Transport, mplex, secio, yamux}; -use libp2p::core::{either, upgrade, transport::boxed::Boxed, muxing::StreamMuxerBox}; -use libp2p::transport_timeout::TransportTimeout; -use std::time::Duration; -use std::usize; +use futures::prelude::*; +use libp2p::{ + InboundUpgradeExt, OutboundUpgradeExt, PeerId, Transport, + mplex, secio, yamux, tcp, dns, websocket, bandwidth +}; +use libp2p::core::{self, transport::boxed::Boxed, muxing::StreamMuxerBox}; +use std::{io, sync::Arc, time::Duration, usize}; + +pub use self::bandwidth::BandwidthSinks; /// Builds the transport that serves as a common ground for all connections. +/// +/// Returns a `BandwidthSinks` object that allows querying the average bandwidth produced by all +/// the connections spawned with this transport. pub fn build_transport( local_private_key: secio::SecioKeyPair -) -> Boxed<(PeerId, StreamMuxerBox)> { +) -> (Boxed<(PeerId, StreamMuxerBox), io::Error>, Arc) { let mut mplex_config = mplex::MplexConfig::new(); mplex_config.max_buffer_len_behaviour(mplex::MaxBufferBehaviour::Block); mplex_config.max_buffer_len(usize::MAX); - let base = libp2p::CommonTransport::new() + let transport = tcp::TcpConfig::new(); + let transport = websocket::WsConfig::new(transport.clone()).or_transport(transport); + let transport = dns::DnsConfig::new(transport); + let (transport, sinks) = bandwidth::BandwidthLogging::new(transport, Duration::from_secs(5)); + + // TODO: rework the transport creation (https://github.com/libp2p/rust-libp2p/issues/783) + let transport = transport .with_upgrade(secio::SecioConfig::new(local_private_key)) .and_then(move |out, endpoint| { - let upgrade = upgrade::or( - upgrade::map(yamux::Config::default(), either::EitherOutput::First), - upgrade::map(mplex_config, either::EitherOutput::Second), - ); let peer_id = out.remote_key.into_peer_id(); - let upgrade = upgrade::map(upgrade, move |muxer| (peer_id, muxer)); - upgrade::apply(out.stream, upgrade, endpoint.into()) + let peer_id2 = peer_id.clone(); + let upgrade = core::upgrade::SelectUpgrade::new(yamux::Config::default(), mplex_config) + .map_inbound(move |muxer| (peer_id, muxer)) + .map_outbound(move |muxer| (peer_id2, muxer)); + + core::upgrade::apply(out.stream, upgrade, endpoint) + .map(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer))) }) - .map(|(id, muxer), _| (id, StreamMuxerBox::new(muxer))); + .with_timeout(Duration::from_secs(20)) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .boxed(); - TransportTimeout::new(base, Duration::from_secs(20)) - .boxed() + (transport, sinks) } diff --git a/core/network-libp2p/tests/test.rs b/core/network-libp2p/tests/test.rs new file mode 100644 index 0000000000000000000000000000000000000000..979cf9b0445097d03871079d66d809e937733e95 --- /dev/null +++ b/core/network-libp2p/tests/test.rs @@ -0,0 +1,262 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use futures::{future, stream, prelude::*, try_ready}; +use rand::seq::SliceRandom; +use std::{io, iter}; +use substrate_network_libp2p::{CustomMessage, Protocol, ServiceEvent, build_multiaddr}; + +/// Builds two services. The second one and further have the first one as its bootstrap node. +/// This is to be used only for testing, and a panic will happen if something goes wrong. +fn build_nodes(num: usize) -> Vec> + where TMsg: CustomMessage + Send + 'static +{ + let mut result: Vec> = Vec::with_capacity(num); + + for _ in 0 .. num { + let mut boot_nodes = Vec::new(); + if !result.is_empty() { + let mut bootnode = result[0].listeners().next().unwrap().clone(); + bootnode.append(Protocol::P2p(result[0].peer_id().clone().into())); + boot_nodes.push(bootnode.to_string()); + } + + let config = substrate_network_libp2p::NetworkConfiguration { + listen_addresses: vec![build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0u16)]], + boot_nodes, + ..substrate_network_libp2p::NetworkConfiguration::default() + }; + + let proto = substrate_network_libp2p::RegisteredProtocol::new(*b"tst", &[1]); + result.push(substrate_network_libp2p::start_service(config, iter::once(proto)).unwrap()); + } + + result +} + +#[test] +fn basic_two_nodes_connectivity() { + let (mut service1, mut service2) = { + let mut l = build_nodes::>(2).into_iter(); + let a = l.next().unwrap(); + let b = l.next().unwrap(); + (a, b) + }; + + let fut1 = future::poll_fn(move || -> io::Result<_> { + match try_ready!(service1.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { protocol, version, .. }) => { + assert_eq!(protocol, *b"tst"); + assert_eq!(version, 1); + Ok(Async::Ready(())) + }, + _ => panic!(), + } + }); + + let fut2 = future::poll_fn(move || -> io::Result<_> { + match try_ready!(service2.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { protocol, version, .. }) => { + assert_eq!(protocol, *b"tst"); + assert_eq!(version, 1); + Ok(Async::Ready(())) + }, + _ => panic!(), + } + }); + + let combined = fut1.select(fut2).map_err(|(err, _)| err); + tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap(); +} + +#[test] +fn two_nodes_transfer_lots_of_packets() { + // We spawn two nodes, then make the first one send lots of packets to the second one. The test + // ends when the second one has received all of them. + + // Note that if we go too high, we will reach the limit to the number of simultaneous + // substreams allowed by the multiplexer. + const NUM_PACKETS: u32 = 5000; + + let (mut service1, mut service2) = { + let mut l = build_nodes::>(2).into_iter(); + let a = l.next().unwrap(); + let b = l.next().unwrap(); + (a, b) + }; + + let fut1 = future::poll_fn(move || -> io::Result<_> { + loop { + match try_ready!(service1.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { node_index, protocol, .. }) => { + for n in 0 .. NUM_PACKETS { + service1.send_custom_message(node_index, protocol, vec![(n % 256) as u8]); + } + }, + _ => panic!(), + } + } + }); + + let mut packet_counter = 0u32; + let fut2 = future::poll_fn(move || -> io::Result<_> { + loop { + match try_ready!(service2.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { .. }) => {}, + Some(ServiceEvent::CustomMessage { message, .. }) => { + assert_eq!(message.len(), 1); + packet_counter += 1; + if packet_counter == NUM_PACKETS { + return Ok(Async::Ready(())) + } + } + _ => panic!(), + } + } + }); + + let combined = fut1.select(fut2).map_err(|(err, _)| err); + tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap(); +} + +#[test] +#[ignore] +// TODO: remove ignore once this test it fixed. #1777 +fn many_nodes_connectivity() { + // Creates many nodes, then make sure that they are all connected to each other. + // Note: if you increase this number, keep in mind that there's a limit to the number of + // simultaneous connections which will make the test fail if it is reached. This can be + // increased in the `NetworkConfiguration`. + const NUM_NODES: usize = 25; + + let mut futures = build_nodes::>(NUM_NODES) + .into_iter() + .map(move |mut node| { + let mut num_connecs = 0; + stream::poll_fn(move || -> io::Result<_> { + loop { + const MAX_BANDWIDTH: u64 = NUM_NODES as u64 * 1024; // 1kiB/s/node + assert!(node.average_download_per_sec() < MAX_BANDWIDTH); + assert!(node.average_upload_per_sec() < MAX_BANDWIDTH); + + match try_ready!(node.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { .. }) => { + num_connecs += 1; + assert!(num_connecs < NUM_NODES); + if num_connecs == NUM_NODES - 1 { + return Ok(Async::Ready(Some(true))) + } + } + Some(ServiceEvent::ClosedCustomProtocol { .. }) => { + let was_success = num_connecs == NUM_NODES - 1; + num_connecs -= 1; + if was_success && num_connecs < NUM_NODES - 1 { + return Ok(Async::Ready(Some(false))) + } + } + _ => panic!(), + } + } + }) + }) + .collect::>(); + + let mut successes = 0; + let combined = future::poll_fn(move || -> io::Result<_> { + for node in futures.iter_mut() { + match node.poll()? { + Async::Ready(Some(true)) => successes += 1, + Async::Ready(Some(false)) => successes -= 1, + Async::Ready(None) => unreachable!(), + Async::NotReady => () + } + } + + if successes == NUM_NODES { + Ok(Async::Ready(())) + } else { + Ok(Async::NotReady) + } + }); + + tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap(); +} + +#[test] +fn basic_two_nodes_requests_in_parallel() { + let (mut service1, mut service2) = { + let mut l = build_nodes::<(Option, Vec)>(2).into_iter(); + let a = l.next().unwrap(); + let b = l.next().unwrap(); + (a, b) + }; + + // Generate random messages with or without a request id. + let mut to_send = { + let mut to_send = Vec::new(); + let mut next_id = 0; + for _ in 0..200 { // Note: don't make that number too high or the CPU usage will explode. + let id = if rand::random::() % 4 != 0 { + let i = next_id; + next_id += 1; + Some(i) + } else { + None + }; + + let msg = (id, (0..10).map(|_| rand::random::()).collect::>()); + to_send.push(msg); + } + to_send + }; + + // Clone `to_send` in `to_receive`. Below we will remove from `to_receive` the messages we + // receive, until the list is empty. + let mut to_receive = to_send.clone(); + to_send.shuffle(&mut rand::thread_rng()); + + let fut1 = future::poll_fn(move || -> io::Result<_> { + loop { + match try_ready!(service1.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { node_index, protocol, .. }) => { + for msg in to_send.drain(..) { + service1.send_custom_message(node_index, protocol, msg); + } + }, + _ => panic!(), + } + } + }); + + let fut2 = future::poll_fn(move || -> io::Result<_> { + loop { + match try_ready!(service2.poll()) { + Some(ServiceEvent::OpenedCustomProtocol { .. }) => {}, + Some(ServiceEvent::CustomMessage { message, .. }) => { + let pos = to_receive.iter().position(|m| *m == message).unwrap(); + to_receive.remove(pos); + if to_receive.is_empty() { + return Ok(Async::Ready(())) + } + } + _ => panic!(), + } + } + }); + + let combined = fut1.select(fut2).map_err(|(err, _)| err); + tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap(); +} diff --git a/core/network/Cargo.toml b/core/network/Cargo.toml index 7eadefb3637f3ec2607f2534a6ba108e60cc3cdb..6e7e8599db97196a9bbb3000a963fa4dd4b433ab 100644 --- a/core/network/Cargo.toml +++ b/core/network/Cargo.toml @@ -4,36 +4,38 @@ name = "substrate-network" version = "0.1.0" license = "GPL-3.0" authors = ["Parity Technologies "] +edition = "2018" [lib] [dependencies] +crossbeam-channel = "0.3.6" log = "0.4" -parking_lot = "0.4" +parking_lot = "0.7.1" error-chain = "0.12" bitflags = "1.0" futures = "0.1.17" linked-hash-map = "0.5" -rustc-hex = "1.0" -rand = "0.5" -substrate-primitives = { path = "../../core/primitives" } -substrate-consensus-common = { path = "../../core/consensus/common" } -substrate-client = { path = "../../core/client" } -sr-primitives = { path = "../../core/sr-primitives" } -parity-codec = "2.1" -parity-codec-derive = "2.1" -substrate-network-libp2p = { path = "../../core/network-libp2p" } +linked_hash_set = "0.1.3" +lru-cache = "0.1.1" +rustc-hex = "2.0" +rand = "0.6" +fork-tree = { path = "../../core/util/fork-tree" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } +client = { package = "substrate-client", path = "../../core/client" } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +parity-codec = { version = "3.2", features = ["derive"] } +network_libp2p = { package = "substrate-network-libp2p", path = "../../core/network-libp2p" } tokio = "0.1.11" - -env_logger = { version = "0.4", optional = true } -substrate-keyring = { path = "../../core/keyring", optional = true } -substrate-test-client = { path = "../../core/test-client", optional = true } +keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true } +test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true } [dev-dependencies] -env_logger = { version = "0.4" } -substrate-keyring = { path = "../../core/keyring" } -substrate-test-client = { path = "../../core/test-client" } +env_logger = { version = "0.6" } +keyring = { package = "substrate-keyring", path = "../../core/keyring" } +test_client = { package = "substrate-test-client", path = "../../core/test-client" } [features] default = [] -test-helpers = ["env_logger", "substrate-keyring", "substrate-test-client"] +test-helpers = ["keyring", "test_client"] diff --git a/core/network/src/blocks.rs b/core/network/src/blocks.rs index db4c38af45aa68b5d309071c277a66b1502e0149..d1e71ca68eeed36f6990f7b232adaf433e705e2d 100644 --- a/core/network/src/blocks.rs +++ b/core/network/src/blocks.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,9 +19,10 @@ use std::cmp; use std::ops::Range; use std::collections::{HashMap, BTreeMap}; use std::collections::hash_map::Entry; +use log::trace; use network_libp2p::NodeIndex; use runtime_primitives::traits::{Block as BlockT, NumberFor, As}; -use message; +use crate::message; const MAX_PARALLEL_DOWNLOADS: u32 = 1; @@ -194,7 +195,7 @@ impl BlockCollection { #[cfg(test)] mod test { use super::{BlockCollection, BlockData, BlockRangeState}; - use message; + use crate::message; use runtime_primitives::testing::{Block as RawBlock, ExtrinsicWrapper}; use primitives::H256; diff --git a/core/network/src/chain.rs b/core/network/src/chain.rs index 8547f9006e3b46294f4fa3e80ddc7a80c0696c6f..87c0dca9c1306e14ccd85ea1274f44dece25789c 100644 --- a/core/network/src/chain.rs +++ b/core/network/src/chain.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,18 +19,18 @@ use client::{self, Client as SubstrateClient, ClientInfo, BlockStatus, CallExecutor}; use client::error::Error; use client::light::fetcher::ChangesProof; -use consensus::BlockImport; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; +use consensus::{BlockImport, Error as ConsensusError}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, AuthorityIdFor}; use runtime_primitives::generic::{BlockId}; use consensus::{ImportBlock, ImportResult}; use runtime_primitives::Justification; -use primitives::{H256, Blake2Hasher, AuthorityId}; +use primitives::{H256, Blake2Hasher, storage::StorageKey}; /// Local client abstraction for the network. pub trait Client: Send + Sync { /// Import a new block. Parent is supposed to be existing in the blockchain. - fn import(&self, block: ImportBlock, new_authorities: Option>) - -> Result; + fn import(&self, block: ImportBlock, new_authorities: Option>>) + -> Result; /// Get blockchain info. fn info(&self) -> Result, Error>; @@ -66,19 +66,22 @@ pub trait Client: Send + Sync { last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &[u8] + key: &StorageKey ) -> Result, Error>; + + /// Returns `true` if the given `block` is a descendent of `base`. + fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result; } impl Client for SubstrateClient where B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static, - Self: BlockImport, + Self: BlockImport, Block: BlockT, RA: Send + Sync { - fn import(&self, block: ImportBlock, new_authorities: Option>) - -> Result + fn import(&self, block: ImportBlock, new_authorities: Option>>) + -> Result { (self as &SubstrateClient).import_block(block, new_authorities) } @@ -125,8 +128,22 @@ impl Client for SubstrateClient where last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &[u8] + key: &StorageKey ) -> Result, Error> { (self as &SubstrateClient).key_changes_proof(first, last, min, max, key) } + + fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result { + if base == block { + return Ok(false); + } + + let tree_route = ::client::blockchain::tree_route( + self.backend().blockchain(), + BlockId::Hash(*block), + BlockId::Hash(*base), + )?; + + Ok(tree_route.common_block().hash == *base) + } } diff --git a/core/network/src/config.rs b/core/network/src/config.rs index a7936ce4915ab34455f86c2c67981e8abc778f7d..7dd4b52b3129f5ddd2818e6caf7dc49dfae8d613 100644 --- a/core/network/src/config.rs +++ b/core/network/src/config.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,13 +16,14 @@ //! Configuration for the networking layer of Substrate. -pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration}; +pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, Secret}; -use chain::Client; -use codec; -use on_demand::OnDemandService; +use bitflags::bitflags; +use crate::chain::Client; +use parity_codec; +use crate::on_demand::OnDemandService; use runtime_primitives::traits::{Block as BlockT}; -use service::{ExHashT, TransactionPool}; +use crate::service::{ExHashT, TransactionPool}; use std::sync::Arc; /// Service initialization parameters. @@ -70,14 +71,14 @@ bitflags! { } } -impl codec::Encode for Roles { - fn encode_to(&self, dest: &mut T) { +impl parity_codec::Encode for Roles { + fn encode_to(&self, dest: &mut T) { dest.push_byte(self.bits()) } } -impl codec::Decode for Roles { - fn decode(input: &mut I) -> Option { +impl parity_codec::Decode for Roles { + fn decode(input: &mut I) -> Option { Self::from_bits(input.read_byte()?) } } diff --git a/core/network/src/consensus_gossip.rs b/core/network/src/consensus_gossip.rs index b9eec32b30cd1f95108ffa0d755d1c80b72e8aa7..72a384e97a6fd69c19fabe8a32d542f9fc07286c 100644 --- a/core/network/src/consensus_gossip.rs +++ b/core/network/src/consensus_gossip.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,39 +18,75 @@ //! Handles chain-specific and standard BFT messages. use std::collections::{HashMap, HashSet}; -use futures::sync::mpsc; +use std::sync::Arc; use std::time::{Instant, Duration}; -use rand::{self, Rng}; -use network_libp2p::NodeIndex; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor}; -use runtime_primitives::generic::BlockId; -pub use message::generic::{Message, ConsensusMessage}; -use protocol::Context; -use config::Roles; +use log::{trace, debug}; +use futures::sync::mpsc; +use rand::{self, seq::SliceRandom}; +use lru_cache::LruCache; +use network_libp2p::{Severity, NodeIndex}; +use runtime_primitives::traits::{Block as BlockT, Hash, HashFor}; +pub use crate::message::generic::{Message, ConsensusMessage}; +use crate::protocol::Context; +use crate::config::Roles; +use crate::ConsensusEngineId; // FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115 -const MESSAGE_LIFETIME: Duration = Duration::from_secs(600); +const MESSAGE_LIFETIME: Duration = Duration::from_secs(120); +const KNOWN_MESSAGES_CACHE_SIZE: usize = 4096; struct PeerConsensus { known_messages: HashSet, is_authority: bool, } +#[derive(Clone, Copy)] +enum Status { + Live, + Future, +} + struct MessageEntry { - topic: B::Hash, message_hash: B::Hash, + topic: B::Hash, message: ConsensusMessage, - broadcast: bool, - instant: Instant, + timestamp: Instant, + status: Status, +} + +/// Message validation result. +pub enum ValidationResult { + /// Message is valid with this topic. + Valid(H), + /// Message is future with this topic. + Future(H), + /// Invalid message. + Invalid, + /// Obsolete message. + Expired, +} + +/// Validates consensus messages. +pub trait Validator { + /// Validate consensus message. + fn validate(&self, data: &[u8]) -> ValidationResult; + + /// Produce a closure for validating messages on a given topic. + fn message_expired<'a>(&'a self) -> Box bool + 'a> { + Box::new(move |_topic, data| match self.validate(data) { + ValidationResult::Valid(_) | ValidationResult::Future(_) => false, + ValidationResult::Invalid | ValidationResult::Expired => true, + }) + } } /// Consensus network protocol handler. Manages statements and candidate requests. pub struct ConsensusGossip { - peers: HashMap>, - live_message_sinks: HashMap>>, + peers: HashMap>, + live_message_sinks: HashMap<(ConsensusEngineId, B::Hash), Vec>>>, messages: Vec>, - known_messages: HashSet<(B::Hash, B::Hash)>, - session_start: Option, + known_messages: LruCache, + validators: HashMap>>, } impl ConsensusGossip { @@ -60,8 +96,8 @@ impl ConsensusGossip { peers: HashMap::new(), live_message_sinks: HashMap::new(), messages: Default::default(), - known_messages: Default::default(), - session_start: None + known_messages: LruCache::new(KNOWN_MESSAGES_CACHE_SIZE), + validators: Default::default(), } } @@ -70,16 +106,24 @@ impl ConsensusGossip { self.live_message_sinks.clear(); } + /// Register message validator for a message type. + pub fn register_validator(&mut self, engine_id: ConsensusEngineId, validator: Arc>) { + self.validators.insert(engine_id, validator); + } + /// Handle new connected peer. pub fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex, roles: Roles) { if roles.intersects(Roles::AUTHORITY) { trace!(target:"gossip", "Registering {:?} {}", roles, who); + let now = Instant::now(); // Send out all known messages to authorities. - // TODO: limit by size let mut known_messages = HashSet::new(); for entry in self.messages.iter() { - known_messages.insert((entry.topic, entry.message_hash)); - protocol.send_message(who, Message::Consensus(entry.topic.clone(), entry.message.clone(), entry.broadcast)); + if entry.timestamp + MESSAGE_LIFETIME < now { continue } + if let Status::Future = entry.status { continue } + + known_messages.insert(entry.message_hash); + protocol.send_message(who, Message::Consensus(entry.message.clone())); } self.peers.insert(who, PeerConsensus { known_messages, @@ -98,33 +142,21 @@ impl ConsensusGossip { &mut self, protocol: &mut Context, message_hash: B::Hash, - topic: B::Hash, - broadcast: bool, get_message: F, ) where F: Fn() -> ConsensusMessage, { - if broadcast { - for (id, ref mut peer) in self.peers.iter_mut() { - if peer.known_messages.insert((topic.clone(), message_hash.clone())) { - let message = get_message(); - if peer.is_authority { - trace!(target:"gossip", "Propagating to authority {}: {:?}", id, message); - } else { - trace!(target:"gossip", "Propagating to {}: {:?}", id, message); - } - protocol.send_message(*id, Message::Consensus(topic, message, broadcast)); - } - } - - return; - } - let mut non_authorities: Vec<_> = self.peers.iter() - .filter_map(|(id, ref peer)| if !peer.is_authority && !peer.known_messages.contains(&(topic, message_hash)) { Some(*id) } else { None }) + .filter_map(|(id, ref peer)| + if !peer.is_authority && !peer.known_messages.contains(&message_hash) { + Some(*id) + } else { + None + } + ) .collect(); - rand::thread_rng().shuffle(&mut non_authorities); + non_authorities.shuffle(&mut rand::thread_rng()); let non_authorities: HashSet<_> = if non_authorities.is_empty() { HashSet::new() } else { @@ -133,30 +165,37 @@ impl ConsensusGossip { for (id, ref mut peer) in self.peers.iter_mut() { if peer.is_authority { - if peer.known_messages.insert((topic.clone(), message_hash.clone())) { + if peer.known_messages.insert(message_hash.clone()) { let message = get_message(); trace!(target:"gossip", "Propagating to authority {}: {:?}", id, message); - protocol.send_message(*id, Message::Consensus(topic, message, broadcast)); + protocol.send_message(*id, Message::Consensus(message)); } } else if non_authorities.contains(&id) { - let message = get_message(); - trace!(target:"gossip", "Propagating to {}: {:?}", id, message); - peer.known_messages.insert((topic.clone(), message_hash.clone())); - protocol.send_message(*id, Message::Consensus(topic, message, broadcast)); + if peer.known_messages.insert(message_hash.clone()) { + let message = get_message(); + trace!(target:"gossip", "Propagating to {}: {:?}", id, message); + protocol.send_message(*id, Message::Consensus(message)); + } } } } - fn register_message(&mut self, message_hash: B::Hash, topic: B::Hash, broadcast: bool, get_message: F) + fn register_message( + &mut self, + message_hash: B::Hash, + topic: B::Hash, + status: Status, + get_message: F, + ) where F: Fn() -> ConsensusMessage { - if self.known_messages.insert((topic, message_hash)) { + if self.known_messages.insert(message_hash, ()).is_none() { self.messages.push(MessageEntry { topic, message_hash, - broadcast, - instant: Instant::now(), message: get_message(), + timestamp: Instant::now(), + status, }); } } @@ -168,36 +207,89 @@ impl ConsensusGossip { /// Prune old or no longer relevant consensus messages. Provide a predicate /// for pruning, which returns `false` when the items with a given topic should be pruned. - pub fn collect_garbage bool>(&mut self, predicate: P) { + pub fn collect_garbage(&mut self) { + use std::collections::hash_map::Entry; + self.live_message_sinks.retain(|_, sinks| { sinks.retain(|sink| !sink.is_closed()); !sinks.is_empty() }); - let hashes = &mut self.known_messages; + let known_messages = &mut self.known_messages; let before = self.messages.len(); + let validators = &self.validators; let now = Instant::now(); - self.messages.retain(|entry| { - if entry.instant + MESSAGE_LIFETIME >= now && predicate(&entry.topic) { - true - } else { - hashes.remove(&(entry.topic, entry.message_hash)); - false - } - }); - trace!(target:"gossip", "Cleaned up {} stale messages, {} left", before - self.messages.len(), self.messages.len()); + + let mut check_fns = HashMap::new(); + let mut message_expired = move |entry: &MessageEntry| { + let engine_id = entry.message.engine_id; + let check_fn = match check_fns.entry(engine_id) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(vacant) => match validators.get(&engine_id) { + None => return true, // treat all messages with no validator as expired + Some(validator) => vacant.insert(validator.message_expired()), + } + }; + + (check_fn)(entry.topic, &entry.message.data) + }; + + self.messages.retain(|entry| + entry.timestamp + MESSAGE_LIFETIME >= now && !message_expired(entry) + ); + + trace!(target: "gossip", "Cleaned up {} stale messages, {} left ({} known)", + before - self.messages.len(), + self.messages.len(), + known_messages.len(), + ); + for (_, ref mut peer) in self.peers.iter_mut() { - peer.known_messages.retain(|h| hashes.contains(h)); + peer.known_messages.retain(|h| known_messages.contains_key(h)); } } - /// Get all incoming messages for a topic. - pub fn messages_for(&mut self, topic: B::Hash) -> mpsc::UnboundedReceiver { + /// Get data of valid, incoming messages for a topic (but might have expired meanwhile) + pub fn messages_for(&mut self, engine_id: ConsensusEngineId, topic: B::Hash) + -> mpsc::UnboundedReceiver> + { let (tx, rx) = mpsc::unbounded(); - for entry in self.messages.iter().filter(|e| e.topic == topic) { - tx.unbounded_send(entry.message.clone()).expect("receiver known to be live; qed"); + + let validator = match self.validators.get(&engine_id) { + None => { + self.live_message_sinks.entry((engine_id, topic)).or_default().push(tx); + return rx; + } + Some(v) => v, + }; + + for entry in self.messages.iter_mut() + .filter(|e| e.topic == topic && e.message.engine_id == engine_id) + { + let live = match entry.status { + Status::Live => true, + Status::Future => match validator.validate(&entry.message.data) { + ValidationResult::Valid(_) => { + entry.status = Status::Live; + true + } + _ => { + // don't send messages considered to be future still. + // if messages are considered expired they'll be cleaned up when we + // collect garbage. + false + } + } + }; + + if live { + entry.status = Status::Live; + tx.unbounded_send(entry.message.data.clone()) + .expect("receiver known to be live; qed"); + } } - self.live_message_sinks.entry(topic).or_default().push(tx); + + self.live_message_sinks.entry((engine_id, topic)).or_default().push(tx); rx } @@ -210,39 +302,53 @@ impl ConsensusGossip { &mut self, protocol: &mut Context, who: NodeIndex, - topic: B::Hash, message: ConsensusMessage, - broadcast: bool, ) -> Option<(B::Hash, ConsensusMessage)> { - let message_hash = HashFor::::hash(&message[..]); + let message_hash = HashFor::::hash(&message.data[..]); - if self.known_messages.contains(&(topic, message_hash)) { - trace!(target:"gossip", "Ignored already known message from {} in {}", who, topic); + if self.known_messages.contains_key(&message_hash) { + trace!(target:"gossip", "Ignored already known message from {}", who); return None; } - match (protocol.client().info(), protocol.client().header(&BlockId::Hash(topic))) { - (_, Err(e)) | (Err(e), _) => { - debug!(target:"gossip", "Error reading blockchain: {:?}", e); - return None; - }, - (Ok(info), Ok(Some(header))) => { - if header.number() < &info.chain.best_number { - trace!(target:"gossip", "Ignored ancient message from {}, hash={}", who, topic); + if let Some(ref mut peer) = self.peers.get_mut(&who) { + use std::collections::hash_map::Entry; + + let engine_id = message.engine_id; + // validate the message + let (topic, status) = match self.validators.get(&engine_id) + .map(|v| v.validate(&message.data)) + { + Some(ValidationResult::Valid(topic)) => (topic, Status::Live), + Some(ValidationResult::Future(topic)) => (topic, Status::Future), + Some(ValidationResult::Invalid) => { + trace!(target:"gossip", "Invalid message from {}", who); + protocol.report_peer( + who, + Severity::Bad(format!("Sent invalid consensus message")), + ); + return None; + }, + Some(ValidationResult::Expired) => { + trace!(target:"gossip", "Ignored expired message from {}", who); return None; } - }, - (Ok(_), Ok(None)) => {}, - } - + None => { + protocol.report_peer( + who, + Severity::Useless(format!("Sent unknown consensus engine id")), + ); + trace!(target:"gossip", "Unknown message engine id {:?} from {}", + engine_id, who); + return None; + } + }; - if let Some(ref mut peer) = self.peers.get_mut(&who) { - use std::collections::hash_map::Entry; - peer.known_messages.insert((topic, message_hash)); - if let Entry::Occupied(mut entry) = self.live_message_sinks.entry(topic) { + peer.known_messages.insert(message_hash); + if let Entry::Occupied(mut entry) = self.live_message_sinks.entry((engine_id, topic)) { debug!(target: "gossip", "Pushing consensus message to sinks for {}.", topic); entry.get_mut().retain(|sink| { - if let Err(e) = sink.unbounded_send(message.clone()) { + if let Err(e) = sink.unbounded_send(message.data.clone()) { trace!(target:"gossip", "Error broadcasting message notification: {:?}", e); } !sink.is_closed() @@ -251,13 +357,12 @@ impl ConsensusGossip { entry.remove_entry(); } } + self.multicast_inner(protocol, message_hash, topic, status, || message.clone()); + Some((topic, message)) } else { trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); - return None; + None } - - self.multicast_inner(protocol, message_hash, topic, broadcast, || message.clone()); - Some((topic, message)) } /// Multicast a message to all peers. @@ -266,10 +371,9 @@ impl ConsensusGossip { protocol: &mut Context, topic: B::Hash, message: ConsensusMessage, - broadcast: bool, ) { - let message_hash = HashFor::::hash(&message); - self.multicast_inner(protocol, message_hash, topic, broadcast, || message.clone()); + let message_hash = HashFor::::hash(&message.data); + self.multicast_inner(protocol, message_hash, topic, Status::Live, || message.clone()); } fn multicast_inner( @@ -277,20 +381,20 @@ impl ConsensusGossip { protocol: &mut Context, message_hash: B::Hash, topic: B::Hash, - broadcast: bool, + status: Status, get_message: F, ) where F: Fn() -> ConsensusMessage { - self.register_message(message_hash, topic, broadcast, &get_message); - self.propagate(protocol, message_hash, topic, broadcast, get_message); + self.register_message(message_hash, topic, status, &get_message); + if let Status::Live = status { + self.propagate(protocol, message_hash, get_message); + } } /// Note new consensus session. - pub fn new_session(&mut self, parent_hash: B::Hash) { - let old_session = self.session_start.take(); - self.session_start = Some(parent_hash); - self.collect_garbage(|topic| old_session.as_ref().map_or(true, |h| topic != h)); + pub fn new_session(&mut self, _parent_hash: B::Hash) { + self.collect_garbage(); } } @@ -298,60 +402,83 @@ impl ConsensusGossip { mod tests { use runtime_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; use std::time::Instant; + use futures::Stream; + use super::*; type Block = RawBlock>; + macro_rules! push_msg { + ($consensus:expr, $topic:expr, $hash: expr, $now: expr, $m:expr) => { + if $consensus.known_messages.insert($hash, ()).is_none() { + $consensus.messages.push(MessageEntry { + topic: $topic, + message_hash: $hash, + message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0]}, + timestamp: $now, + status: Status::Live, + }); + } + } + } + + struct AllowAll; + impl Validator for AllowAll { + fn validate(&self, _data: &[u8]) -> ValidationResult { + ValidationResult::Valid(H256::default()) + } + } + #[test] fn collects_garbage() { + struct AllowOne; + impl Validator for AllowOne { + fn validate(&self, data: &[u8]) -> ValidationResult { + if data[0] == 1 { + ValidationResult::Valid(H256::default()) + } else { + ValidationResult::Expired + } + } + } + let prev_hash = H256::random(); let best_hash = H256::random(); let mut consensus = ConsensusGossip::::new(); - let now = Instant::now(); let m1_hash = H256::random(); let m2_hash = H256::random(); let m1 = vec![1, 2, 3]; let m2 = vec![4, 5, 6]; - macro_rules! push_msg { - ($topic:expr, $hash: expr, $now: expr, $m:expr) => { - consensus.messages.push(MessageEntry { - topic: $topic, - message_hash: $hash, - instant: $now, - message: $m, - broadcast: false, - }) - } - } - - push_msg!(prev_hash, m1_hash, now, m1); - push_msg!(best_hash, m2_hash, now, m2.clone()); - consensus.known_messages.insert((prev_hash, m1_hash)); - consensus.known_messages.insert((best_hash, m2_hash)); - - // nothing to collect - consensus.collect_garbage(|_t| true); + let now = Instant::now(); + push_msg!(consensus, prev_hash, m1_hash, now, m1); + push_msg!(consensus, best_hash, m2_hash, now, m2.clone()); + consensus.known_messages.insert(m1_hash, ()); + consensus.known_messages.insert(m2_hash, ()); + + let test_engine_id = Default::default(); + consensus.register_validator(test_engine_id, Arc::new(AllowAll)); + consensus.collect_garbage(); assert_eq!(consensus.messages.len(), 2); assert_eq!(consensus.known_messages.len(), 2); - // nothing to collect with default. - consensus.collect_garbage(|&topic| topic != Default::default()); - assert_eq!(consensus.messages.len(), 2); - assert_eq!(consensus.known_messages.len(), 2); + consensus.register_validator(test_engine_id, Arc::new(AllowOne)); - // topic that was used in one message. - consensus.collect_garbage(|topic| topic != &prev_hash); + // m2 is expired + consensus.collect_garbage(); assert_eq!(consensus.messages.len(), 1); - assert_eq!(consensus.known_messages.len(), 1); - assert!(consensus.known_messages.contains(&(best_hash, m2_hash))); + // known messages are only pruned based on size. + assert_eq!(consensus.known_messages.len(), 2); + assert!(consensus.known_messages.contains_key(&m2_hash)); - // make timestamp expired + // make timestamp expired, but the message is still kept as known consensus.messages.clear(); - push_msg!(best_hash, m2_hash, now - MESSAGE_LIFETIME, m2); - consensus.collect_garbage(|_topic| true); + consensus.known_messages.clear(); + consensus.register_validator(test_engine_id, Arc::new(AllowAll)); + push_msg!(consensus, best_hash, m2_hash, now - MESSAGE_LIFETIME, m2.clone()); + consensus.collect_garbage(); assert!(consensus.messages.is_empty()); - assert!(consensus.known_messages.is_empty()); + assert_eq!(consensus.known_messages.len(), 1); } #[test] @@ -359,16 +486,17 @@ mod tests { use futures::Stream; let mut consensus = ConsensusGossip::::new(); + consensus.register_validator([0, 0, 0, 0], Arc::new(AllowAll)); - let message = vec![1, 2, 3]; + let message = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; - let message_hash = HashFor::::hash(&message); + let message_hash = HashFor::::hash(&message.data); let topic = HashFor::::hash(&[1,2,3]); - consensus.register_message(message_hash, topic, false, || message.clone()); - let stream = consensus.messages_for(topic); + consensus.register_message(message_hash, topic, Status::Live, || message.clone()); + let stream = consensus.messages_for([0, 0, 0, 0], topic); - assert_eq!(stream.wait().next(), Some(Ok(message))); + assert_eq!(stream.wait().next(), Some(Ok(message.data))); } #[test] @@ -376,32 +504,50 @@ mod tests { let mut consensus = ConsensusGossip::::new(); let topic = [1; 32].into(); - let msg_a = vec![1, 2, 3]; - let msg_b = vec![4, 5, 6]; + let msg_a = ConsensusMessage { data: vec![1, 2, 3], engine_id: [0, 0, 0, 0] }; + let msg_b = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; - consensus.register_message(HashFor::::hash(&msg_a), topic, false, || msg_a.clone()); - consensus.register_message(HashFor::::hash(&msg_b), topic, false, || msg_b.clone()); + consensus.register_message(HashFor::::hash(&msg_a.data), topic, Status::Live, || msg_a.clone()); + consensus.register_message(HashFor::::hash(&msg_b.data), topic, Status::Live, || msg_b.clone()); assert_eq!(consensus.messages.len(), 2); } #[test] fn can_keep_multiple_subscribers_per_topic() { - use futures::Stream; - let mut consensus = ConsensusGossip::::new(); + consensus.register_validator([0, 0, 0, 0], Arc::new(AllowAll)); - let message = vec![1, 2, 3]; + let message = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; - let message_hash = HashFor::::hash(&message); + let message_hash = HashFor::::hash(&message.data); let topic = HashFor::::hash(&[1,2,3]); - consensus.register_message(message_hash, topic, false, || message.clone()); + consensus.register_message(message_hash, topic, Status::Live, || message.clone()); + + let stream1 = consensus.messages_for([0, 0, 0, 0], topic); + let stream2 = consensus.messages_for([0, 0, 0, 0], topic); + + assert_eq!(stream1.wait().next(), Some(Ok(message.data.clone()))); + assert_eq!(stream2.wait().next(), Some(Ok(message.data))); + } + + #[test] + fn topics_are_localized_to_engine_id() { + let mut consensus = ConsensusGossip::::new(); + consensus.register_validator([0, 0, 0, 0], Arc::new(AllowAll)); + + let topic = [1; 32].into(); + let msg_a = ConsensusMessage { data: vec![1, 2, 3], engine_id: [0, 0, 0, 0] }; + let msg_b = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 1] }; + + consensus.register_message(HashFor::::hash(&msg_a.data), topic, Status::Live, || msg_a.clone()); + consensus.register_message(HashFor::::hash(&msg_b.data), topic, Status::Live, || msg_b.clone()); - let stream1 = consensus.messages_for(topic); - let stream2 = consensus.messages_for(topic); + let mut stream = consensus.messages_for([0, 0, 0, 0], topic).wait(); - assert_eq!(stream1.wait().next(), Some(Ok(message.clone()))); - assert_eq!(stream2.wait().next(), Some(Ok(message))); + assert_eq!(stream.next(), Some(Ok(vec![1, 2, 3]))); + let _ = consensus.live_message_sinks.remove(&([0, 0, 0, 0], topic)); + assert_eq!(stream.next(), None); } } diff --git a/core/network/src/error.rs b/core/network/src/error.rs index dcfdee8fd4ff11b9961b374e6b90e46b5c9b6025..bf687f99698e91a796c3edbf5af11b8314a3b221 100644 --- a/core/network/src/error.rs +++ b/core/network/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,13 +16,16 @@ //! Substrate service possible errors. +// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting` +// https://github.com/paritytech/substrate/issues/1547 +#![allow(deprecated)] + +use error_chain::*; use std::io::Error as IoError; -use network_libp2p::Error as NetworkError; use client; error_chain! { foreign_links { - Network(NetworkError) #[doc = "Devp2p error."]; Io(IoError) #[doc = "IO error."]; } diff --git a/core/network/src/import_queue.rs b/core/network/src/import_queue.rs deleted file mode 100644 index 58919ea75a789aa6108be085ab7ee9570f889d18..0000000000000000000000000000000000000000 --- a/core/network/src/import_queue.rs +++ /dev/null @@ -1,793 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Import Queue primitive: something which can verify and import blocks. -//! -//! This serves as an intermediate and abstracted step between synchronization -//! and import. Each mode of consensus will have its own requirements for block verification. -//! Some algorithms can verify in parallel, while others only sequentially. -//! -//! The `ImportQueue` trait allows such verification strategies to be instantiated. -//! The `BasicQueue` and `BasicVerifier` traits allow serial queues to be -//! instantiated simply. - -use std::collections::{HashSet, VecDeque}; -use std::sync::{Arc, Weak}; -use std::sync::atomic::{AtomicBool, Ordering}; -use parking_lot::{Condvar, Mutex, RwLock}; -use network_libp2p::{NodeIndex, Severity}; -use primitives::AuthorityId; - -use runtime_primitives::Justification; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; - -pub use blocks::BlockData; -use client::error::Error as ClientError; -use error::{ErrorKind, Error}; -use protocol::Context; -use service::ExecuteInContext; -use sync::ChainSync; - -pub use consensus::{ImportBlock, BlockImport, ImportResult, BlockOrigin}; - -/// Shared block import struct used by the queue. -pub type SharedBlockImport = Arc + Send + Sync>; - -#[cfg(any(test, feature = "test-helpers"))] -use std::cell::RefCell; - -/// Verify a justification of a block -pub trait Verifier: Send + Sync + Sized { - /// Verify the given data and return the ImportBlock and an optional - /// new set of validators to import. If not, err with an Error-Message - /// presented to the User in the logs. - fn verify( - &self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - body: Option> - ) -> Result<(ImportBlock, Option>), String>; -} - -/// Blocks import queue API. -pub trait ImportQueue: Send + Sync { - /// Start background work for the queue as necessary. - /// - /// This is called automatically by the network service when synchronization - /// begins. - fn start(&self, _link: L) -> Result<(), Error> where - Self: Sized, - L: 'static + Link, - { - Ok(()) - } - /// Clear the queue when sync is restarting. - fn clear(&self); - /// Clears the import queue and stops importing. - fn stop(&self); - /// Get queue status. - fn status(&self) -> ImportQueueStatus; - /// Is block with given hash currently in the queue. - fn is_importing(&self, hash: &B::Hash) -> bool; - /// Import bunch of blocks. - fn import_blocks(&self, origin: BlockOrigin, blocks: Vec>); -} - -/// Import queue status. It isn't completely accurate. -pub struct ImportQueueStatus { - /// Number of blocks that are currently in the queue. - pub importing_count: usize, - /// The number of the best block that was ever in the queue since start/last failure. - pub best_importing_number: <::Header as HeaderT>::Number, -} - -/// Basic block import queue that is importing blocks sequentially in a separate thread, -/// with pluggable verification. -pub struct BasicQueue> { - handle: Mutex>>, - data: Arc>, - verifier: Arc, - block_import: SharedBlockImport, -} - -/// Locks order: queue, queue_blocks, best_importing_number -struct AsyncImportQueueData { - signal: Condvar, - queue: Mutex>)>>, - queue_blocks: RwLock>, - best_importing_number: RwLock<<::Header as HeaderT>::Number>, - is_stopping: AtomicBool, -} - -impl> BasicQueue { - /// Instantiate a new basic queue, with given verifier. - pub fn new(verifier: Arc, block_import: SharedBlockImport) -> Self { - Self { - handle: Mutex::new(None), - data: Arc::new(AsyncImportQueueData::new()), - verifier, - block_import, - } - } -} - -impl AsyncImportQueueData { - fn new() -> Self { - Self { - signal: Default::default(), - queue: Mutex::new(VecDeque::new()), - queue_blocks: RwLock::new(HashSet::new()), - best_importing_number: RwLock::new(Zero::zero()), - is_stopping: Default::default(), - } - } -} - -impl> ImportQueue for BasicQueue { - fn start>( - &self, - link: L, - ) -> Result<(), Error> { - debug_assert!(self.handle.lock().is_none()); - - let qdata = self.data.clone(); - let verifier = self.verifier.clone(); - let block_import = self.block_import.clone(); - *self.handle.lock() = Some(::std::thread::Builder::new().name("ImportQueue".into()).spawn(move || { - import_thread(block_import, link, qdata, verifier) - }).map_err(|err| Error::from(ErrorKind::Io(err)))?); - Ok(()) - } - - fn clear(&self) { - let mut queue = self.data.queue.lock(); - let mut queue_blocks = self.data.queue_blocks.write(); - let mut best_importing_number = self.data.best_importing_number.write(); - queue_blocks.clear(); - queue.clear(); - *best_importing_number = Zero::zero(); - } - - fn stop(&self) { - self.clear(); - if let Some(handle) = self.handle.lock().take() { - { - // Perform storing the stop flag and signalling under a single lock. - let _queue_lock = self.data.queue.lock(); - self.data.is_stopping.store(true, Ordering::SeqCst); - self.data.signal.notify_one(); - } - - let _ = handle.join(); - } - } - - fn status(&self) -> ImportQueueStatus { - ImportQueueStatus { - importing_count: self.data.queue_blocks.read().len(), - best_importing_number: *self.data.best_importing_number.read(), - } - } - - fn is_importing(&self, hash: &B::Hash) -> bool { - self.data.queue_blocks.read().contains(hash) - } - - fn import_blocks(&self, origin: BlockOrigin, blocks: Vec>) { - if blocks.is_empty() { - return; - } - - trace!(target:"sync", "Scheduling {} blocks for import", blocks.len()); - - let mut queue = self.data.queue.lock(); - let mut queue_blocks = self.data.queue_blocks.write(); - let mut best_importing_number = self.data.best_importing_number.write(); - let new_best_importing_number = blocks.last().and_then(|b| b.block.header.as_ref().map(|h| h.number().clone())).unwrap_or_else(|| Zero::zero()); - queue_blocks.extend(blocks.iter().map(|b| b.block.hash.clone())); - if new_best_importing_number > *best_importing_number { - *best_importing_number = new_best_importing_number; - } - queue.push_back((origin, blocks)); - self.data.signal.notify_one(); - } -} - -impl> Drop for BasicQueue { - fn drop(&mut self) { - self.stop(); - } -} - -/// Blocks import thread. -fn import_thread, V: Verifier>( - block_import: SharedBlockImport, - link: L, - qdata: Arc>, - verifier: Arc -) { - trace!(target: "sync", "Starting import thread"); - loop { - let new_blocks = { - let mut queue_lock = qdata.queue.lock(); - - // We are holding the same lock that `stop` takes so here we either see that stop flag - // is active or wait for the signal. The latter one unlocks the mutex and this gives a chance - // to `stop` to generate the signal. - if qdata.is_stopping.load(Ordering::SeqCst) { - break; - } - if queue_lock.is_empty() { - qdata.signal.wait(&mut queue_lock); - } - - match queue_lock.pop_front() { - Some(new_blocks) => new_blocks, - None => break, - } - }; - - let blocks_hashes: Vec = new_blocks.1.iter().map(|b| b.block.hash.clone()).collect(); - if !import_many_blocks( - &*block_import, - &link, - Some(&*qdata), - new_blocks, - verifier.clone(), - ) { - break; - } - - let mut queue_blocks = qdata.queue_blocks.write(); - for blocks_hash in blocks_hashes { - queue_blocks.remove(&blocks_hash); - } - } - - trace!(target: "sync", "Stopping import thread"); -} - -/// Hooks that the verification queue can use to influence the synchronization -/// algorithm. -pub trait Link: Send { - /// Block imported. - fn block_imported(&self, _hash: &B::Hash, _number: NumberFor) { } - /// Maintain sync. - fn maintain_sync(&self) { } - /// Disconnect from peer. - fn useless_peer(&self, _who: NodeIndex, _reason: &str) { } - /// Disconnect from peer and restart sync. - fn note_useless_and_restart_sync(&self, _who: NodeIndex, _reason: &str) { } - /// Restart sync. - fn restart(&self) { } -} - -/// A link implementation that does nothing. -pub struct NoopLink; - -impl Link for NoopLink { } - -/// A link implementation that connects to the network. -pub struct NetworkLink> { - /// The chain-sync handle - pub(crate) sync: Weak>>, - /// Network context. - pub(crate) context: Weak, -} - -impl> NetworkLink { - /// Execute closure with locked ChainSync. - fn with_sync, &mut Context)>(&self, closure: F) { - if let (Some(sync), Some(service)) = (self.sync.upgrade(), self.context.upgrade()) { - service.execute_in_context(move |protocol| { - let mut sync = sync.write(); - closure(&mut *sync, protocol) - }); - } - } -} - -impl> Link for NetworkLink { - fn block_imported(&self, hash: &B::Hash, number: NumberFor) { - self.with_sync(|sync, _| sync.block_imported(&hash, number)) - } - - fn maintain_sync(&self) { - self.with_sync(|sync, protocol| sync.maintain_sync(protocol)) - } - - fn useless_peer(&self, who: NodeIndex, reason: &str) { - trace!(target:"sync", "Useless peer {}, {}", who, reason); - self.with_sync(|_, protocol| protocol.report_peer(who, Severity::Useless(reason))) - } - - fn note_useless_and_restart_sync(&self, who: NodeIndex, reason: &str) { - trace!(target:"sync", "Bad peer {}, {}", who, reason); - self.with_sync(|sync, protocol| { - protocol.report_peer(who, Severity::Useless(reason)); // is this actually malign or just useless? - sync.restart(protocol); - }) - } - - fn restart(&self) { - self.with_sync(|sync, protocol| sync.restart(protocol)) - } -} - -/// Block import successful result. -#[derive(Debug, PartialEq)] -enum BlockImportResult { - /// Imported known block. - ImportedKnown(H, N), - /// Imported unknown block. - ImportedUnknown(H, N), -} - -/// Block import error. -#[derive(Debug, PartialEq)] -enum BlockImportError { - /// Block missed header, can't be imported - IncompleteHeader(Option), - /// Block verification failed, can't be imported - VerificationFailed(Option, String), - /// Block is known to be Bad - BadBlock(Option), - /// Block has an unknown parent - UnknownParent, - /// Other Error. - Error, -} - -/// Import a bunch of blocks. -fn import_many_blocks<'a, B: BlockT, V: Verifier>( - import_handle: &BlockImport, - link: &Link, - qdata: Option<&AsyncImportQueueData>, - blocks: (BlockOrigin, Vec>), - verifier: Arc -) -> bool -{ - let (blocks_origin, blocks) = blocks; - let count = blocks.len(); - let mut imported = 0; - - let blocks_range = match ( - blocks.first().and_then(|b| b.block.header.as_ref().map(|h| h.number())), - blocks.last().and_then(|b| b.block.header.as_ref().map(|h| h.number())), - ) { - (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), - (Some(first), Some(_)) => format!(" ({})", first), - _ => Default::default(), - }; - trace!(target:"sync", "Starting import of {} blocks {}", count, blocks_range); - - // Blocks in the response/drain should be in ascending order. - for block in blocks { - let import_result = import_single_block( - import_handle, - blocks_origin.clone(), - block, - verifier.clone(), - ); - let is_import_failed = import_result.is_err(); - imported += process_import_result(link, import_result); - if is_import_failed { - qdata.map(|qdata| *qdata.best_importing_number.write() = Zero::zero()); - return true; - } - - if qdata.map(|qdata| qdata.is_stopping.load(Ordering::SeqCst)).unwrap_or_default() { - return false; - } - } - - trace!(target: "sync", "Imported {} of {}", imported, count); - link.maintain_sync(); - true -} - -/// Single block import function. -fn import_single_block>( - import_handle: &BlockImport, - block_origin: BlockOrigin, - block: BlockData, - verifier: Arc -) -> Result::Header as HeaderT>::Number>, BlockImportError> -{ - let peer = block.origin; - let block = block.block; - - let (header, justification) = match (block.header, block.justification) { - (Some(header), justification) => (header, justification), - (None, _) => { - if let Some(peer) = peer { - debug!(target: "sync", "Header {} was not provided by {} ", block.hash, peer); - } else { - debug!(target: "sync", "Header {} was not provided ", block.hash); - } - return Err(BlockImportError::IncompleteHeader(peer)) //TODO: use persistent ID - }, - }; - - let number = header.number().clone(); - let hash = header.hash(); - let parent = header.parent_hash().clone(); - let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body) - .map_err(|msg| { - if let Some(peer) = peer { - trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg); - } else { - trace!(target: "sync", "Verifying {}({}) failed: {}", number, hash, msg); - } - BlockImportError::VerificationFailed(peer, msg) - })?; - - match import_handle.import_block(import_block, new_authorities) { - Ok(ImportResult::AlreadyInChain) => { - trace!(target: "sync", "Block already in chain {}: {:?}", number, hash); - Ok(BlockImportResult::ImportedKnown(hash, number)) - }, - Ok(ImportResult::AlreadyQueued) => { - trace!(target: "sync", "Block already queued {}: {:?}", number, hash); - Ok(BlockImportResult::ImportedKnown(hash, number)) - }, - Ok(ImportResult::Queued) => { - trace!(target: "sync", "Block queued {}: {:?}", number, hash); - Ok(BlockImportResult::ImportedUnknown(hash, number)) - }, - Ok(ImportResult::UnknownParent) => { - debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); - Err(BlockImportError::UnknownParent) - }, - Ok(ImportResult::KnownBad) => { - debug!(target: "sync", "Peer gave us a bad block {}: {:?}", number, hash); - Err(BlockImportError::BadBlock(peer)) //TODO: use persistent ID - } - Err(e) => { - debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e); - Err(BlockImportError::Error) - } - } -} - -/// Process single block import result. -fn process_import_result( - link: &Link, - result: Result::Header as HeaderT>::Number>, BlockImportError> -) -> usize -{ - match result { - Ok(BlockImportResult::ImportedKnown(hash, number)) => { - link.block_imported(&hash, number); - 1 - }, - Ok(BlockImportResult::ImportedUnknown(hash, number)) => { - link.block_imported(&hash, number); - 1 - }, - Err(BlockImportError::IncompleteHeader(who)) => { - if let Some(peer) = who { - link.useless_peer(peer, "Sent block with incomplete header to import"); - } - 0 - }, - Err(BlockImportError::VerificationFailed(who, e)) => { - if let Some(peer) = who { - link.useless_peer(peer, &format!("Verification failed: {}", e)); - } - 0 - }, - Err(BlockImportError::BadBlock(who)) => { - if let Some(peer) = who { - link.note_useless_and_restart_sync(peer, "Sent us a bad block"); - } - 0 - }, - Err(BlockImportError::UnknownParent) | Err(BlockImportError::Error) => { - link.restart(); - 0 - }, - } -} - - -#[cfg(any(test, feature = "test-helpers"))] -struct ImportCB(RefCell>) -> bool>>>); - -#[cfg(any(test, feature = "test-helpers"))] -impl ImportCB { - fn new() -> Self { - ImportCB(RefCell::new(None)) - } - fn set(&self, cb: Box) - where F: 'static + Fn(BlockOrigin, Vec>) -> bool - { - *self.0.borrow_mut() = Some(cb); - } - fn call(&self, origin: BlockOrigin, data: Vec>) -> bool { - let b = self.0.borrow(); - b.as_ref().expect("The Callback has been set before. qed.")(origin, data) - } -} - -#[cfg(any(test, feature = "test-helpers"))] -unsafe impl Send for ImportCB {} -#[cfg(any(test, feature = "test-helpers"))] -unsafe impl Sync for ImportCB {} - - -#[cfg(any(test, feature = "test-helpers"))] -/// A Verifier that accepts all blocks and passes them on with the configured -/// finality to be imported. -pub struct PassThroughVerifier(pub bool); - -#[cfg(any(test, feature = "test-helpers"))] -/// This Verifiyer accepts all data as valid -impl Verifier for PassThroughVerifier { - fn verify( - &self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - body: Option> - ) -> Result<(ImportBlock, Option>), String> { - Ok((ImportBlock { - origin, - header, - body, - finalized: self.0, - justification, - post_digests: vec![], - auxiliary: Vec::new(), - }, None)) - } -} - -/// Blocks import queue that is importing blocks in the same thread. -/// The boolean value indicates whether blocks should be imported without instant finality. -#[cfg(any(test, feature = "test-helpers"))] -pub struct SyncImportQueue> { - verifier: Arc, - link: ImportCB, - block_import: SharedBlockImport, -} - -#[cfg(any(test, feature = "test-helpers"))] -impl> SyncImportQueue { - /// Create a new SyncImportQueue wrapping the given Verifier and block import - /// handle. - pub fn new(verifier: Arc, block_import: SharedBlockImport) -> Self { - let queue = SyncImportQueue { - verifier, - link: ImportCB::new(), - block_import, - }; - - let v = queue.verifier.clone(); - let import_handle = queue.block_import.clone(); - queue.link.set(Box::new(move |origin, new_blocks| { - let verifier = v.clone(); - import_many_blocks( - &*import_handle, - &NoopLink, - None, - (origin, new_blocks), - verifier, - ) - })); - - queue - } -} - -#[cfg(any(test, feature = "test-helpers"))] -impl> ImportQueue for SyncImportQueue -{ - fn start>( - &self, - link: L, - ) -> Result<(), Error> { - let v = self.verifier.clone(); - let import_handle = self.block_import.clone(); - self.link.set(Box::new(move |origin, new_blocks| { - let verifier = v.clone(); - import_many_blocks( - &*import_handle, - &link, - None, - (origin, new_blocks), - verifier, - ) - })); - Ok(()) - } - fn clear(&self) { } - - fn stop(&self) { } - - fn status(&self) -> ImportQueueStatus { - ImportQueueStatus { - importing_count: 0, - best_importing_number: Zero::zero(), - } - } - - fn is_importing(&self, _hash: &B::Hash) -> bool { - false - } - - fn import_blocks(&self, origin: BlockOrigin, blocks: Vec>) { - self.link.call(origin, blocks); - } -} - -#[cfg(test)] -pub mod tests { - use client; - use message; - use test_client::{self, TestClient}; - use test_client::runtime::{Block, Hash}; - use runtime_primitives::generic::BlockId; - use std::cell::Cell; - use super::*; - - struct TestLink { - imported: Cell, - maintains: Cell, - disconnects: Cell, - restarts: Cell, - } - - impl TestLink { - fn new() -> TestLink { - TestLink { - imported: Cell::new(0), - maintains: Cell::new(0), - disconnects: Cell::new(0), - restarts: Cell::new(0), - } - } - - fn total(&self) -> usize { - self.imported.get() + self.maintains.get() + self.disconnects.get() + self.restarts.get() - } - } - - impl Link for TestLink { - fn block_imported(&self, _hash: &Hash, _number: NumberFor) { - self.imported.set(self.imported.get() + 1); - } - fn maintain_sync(&self) { - self.maintains.set(self.maintains.get() + 1); - } - fn useless_peer(&self, _: NodeIndex, _: &str) { - self.disconnects.set(self.disconnects.get() + 1); - } - fn note_useless_and_restart_sync(&self, id: NodeIndex, r: &str) { - self.useless_peer(id, r); - self.restart(); - } - fn restart(&self) { - self.restarts.set(self.restarts.get() + 1); - } - } - - fn prepare_good_block() -> (client::Client, Hash, u64, BlockData) { - let client = test_client::new(); - let block = client.new_block().unwrap().bake().unwrap(); - client.import(BlockOrigin::File, block).unwrap(); - - let (hash, number) = (client.block_hash(1).unwrap().unwrap(), 1); - let block = message::BlockData:: { - hash: client.block_hash(1).unwrap().unwrap(), - header: client.header(&BlockId::Number(1)).unwrap(), - body: None, - receipt: None, - message_queue: None, - justification: client.justification(&BlockId::Number(1)).unwrap(), - }; - - (client, hash, number, BlockData { block, origin: Some(0) }) - } - - #[test] - fn import_single_good_block_works() { - let (_, hash, number, block) = prepare_good_block(); - assert_eq!( - import_single_block(&test_client::new(), BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), - Ok(BlockImportResult::ImportedUnknown(hash, number)) - ); - } - - #[test] - fn import_single_good_known_block_is_ignored() { - let (client, hash, number, block) = prepare_good_block(); - assert_eq!( - import_single_block(&client, BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), - Ok(BlockImportResult::ImportedKnown(hash, number)) - ); - } - - #[test] - fn import_single_good_block_without_header_fails() { - let (_, _, _, mut block) = prepare_good_block(); - block.block.header = None; - assert_eq!( - import_single_block(&test_client::new(), BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), - Err(BlockImportError::IncompleteHeader(Some(0))) - ); - } - - #[test] - fn process_import_result_works() { - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Ok(BlockImportResult::ImportedKnown(Default::default(), 0))), 1); - assert_eq!(link.total(), 1); - - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Ok(BlockImportResult::ImportedKnown(Default::default(), 0))), 1); - assert_eq!(link.total(), 1); - assert_eq!(link.imported.get(), 1); - - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Ok(BlockImportResult::ImportedUnknown(Default::default(), 0))), 1); - assert_eq!(link.total(), 1); - assert_eq!(link.imported.get(), 1); - - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Err(BlockImportError::IncompleteHeader(Some(0)))), 0); - assert_eq!(link.total(), 1); - assert_eq!(link.disconnects.get(), 1); - - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Err(BlockImportError::UnknownParent)), 0); - assert_eq!(link.total(), 1); - assert_eq!(link.restarts.get(), 1); - - let link = TestLink::new(); - assert_eq!(process_import_result::(&link, Err(BlockImportError::Error)), 0); - assert_eq!(link.total(), 1); - assert_eq!(link.restarts.get(), 1); - } - - #[test] - fn import_many_blocks_stops_when_stopping() { - let (_, _, _, block) = prepare_good_block(); - let qdata = AsyncImportQueueData::new(); - let verifier = Arc::new(PassThroughVerifier(true)); - qdata.is_stopping.store(true, Ordering::SeqCst); - let client = test_client::new(); - assert!(!import_many_blocks( - &client, - &mut TestLink::new(), - Some(&qdata), - (BlockOrigin::File, vec![block.clone(), block]), - verifier - )); - } - - #[test] - fn async_import_queue_drops() { - // Perform this test multiple times since it exhibits non-deterministic behavior. - for _ in 0..100 { - let verifier = Arc::new(PassThroughVerifier(true)); - let queue = BasicQueue::new(verifier, Arc::new(test_client::new())); - queue.start(TestLink::new()).unwrap(); - drop(queue); - } - } -} diff --git a/core/network/src/io.rs b/core/network/src/io.rs deleted file mode 100644 index 5413d8c74c0b0d6e4bf3b21973889e7ac87b8aae..0000000000000000000000000000000000000000 --- a/core/network/src/io.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use parking_lot::Mutex; -use network_libp2p::{Service, Severity, NodeIndex, PeerId, ProtocolId}; -use std::sync::Arc; - -/// IO interface for the syncing handler. -/// Provides peer connection management and an interface to the blockchain client. -pub trait SyncIo { - /// Report a peer for misbehaviour. - fn report_peer(&mut self, who: NodeIndex, reason: Severity); - /// Send a packet to a peer. - fn send(&mut self, who: NodeIndex, data: Vec); - /// Returns peer identifier string - fn peer_debug_info(&self, who: NodeIndex) -> String { - who.to_string() - } - /// Returns information on p2p session - fn peer_id(&self, who: NodeIndex) -> Option; -} - -/// Wraps the network service. -pub struct NetSyncIo<'s> { - network: &'s Arc>, - protocol: ProtocolId, -} - -impl<'s> NetSyncIo<'s> { - /// Creates a new instance. - pub fn new(network: &'s Arc>, protocol: ProtocolId) -> NetSyncIo<'s> { - NetSyncIo { - network, - protocol, - } - } -} - -impl<'s> SyncIo for NetSyncIo<'s> { - fn report_peer(&mut self, who: NodeIndex, reason: Severity) { - info!("Purposefully dropping {} ; reason: {:?}", who, reason); - match reason { - Severity::Bad(_) => self.network.lock().ban_node(who), - Severity::Useless(_) => self.network.lock().drop_node(who), - Severity::Timeout => self.network.lock().drop_node(who), - } - } - - fn send(&mut self, who: NodeIndex, data: Vec) { - self.network.lock().send_custom_message(who, self.protocol, data) - } - - fn peer_id(&self, who: NodeIndex) -> Option { - let net = self.network.lock(); - net.peer_id_of_node(who).cloned() - } - - fn peer_debug_info(&self, who: NodeIndex) -> String { - let net = self.network.lock(); - if let (Some(peer_id), Some(addr)) = (net.peer_id_of_node(who), net.node_endpoint(who)) { - format!("{:?} through {:?}", peer_id, addr) - } else { - "unknown".to_string() - } - } -} diff --git a/core/network/src/lib.rs b/core/network/src/lib.rs index b6ba3f78836e0144a138a4f2ecd72e8a72a70351..de4597d597a8e1a73b571375d361d2fd6879b27d 100644 --- a/core/network/src/lib.rs +++ b/core/network/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,42 +20,15 @@ //! Substrate-specific P2P networking: synchronizing blocks, propagating BFT messages. //! Allows attachment of an optional subprotocol for chain-specific requests. -extern crate linked_hash_map; -extern crate parking_lot; -extern crate substrate_primitives as primitives; -extern crate substrate_client as client; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_network_libp2p as network_libp2p; -extern crate substrate_consensus_common as consensus; -extern crate parity_codec as codec; -extern crate futures; -extern crate rustc_hex; -extern crate rand; -extern crate tokio; -#[macro_use] extern crate log; -#[macro_use] extern crate bitflags; -#[macro_use] extern crate error_chain; -#[macro_use] extern crate parity_codec_derive; - -#[cfg(test)] -extern crate env_logger; - -#[cfg(any(test, feature = "test-helpers"))] -extern crate substrate_keyring as keyring; - -#[cfg(any(test, feature = "test-helpers"))] -extern crate substrate_test_client as test_client; - mod service; mod sync; #[macro_use] mod protocol; -mod io; mod chain; mod blocks; mod on_demand; +mod util; pub mod config; -pub mod import_queue; pub mod consensus_gossip; pub mod error; pub mod message; @@ -65,14 +38,15 @@ pub mod specialization; pub mod test; pub use chain::Client as ClientHandle; -pub use service::{Service, FetchFuture, TransactionPool, ManageNetwork, SyncProvider, ExHashT}; +pub use service::{Service, FetchFuture, TransactionPool, ManageNetwork, NetworkMsg, SyncProvider, ExHashT}; pub use protocol::{ProtocolStatus, PeerInfo, Context}; pub use sync::{Status as SyncStatus, SyncState}; pub use network_libp2p::{ NodeIndex, ProtocolId, Severity, Protocol, Multiaddr, - obtain_private_key, multiaddr, + NetworkState, NetworkStatePeer, NetworkStateNotConnectedPeer, NetworkStatePeerEndpoint, + obtain_private_key, build_multiaddr, PeerId, PublicKey }; -pub use message::{generic as generic_message, RequestId, Status as StatusMessage}; +pub use message::{generic as generic_message, RequestId, Status as StatusMessage, ConsensusEngineId}; pub use error::Error; pub use on_demand::{OnDemand, OnDemandService, RemoteResponse}; #[doc(hidden)] diff --git a/core/network/src/message.rs b/core/network/src/message.rs index e422c77418afbfa8f76c0e970774d519ed487795..355935b10ece69827df608dc5b00b4574b7c8237 100644 --- a/core/network/src/message.rs +++ b/core/network/src/message.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,9 @@ //! Network packet message types. These get serialized and put into the lower level protocol payload. +use bitflags::bitflags; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; -use codec::{Encode, Decode, Input, Output}; +use parity_codec::{Encode, Decode, Input, Output}; pub use self::generic::{ BlockAnnounce, RemoteCallRequest, RemoteReadRequest, RemoteHeaderRequest, RemoteHeaderResponse, @@ -28,6 +29,9 @@ pub use self::generic::{ /// A unique ID of a request. pub type RequestId = u64; +/// Consensus engine unique ID. +pub type ConsensusEngineId = [u8; 4]; + /// Type alias for using the message type using block type parameters. pub type Message = generic::Message< ::Header, @@ -48,7 +52,6 @@ pub type BlockRequest = generic::BlockRequest< <::Header as HeaderT>::Number, >; - /// Type alias for using the BlockData type using block type parameters. pub type BlockData = generic::BlockData< ::Header, @@ -124,14 +127,22 @@ pub struct RemoteReadResponse { /// Generic types. pub mod generic { + use parity_codec::{Encode, Decode}; + use network_libp2p::{CustomMessage, CustomMessageId}; use runtime_primitives::Justification; - use config::Roles; + use crate::config::Roles; use super::{ BlockAttributes, RemoteCallResponse, RemoteReadResponse, - RequestId, Transactions, Direction + RequestId, Transactions, Direction, ConsensusEngineId, }; - /// Consensus is opaque to us - pub type ConsensusMessage = Vec; + /// Consensus is mostly opaque to us + #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] + pub struct ConsensusMessage { + /// Identifies consensus engine. + pub engine_id: ConsensusEngineId, + /// Message payload. + pub data: Vec, + } /// Block data sent in the response. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -173,7 +184,7 @@ pub mod generic { /// Transactions. Transactions(Transactions), /// Consensus protocol message. - Consensus(Hash, ConsensusMessage, bool), // topic, opaque Vec, broadcast + Consensus(ConsensusMessage), /// Remote method call request. RemoteCallRequest(RemoteCallRequest), /// Remote method call response. @@ -195,11 +206,45 @@ pub mod generic { ChainSpecific(Vec), } + impl CustomMessage for Message + where Self: Decode + Encode + { + fn into_bytes(self) -> Vec { + self.encode() + } + + fn from_bytes(bytes: &[u8]) -> Result { + Decode::decode(&mut &bytes[..]).ok_or(()) + } + + fn request_id(&self) -> CustomMessageId { + match *self { + Message::Status(_) => CustomMessageId::OneWay, + Message::BlockRequest(ref req) => CustomMessageId::Request(req.id), + Message::BlockResponse(ref resp) => CustomMessageId::Response(resp.id), + Message::BlockAnnounce(_) => CustomMessageId::OneWay, + Message::Transactions(_) => CustomMessageId::OneWay, + Message::Consensus(_) => CustomMessageId::OneWay, + Message::RemoteCallRequest(ref req) => CustomMessageId::Request(req.id), + Message::RemoteCallResponse(ref resp) => CustomMessageId::Response(resp.id), + Message::RemoteReadRequest(ref req) => CustomMessageId::Request(req.id), + Message::RemoteReadResponse(ref resp) => CustomMessageId::Response(resp.id), + Message::RemoteHeaderRequest(ref req) => CustomMessageId::Request(req.id), + Message::RemoteHeaderResponse(ref resp) => CustomMessageId::Response(resp.id), + Message::RemoteChangesRequest(ref req) => CustomMessageId::Request(req.id), + Message::RemoteChangesResponse(ref resp) => CustomMessageId::Response(resp.id), + Message::ChainSpecific(_) => CustomMessageId::OneWay, + } + } + } + /// Status sent on connection. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct Status { /// Protocol version. pub version: u32, + /// Minimum supported version. + pub min_supported_version: u32, /// Supported roles. pub roles: Roles, /// Best block number. diff --git a/core/network/src/on_demand.rs b/core/network/src/on_demand.rs index 59a5333a47802fe737769fb1903abbf8f6469fd5..d012a1ef4d839900b238d2f8e2fb431ae93a1736 100644 --- a/core/network/src/on_demand.rs +++ b/core/network/src/on_demand.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,21 +17,21 @@ //! On-demand requests service. use std::collections::{HashMap, VecDeque}; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use std::time::{Instant, Duration}; +use log::trace; use futures::{Async, Future, Poll}; -use futures::sync::oneshot::{channel, Receiver, Sender}; +use futures::sync::oneshot::{channel, Receiver, Sender as OneShotSender}; use linked_hash_map::LinkedHashMap; use linked_hash_map::Entry; use parking_lot::Mutex; -use client::{self, error::{Error as ClientError, ErrorKind as ClientErrorKind}}; +use client::{error::{Error as ClientError, ErrorKind as ClientErrorKind}}; use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof}; -use io::SyncIo; -use message; +use crate::message; use network_libp2p::{Severity, NodeIndex}; -use config::Roles; -use service; +use crate::config::Roles; +use crate::service::{NetworkChan, NetworkMsg}; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; /// Remote request timeout. @@ -51,35 +51,34 @@ pub trait OnDemandService: Send + Sync { fn on_disconnect(&self, peer: NodeIndex); /// Maintain peers requests. - fn maintain_peers(&self, io: &mut SyncIo); + fn maintain_peers(&self); /// When header response is received from remote node. fn on_remote_header_response( &self, - io: &mut SyncIo, peer: NodeIndex, response: message::RemoteHeaderResponse ); /// When read response is received from remote node. - fn on_remote_read_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteReadResponse); + fn on_remote_read_response(&self, peer: NodeIndex, response: message::RemoteReadResponse); /// When call response is received from remote node. - fn on_remote_call_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteCallResponse); + fn on_remote_call_response(&self, peer: NodeIndex, response: message::RemoteCallResponse); /// When changes response is received from remote node. fn on_remote_changes_response( &self, - io: &mut SyncIo, peer: NodeIndex, response: message::RemoteChangesResponse, Block::Hash> ); } /// On-demand requests service. Dispatches requests to appropriate peers. -pub struct OnDemand> { - core: Mutex>, +pub struct OnDemand { + core: Mutex>, checker: Arc>, + network_sender: Mutex>>, } /// On-demand remote call response. @@ -88,8 +87,7 @@ pub struct RemoteResponse { } #[derive(Default)] -struct OnDemandCore> { - service: Weak, +struct OnDemandCore { next_request_id: u64, pending_requests: VecDeque>, active_peers: LinkedHashMap>, @@ -105,10 +103,10 @@ struct Request { } enum RequestData { - RemoteHeader(RemoteHeaderRequest, Sender>), - RemoteRead(RemoteReadRequest, Sender>, ClientError>>), - RemoteCall(RemoteCallRequest, Sender>), - RemoteChanges(RemoteChangesRequest, Sender, u32)>, ClientError>>), + RemoteHeader(RemoteHeaderRequest, OneShotSender>), + RemoteRead(RemoteReadRequest, OneShotSender>, ClientError>>), + RemoteCall(RemoteCallRequest, OneShotSender, ClientError>>), + RemoteChanges(RemoteChangesRequest, OneShotSender, u32)>, ClientError>>), } enum Accept { @@ -132,16 +130,15 @@ impl Future for RemoteResponse { } } -impl OnDemand where - E: service::ExecuteInContext, +impl OnDemand where B::Header: HeaderT, { /// Creates new on-demand service. pub fn new(checker: Arc>) -> Self { OnDemand { checker, + network_sender: Mutex::new(None), core: Mutex::new(OnDemandCore { - service: Weak::new(), next_request_id: 0, pending_requests: VecDeque::new(), active_peers: LinkedHashMap::new(), @@ -152,25 +149,34 @@ impl OnDemand where } /// Sets weak reference to network service. - pub fn set_service_link(&self, service: Weak) { - self.core.lock().service = service; + pub fn set_network_sender(&self, network_sender: NetworkChan) { + self.network_sender.lock().replace(network_sender); + } + + fn send(&self, msg: NetworkMsg) { + let _ = self.network_sender + .lock() + .as_ref() + .expect("1. OnDemand is passed a network sender upon initialization of the service, 2. it should bet set by now") + .send(msg); } /// Schedule && dispatch all scheduled requests. fn schedule_request(&self, retry_count: Option, data: RequestData, result: R) -> R { let mut core = self.core.lock(); core.insert(retry_count.unwrap_or(RETRY_COUNT), data); - core.dispatch(); + core.dispatch(self); result } /// Try to accept response from given peer. - fn accept_response) -> Accept>(&self, rtype: &str, io: &mut SyncIo, peer: NodeIndex, request_id: u64, try_accept: F) { + fn accept_response) -> Accept>(&self, rtype: &str, peer: NodeIndex, request_id: u64, try_accept: F) { let mut core = self.core.lock(); let request = match core.remove(peer, request_id) { Some(request) => request, None => { - io.report_peer(peer, Severity::Bad(&format!("Invalid remote {} response from peer", rtype))); + let reason = format!("Invalid remote {} response from peer", rtype); + self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); core.remove_peer(peer); return; }, @@ -180,7 +186,8 @@ impl OnDemand where let (retry_count, retry_request_data) = match try_accept(request) { Accept::Ok => (retry_count, None), Accept::CheckFailed(error, retry_request_data) => { - io.report_peer(peer, Severity::Bad(&format!("Failed to check remote {} response from peer: {}", rtype, error))); + let reason = format!("Failed to check remote {} response from peer: {}", rtype, error); + self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); core.remove_peer(peer); if retry_count > 0 { @@ -192,7 +199,8 @@ impl OnDemand where } }, Accept::Unexpected(retry_request_data) => { - io.report_peer(peer, Severity::Bad(&format!("Unexpected response to remote {} from peer", rtype))); + let reason = format!("Unexpected response to remote {} from peer", rtype); + self.send(NetworkMsg::ReportPeer(peer, Severity::Bad(reason))); core.remove_peer(peer); (retry_count, Some(retry_request_data)) @@ -203,47 +211,46 @@ impl OnDemand where core.insert(retry_count, request_data); } - core.dispatch(); + core.dispatch(self); } } -impl OnDemandService for OnDemand where +impl OnDemandService for OnDemand where B: BlockT, - E: service::ExecuteInContext, B::Header: HeaderT, { fn on_connect(&self, peer: NodeIndex, role: Roles, best_number: NumberFor) { - if !role.intersects(Roles::FULL | Roles::AUTHORITY) { // TODO: correct? + if !role.intersects(Roles::FULL | Roles::AUTHORITY) { return; } let mut core = self.core.lock(); core.add_peer(peer, best_number); - core.dispatch(); + core.dispatch(self); } fn on_block_announce(&self, peer: NodeIndex, best_number: NumberFor) { let mut core = self.core.lock(); core.update_peer(peer, best_number); - core.dispatch(); + core.dispatch(self); } fn on_disconnect(&self, peer: NodeIndex) { let mut core = self.core.lock(); core.remove_peer(peer); - core.dispatch(); + core.dispatch(self); } - fn maintain_peers(&self, io: &mut SyncIo) { + fn maintain_peers(&self) { let mut core = self.core.lock(); for bad_peer in core.maintain_peers() { - io.report_peer(bad_peer, Severity::Timeout); + self.send(NetworkMsg::ReportPeer(bad_peer, Severity::Timeout)); } - core.dispatch(); + core.dispatch(self); } - fn on_remote_header_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteHeaderResponse) { - self.accept_response("header", io, peer, response.id, |request| match request.data { + fn on_remote_header_response(&self, peer: NodeIndex, response: message::RemoteHeaderResponse) { + self.accept_response("header", peer, response.id, |request| match request.data { RequestData::RemoteHeader(request, sender) => match self.checker.check_header_proof(&request, response.header, response.proof) { Ok(response) => { // we do not bother if receiver has been dropped already @@ -256,8 +263,8 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_read_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteReadResponse) { - self.accept_response("read", io, peer, response.id, |request| match request.data { + fn on_remote_read_response(&self, peer: NodeIndex, response: message::RemoteReadResponse) { + self.accept_response("read", peer, response.id, |request| match request.data { RequestData::RemoteRead(request, sender) => match self.checker.check_read_proof(&request, response.proof) { Ok(response) => { // we do not bother if receiver has been dropped already @@ -270,8 +277,8 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_call_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteCallResponse) { - self.accept_response("call", io, peer, response.id, |request| match request.data { + fn on_remote_call_response(&self, peer: NodeIndex, response: message::RemoteCallResponse) { + self.accept_response("call", peer, response.id, |request| match request.data { RequestData::RemoteCall(request, sender) => match self.checker.check_execution_proof(&request, response.proof) { Ok(response) => { // we do not bother if receiver has been dropped already @@ -284,8 +291,8 @@ impl OnDemandService for OnDemand where }) } - fn on_remote_changes_response(&self, io: &mut SyncIo, peer: NodeIndex, response: message::RemoteChangesResponse, B::Hash>) { - self.accept_response("changes", io, peer, response.id, |request| match request.data { + fn on_remote_changes_response(&self, peer: NodeIndex, response: message::RemoteChangesResponse, B::Hash>) { + self.accept_response("changes", peer, response.id, |request| match request.data { RequestData::RemoteChanges(request, sender) => match self.checker.check_changes_proof( &request, ChangesProof { max_block: response.max, @@ -305,14 +312,13 @@ impl OnDemandService for OnDemand where } } -impl Fetcher for OnDemand where +impl Fetcher for OnDemand where B: BlockT, - E: service::ExecuteInContext, B::Header: HeaderT, { type RemoteHeaderResult = RemoteResponse; type RemoteReadResult = RemoteResponse>>; - type RemoteCallResult = RemoteResponse; + type RemoteCallResult = RemoteResponse>; type RemoteChangesResult = RemoteResponse, u32)>>; fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult { @@ -340,9 +346,8 @@ impl Fetcher for OnDemand where } } -impl OnDemandCore where +impl OnDemandCore where B: BlockT, - E: service::ExecuteInContext, B::Header: HeaderT, { pub fn add_peer(&mut self, peer: NodeIndex, best_number: NumberFor) { @@ -407,22 +412,26 @@ impl OnDemandCore where } } - pub fn dispatch(&mut self) { - let service = match self.service.upgrade() { - Some(service) => service, - None => return, - }; + pub fn dispatch(&mut self, on_demand: &OnDemand) { + + let mut last_peer = self.idle_peers.back().cloned(); + let mut unhandled_requests = VecDeque::new(); - let last_peer = self.idle_peers.back().cloned(); - while !self.pending_requests.is_empty() { + loop { let peer = match self.idle_peers.pop_front() { Some(peer) => peer, - None => return, + None => break, }; // check if request can (optimistically) be processed by the peer let can_be_processed_by_peer = { - let request = self.pending_requests.front().expect("checked in loop condition; qed"); + let request = match self.pending_requests.front() { + Some(r) => r, + None => { + self.idle_peers.push_front(peer); + break; + }, + }; let peer_best_block = self.best_blocks.get(&peer) .expect("entries are inserted into best_blocks when peer is connected; entries are removed from best_blocks when peer is disconnected; @@ -436,19 +445,24 @@ impl OnDemandCore where // we have enumerated all peers and noone can handle request if Some(peer) == last_peer { - break; + let request = self.pending_requests.pop_front().expect("checked in loop condition; qed"); + unhandled_requests.push_back(request); + last_peer = self.idle_peers.back().cloned(); } continue; } + last_peer = self.idle_peers.back().cloned(); + let mut request = self.pending_requests.pop_front().expect("checked in loop condition; qed"); request.timestamp = Instant::now(); trace!(target: "sync", "Dispatching remote request {} to peer {}", request.id, peer); - - service.execute_in_context(|ctx| ctx.send_message(peer, request.message())); + on_demand.send(NetworkMsg::Outgoing(peer, request.message())); self.active_peers.insert(peer, request); } + + self.pending_requests.append(&mut unhandled_requests); } } @@ -509,30 +523,23 @@ impl RequestData { #[cfg(test)] pub mod tests { - use std::collections::VecDeque; use std::sync::Arc; use std::time::Instant; use futures::Future; - use parking_lot::RwLock; use runtime_primitives::traits::NumberFor; - use client::{self, error::{ErrorKind as ClientErrorKind, Result as ClientResult}}; + use client::{error::{ErrorKind as ClientErrorKind, Result as ClientResult}}; use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof}; - use config::Roles; - use message; - use network_libp2p::NodeIndex; - use service::ExecuteInContext; - use test::TestIo; + use crate::config::Roles; + use crate::message; + use network_libp2p::{NodeIndex, ProtocolId, Severity}; + use crate::service::{network_channel, NetworkPort, NetworkMsg}; use super::{REQUEST_TIMEOUT, OnDemand, OnDemandService}; use test_client::runtime::{changes_trie_config, Block, Header}; pub struct DummyExecutor; struct DummyFetchChecker { ok: bool } - impl ExecuteInContext for DummyExecutor { - fn execute_in_context)>(&self, _closure: F) {} - } - impl FetchChecker for DummyFetchChecker { fn check_header_proof( &self, @@ -553,12 +560,9 @@ pub mod tests { } } - fn check_execution_proof(&self, _: &RemoteCallRequest
, _: Vec>) -> ClientResult { + fn check_execution_proof(&self, _: &RemoteCallRequest
, _: Vec>) -> ClientResult> { match self.ok { - true => Ok(client::CallResult { - return_data: vec![42], - changes: Default::default(), - }), + true => Ok(vec![42]), false => Err(ClientErrorKind::Backend("Test error".into()).into()), } } @@ -571,20 +575,19 @@ pub mod tests { } } - fn dummy(ok: bool) -> (Arc, Arc>) { + fn dummy(ok: bool) -> (Arc, Arc>) { let executor = Arc::new(DummyExecutor); let service = Arc::new(OnDemand::new(Arc::new(DummyFetchChecker { ok }))); - service.set_service_link(Arc::downgrade(&executor)); (executor, service) } - fn total_peers(on_demand: &OnDemand) -> usize { + fn total_peers(on_demand: &OnDemand) -> usize { let core = on_demand.core.lock(); core.idle_peers.len() + core.active_peers.len() } - fn receive_call_response(on_demand: &OnDemand, network: &mut TestIo, peer: NodeIndex, id: message::RequestId) { - on_demand.on_remote_call_response(network, peer, message::RemoteCallResponse { + fn receive_call_response(on_demand: &OnDemand, peer: NodeIndex, id: message::RequestId) { + on_demand.on_remote_call_response(peer, message::RemoteCallResponse { id: id, proof: vec![vec![2]], }); @@ -600,6 +603,21 @@ pub mod tests { } } + fn assert_disconnected_peer(network_port: NetworkPort, expected_severity: Severity) { + let mut disconnect_count = 0; + while let Ok(msg) = network_port.receiver().try_recv() { + match msg { + NetworkMsg::ReportPeer(_, severity) => { + if severity == expected_severity { + disconnect_count = disconnect_count + 1; + } + }, + _ => {}, + } + } + assert_eq!(disconnect_count, 1); + } + #[test] fn knows_about_peers_roles() { let (_, on_demand) = dummy(true); @@ -626,9 +644,8 @@ pub mod tests { #[test] fn disconnects_from_timeouted_peer() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); - + let (network_sender, network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); on_demand.on_connect(1, Roles::FULL, 1000); assert_eq!(vec![0, 1], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); @@ -645,17 +662,17 @@ pub mod tests { assert_eq!(vec![0], on_demand.core.lock().active_peers.keys().cloned().collect::>()); on_demand.core.lock().active_peers[&0].timestamp = Instant::now() - REQUEST_TIMEOUT - REQUEST_TIMEOUT; - on_demand.maintain_peers(&mut network); + on_demand.maintain_peers(); assert!(on_demand.core.lock().idle_peers.is_empty()); assert_eq!(vec![1], on_demand.core.lock().active_peers.keys().cloned().collect::>()); - assert!(network.to_disconnect.contains(&0)); + assert_disconnected_peer(network_port, Severity::Timeout); } #[test] fn disconnects_from_peer_on_response_with_wrong_id() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); on_demand.remote_call(RemoteCallRequest { @@ -665,16 +682,16 @@ pub mod tests { call_data: vec![], retry_count: None, }); - receive_call_response(&*on_demand, &mut network, 0, 1); - assert!(network.to_disconnect.contains(&0)); + receive_call_response(&*on_demand, 0, 1); + assert_disconnected_peer(network_port, Severity::Bad("Invalid remote call response from peer".to_string())); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } #[test] fn disconnects_from_peer_on_incorrect_response() { let (_x, on_demand) = dummy(false); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.remote_call(RemoteCallRequest { block: Default::default(), header: dummy_header(), @@ -684,27 +701,27 @@ pub mod tests { }); on_demand.on_connect(0, Roles::FULL, 1000); - receive_call_response(&*on_demand, &mut network, 0, 0); - assert!(network.to_disconnect.contains(&0)); + receive_call_response(&*on_demand, 0, 0); + assert_disconnected_peer(network_port, Severity::Bad("Failed to check remote call response from peer: Backend error: Test error".to_string())); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } #[test] fn disconnects_from_peer_on_unexpected_response() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); - receive_call_response(&*on_demand, &mut network, 0, 0); - assert!(network.to_disconnect.contains(&0)); + receive_call_response(&*on_demand, 0, 0); + assert_disconnected_peer(network_port, Severity::Bad("Invalid remote call response from peer".to_string())); } #[test] fn disconnects_from_peer_on_wrong_response_type() { let (_x, on_demand) = dummy(false); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); on_demand.remote_call(RemoteCallRequest { @@ -715,11 +732,11 @@ pub mod tests { retry_count: Some(1), }); - on_demand.on_remote_read_response(&mut network, 0, message::RemoteReadResponse { + on_demand.on_remote_read_response(0, message::RemoteReadResponse { id: 0, proof: vec![vec![2]], }); - assert!(network.to_disconnect.contains(&0)); + assert_disconnected_peer(network_port, Severity::Bad("Unexpected response to remote read from peer".to_string())); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); } @@ -729,8 +746,8 @@ pub mod tests { let retry_count = 2; let (_x, on_demand) = dummy(false); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); for i in 0..retry_count+1 { on_demand.on_connect(i, Roles::FULL, 1000); } @@ -756,7 +773,7 @@ pub mod tests { for i in 0..retry_count+1 { let mut current = current.lock(); *current = *current + 1; - receive_call_response(&*on_demand, &mut network, i, i as u64); + receive_call_response(&*on_demand, i, i as u64); } let mut finished_at = finished_at.lock(); @@ -769,8 +786,8 @@ pub mod tests { #[test] fn receives_remote_call_response() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); let response = on_demand.remote_call(RemoteCallRequest { @@ -782,18 +799,18 @@ pub mod tests { }); let thread = ::std::thread::spawn(move || { let result = response.wait().unwrap(); - assert_eq!(result.return_data, vec![42]); + assert_eq!(result, vec![42]); }); - receive_call_response(&*on_demand, &mut network, 0, 0); + receive_call_response(&*on_demand, 0, 0); thread.join().unwrap(); } #[test] fn receives_remote_read_response() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); let response = on_demand.remote_read(RemoteReadRequest { @@ -807,7 +824,7 @@ pub mod tests { assert_eq!(result, Some(vec![42])); }); - on_demand.on_remote_read_response(&mut network, 0, message::RemoteReadResponse { + on_demand.on_remote_read_response(0, message::RemoteReadResponse { id: 0, proof: vec![vec![2]], }); @@ -817,8 +834,8 @@ pub mod tests { #[test] fn receives_remote_header_response() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); let response = on_demand.remote_header(RemoteHeaderRequest { @@ -835,7 +852,7 @@ pub mod tests { ); }); - on_demand.on_remote_header_response(&mut network, 0, message::RemoteHeaderResponse { + on_demand.on_remote_header_response(0, message::RemoteHeaderResponse { id: 0, header: Some(Header { parent_hash: Default::default(), @@ -852,8 +869,8 @@ pub mod tests { #[test] fn receives_remote_changes_response() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(0, Roles::FULL, 1000); let response = on_demand.remote_changes(RemoteChangesRequest { @@ -870,7 +887,7 @@ pub mod tests { assert_eq!(result, vec![(100, 2)]); }); - on_demand.on_remote_changes_response(&mut network, 0, message::RemoteChangesResponse { + on_demand.on_remote_changes_response(0, message::RemoteChangesResponse { id: 0, max: 1000, proof: vec![vec![2]], @@ -883,8 +900,8 @@ pub mod tests { #[test] fn does_not_sends_request_to_peer_who_has_no_required_block() { let (_x, on_demand) = dummy(true); - let queue = RwLock::new(VecDeque::new()); - let mut network = TestIo::new(&queue, None); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); on_demand.on_connect(1, Roles::FULL, 100); @@ -919,7 +936,7 @@ pub mod tests { assert!(!on_demand.core.lock().idle_peers.iter().any(|_| true)); assert_eq!(on_demand.core.lock().pending_requests.len(), 1); - on_demand.on_remote_header_response(&mut network, 1, message::RemoteHeaderResponse { + on_demand.on_remote_header_response(1, message::RemoteHeaderResponse { id: 0, header: Some(dummy_header()), proof: vec![], @@ -928,4 +945,55 @@ pub mod tests { assert!(!on_demand.core.lock().idle_peers.iter().any(|_| true)); assert_eq!(on_demand.core.lock().pending_requests.len(), 0); } + + #[test] + fn does_not_loop_forever_after_dispatching_request_to_last_peer() { + // this test is a regression for a bug where the dispatch function would + // loop forever after dispatching a request to the last peer, since the + // last peer was not updated + let (_x, on_demand) = dummy(true); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); + + on_demand.remote_header(RemoteHeaderRequest { + cht_root: Default::default(), + block: 250, + retry_count: None, + }); + on_demand.remote_header(RemoteHeaderRequest { + cht_root: Default::default(), + block: 250, + retry_count: None, + }); + + on_demand.on_connect(1, Roles::FULL, 200); + on_demand.on_connect(2, Roles::FULL, 200); + on_demand.on_connect(3, Roles::FULL, 250); + + assert_eq!(vec![1, 2], on_demand.core.lock().idle_peers.iter().cloned().collect::>()); + assert_eq!(on_demand.core.lock().pending_requests.len(), 1); + } + + #[test] + fn tries_to_send_all_pending_requests() { + let (_x, on_demand) = dummy(true); + let (network_sender, _network_port) = network_channel(ProtocolId::default()); + on_demand.set_network_sender(network_sender.clone()); + + on_demand.remote_header(RemoteHeaderRequest { + cht_root: Default::default(), + block: 300, + retry_count: None, + }); + on_demand.remote_header(RemoteHeaderRequest { + cht_root: Default::default(), + block: 250, + retry_count: None, + }); + + on_demand.on_connect(1, Roles::FULL, 250); + + assert!(on_demand.core.lock().idle_peers.iter().cloned().collect::>().is_empty()); + assert_eq!(on_demand.core.lock().pending_requests.len(), 1); + } } diff --git a/core/network/src/protocol.rs b/core/network/src/protocol.rs index 60133b25c144e0bfa5b4083ea302116e607729b8..9636d1bb14ff48f823fc27c6d1a74ac4b5742b1c 100644 --- a/core/network/src/protocol.rs +++ b/core/network/src/protocol.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,35 +14,45 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::collections::{HashMap, HashSet, BTreeMap}; -use std::{mem, cmp}; -use std::sync::Arc; -use std::time; +use crossbeam_channel::{self as channel, Receiver, Sender, select}; +use futures::sync::mpsc; +use parking_lot::Mutex; +use network_libp2p::{NodeIndex, PeerId, Severity}; +use primitives::storage::StorageKey; +use runtime_primitives::generic::BlockId; +use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, NumberFor, Zero}; +use consensus::import_queue::ImportQueue; +use crate::message::{self, Message, ConsensusEngineId}; +use crate::message::generic::{Message as GenericMessage, ConsensusMessage}; +use crate::consensus_gossip::ConsensusGossip; +use crate::on_demand::OnDemandService; +use crate::specialization::NetworkSpecialization; +use crate::sync::{ChainSync, Status as SyncStatus, SyncState}; +use crate::service::{NetworkChan, NetworkMsg, TransactionPool, ExHashT}; +use crate::config::{ProtocolConfig, Roles}; use parking_lot::RwLock; use rustc_hex::ToHex; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As, Zero}; -use runtime_primitives::generic::BlockId; -use network_libp2p::{NodeIndex, Severity}; -use codec::{Encode, Decode}; - -use message::{self, Message}; -use message::generic::Message as GenericMessage; -use consensus_gossip::ConsensusGossip; -use specialization::NetworkSpecialization; -use sync::{ChainSync, Status as SyncStatus, SyncState}; -use service::{TransactionPool, ExHashT}; -use import_queue::ImportQueue; -use config::{ProtocolConfig, Roles}; -use chain::Client; +use std::collections::{BTreeMap, HashMap}; +use std::sync::Arc; +use std::sync::atomic::AtomicBool; +use std::{cmp, num::NonZeroUsize, thread, time}; +use log::{trace, debug, warn}; +use crate::chain::Client; use client::light::fetcher::ChangesProof; -use on_demand::OnDemandService; -use io::SyncIo; -use error; +use crate::{error, util::LruHashSet}; const REQUEST_TIMEOUT_SEC: u64 = 40; +/// Interval at which we perform time based maintenance +const TICK_TIMEOUT: time::Duration = time::Duration::from_millis(1100); +/// Interval at which we propagate exstrinsics; +const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900); +/// Interval at which we send status updates on the SyncProvider status stream. +const STATUS_INTERVAL: time::Duration = time::Duration::from_millis(5000); /// Current protocol version. -pub (crate) const CURRENT_VERSION: u32 = 1; +pub(crate) const CURRENT_VERSION: u32 = 2; +/// Lowest version we support +const MIN_VERSION: u32 = 2; // Maximum allowed entries in `BlockResponse` const MAX_BLOCK_DATA_RESPONSE: u32 = 128; @@ -53,17 +63,38 @@ const LIGHT_MAXIMAL_BLOCKS_DIFFERENCE: u64 = 8192; // Lock must always be taken in order declared here. pub struct Protocol, H: ExHashT> { + status_sinks: Arc>>>>, + network_chan: NetworkChan, + port: Receiver>, + from_network_port: Receiver>, config: ProtocolConfig, on_demand: Option>>, genesis_hash: B::Hash, - sync: Arc>>, - specialization: RwLock, - consensus_gossip: RwLock>, + sync: ChainSync, + specialization: S, + consensus_gossip: ConsensusGossip, context_data: ContextData, // Connected peers pending Status message. - handshaking_peers: RwLock>, + handshaking_peers: HashMap, + // Connected peers from whom we received a Status message, + // similar to context_data.peers but shared with the SyncProvider. + connected_peers: Arc>>>, transaction_pool: Arc>, } + +/// A peer from whom we have received a Status message. +#[derive(Clone)] +pub struct ConnectedPeer { + pub peer_info: PeerInfo +} + +/// A peer that we are connected to +/// and from whom we have not yet received a Status message. +struct HandshakingPeer { + timestamp: time::Instant, + peer_id: PeerId, +} + /// Syncing status and statistics #[derive(Clone)] pub struct ProtocolStatus { @@ -76,30 +107,26 @@ pub struct ProtocolStatus { } /// Peer information +#[derive(Debug)] struct Peer { - /// Protocol version - protocol_version: u32, - /// Roles - roles: Roles, - /// Peer best block hash - best_hash: B::Hash, - /// Peer best block number - best_number: ::Number, - /// Pending block request if any - block_request: Option>, - /// Request timestamp - request_timestamp: Option, + info: PeerInfo, + /// Current block request, if any. + block_request: Option<(time::Instant, message::BlockRequest)>, + /// Requests we are no longer insterested in. + obsolete_requests: HashMap, /// Holds a set of transactions known to this peer. - known_extrinsics: HashSet, + known_extrinsics: LruHashSet, /// Holds a set of blocks known to this peer. - known_blocks: HashSet, + known_blocks: LruHashSet, /// Request counter, next_request_id: message::RequestId, } /// Info about a peer's known state. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct PeerInfo { + /// Network id. + pub peer_id: PeerId, /// Roles pub roles: Roles, /// Protocol version @@ -113,7 +140,7 @@ pub struct PeerInfo { /// Context for a network-specific handler. pub trait Context { /// Get a reference to the client. - fn client(&self) -> &::chain::Client; + fn client(&self) -> &crate::chain::Client; /// Point out that a peer has been malign or irresponsible or appeared lazy. fn report_peer(&mut self, who: NodeIndex, reason: Severity); @@ -122,57 +149,32 @@ pub trait Context { fn peer_info(&self, peer: NodeIndex) -> Option>; /// Send a message to a peer. - fn send_message(&mut self, who: NodeIndex, data: ::message::Message); + fn send_message(&mut self, who: NodeIndex, data: crate::message::Message); } /// Protocol context. -pub(crate) struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { - io: &'a mut SyncIo, - context_data: &'a ContextData, +struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { + network_chan: &'a NetworkChan, + context_data: &'a mut ContextData, } impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> { - pub(crate) fn new(context_data: &'a ContextData, io: &'a mut SyncIo) -> Self { - ProtocolContext { - io, - context_data, - } - } - - /// Send a message to a peer. - pub fn send_message(&mut self, who: NodeIndex, message: Message) { - send_message(&self.context_data.peers, self.io, who, message) - } - - /// Point out that a peer has been malign or irresponsible or appeared lazy. - pub fn report_peer(&mut self, who: NodeIndex, reason: Severity) { - self.io.report_peer(who, reason); - } - - /// Get peer info. - pub fn peer_info(&self, peer: NodeIndex) -> Option> { - self.context_data.peers.read().get(&peer).map(|p| { - PeerInfo { - roles: p.roles, - protocol_version: p.protocol_version, - best_hash: p.best_hash, - best_number: p.best_number, - } - }) + fn new(context_data: &'a mut ContextData, network_chan: &'a NetworkChan) -> Self { + ProtocolContext { network_chan, context_data } } } impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, H> { fn send_message(&mut self, who: NodeIndex, message: Message) { - ProtocolContext::send_message(self, who, message); + send_message(&mut self.context_data.peers, &self.network_chan, who, message) } fn report_peer(&mut self, who: NodeIndex, reason: Severity) { - ProtocolContext::report_peer(self, who, reason); + self.network_chan.send(NetworkMsg::ReportPeer(who, reason)) } fn peer_info(&self, who: NodeIndex) -> Option> { - ProtocolContext::peer_info(self, who) + self.context_data.peers.get(&who).map(|p| p.info.clone()) } fn client(&self) -> &Client { @@ -181,182 +183,414 @@ impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, } /// Data necessary to create a context. -pub(crate) struct ContextData { +struct ContextData { // All connected peers - peers: RwLock>>, + peers: HashMap>, pub chain: Arc>, } +/// A task, consisting of a user-provided closure, to be executed on the Protocol thread. +pub trait SpecTask> { + fn call_box(self: Box, spec: &mut S, context: &mut Context); +} + +impl, F: FnOnce(&mut S, &mut Context)> SpecTask for F { + fn call_box(self: Box, spec: &mut S, context: &mut Context) { + (*self)(spec, context) + } +} + +/// A task, consisting of a user-provided closure, to be executed on the Protocol thread. +pub trait GossipTask { + fn call_box(self: Box, gossip: &mut ConsensusGossip, context: &mut Context); +} + +impl, &mut Context)> GossipTask for F { + fn call_box(self: Box, gossip: &mut ConsensusGossip, context: &mut Context) { + (*self)(gossip, context) + } +} + +/// Messages sent to Protocol from elsewhere inside the system. +pub enum ProtocolMsg> { + /// A batch of blocks has been processed, with or without errors. + BlocksProcessed(Vec, bool), + /// Tell protocol to restart sync. + RestartSync, + /// Propagate status updates. + Status, + /// Tell protocol to propagate extrinsics. + PropagateExtrinsics, + /// Tell protocol that a block was imported (sent by the import-queue). + BlockImportedSync(B::Hash, NumberFor), + /// Tell protocol to clear all pending justification requests. + ClearJustificationRequests, + /// Tell protocol to request justification for a block. + RequestJustification(B::Hash, NumberFor), + /// Inform protocol whether a justification was successfully imported. + JustificationImportResult(B::Hash, NumberFor, bool), + /// Propagate a block to peers. + AnnounceBlock(B::Hash), + /// A block has been imported (sent by the client). + BlockImported(B::Hash, B::Header), + /// A block has been finalized (sent by the client). + BlockFinalized(B::Hash, B::Header), + /// Execute a closure with the chain-specific network specialization. + ExecuteWithSpec(Box + Send + 'static>), + /// Execute a closure with the consensus gossip. + ExecuteWithGossip(Box + Send + 'static>), + /// Incoming gossip consensus message. + GossipConsensusMessage(B::Hash, ConsensusEngineId, Vec), + /// Tell protocol to abort sync (does not stop protocol). + /// Only used in tests. + #[cfg(any(test, feature = "test-helpers"))] + Abort, + /// Tell protocol to abort sync and stop. + Stop, + /// Tell protocol to perform regular maintenance. + Tick, +} + +/// Messages sent to Protocol from Network-libp2p. +pub enum FromNetworkMsg { + /// A peer connected, with debug info. + PeerConnected(PeerId, NodeIndex, String), + /// A peer disconnected, with debug info. + PeerDisconnected(NodeIndex, String), + /// A custom message from another peer. + CustomMessage(NodeIndex, Message), + /// Let protocol know a peer is currenlty clogged. + PeerClogged(NodeIndex, Option>), +} + +enum Incoming> { + FromNetwork(FromNetworkMsg), + FromClient(ProtocolMsg) +} + impl, H: ExHashT> Protocol { /// Create a new instance. - pub fn new>( + pub fn new( + status_sinks: Arc>>>>, + is_offline: Arc, + is_major_syncing: Arc, + connected_peers: Arc>>>, + network_chan: NetworkChan, config: ProtocolConfig, chain: Arc>, - import_queue: Arc, + import_queue: Box>, on_demand: Option>>, transaction_pool: Arc>, specialization: S, - ) -> error::Result { + ) -> error::Result<(Sender>, Sender>)> { + let (protocol_sender, port) = channel::unbounded(); + let (from_network_sender, from_network_port) = channel::bounded(4); let info = chain.info()?; - let sync = ChainSync::new(config.roles, &info, import_queue); - let protocol = Protocol { - config: config, - context_data: ContextData { - peers: RwLock::new(HashMap::new()), - chain, + let sync = ChainSync::new(is_offline, is_major_syncing, config.roles, &info, import_queue); + let _ = thread::Builder::new() + .name("Protocol".into()) + .spawn(move || { + let mut protocol = Protocol { + status_sinks, + network_chan, + from_network_port, + port, + config: config, + context_data: ContextData { + peers: HashMap::new(), + chain, + }, + on_demand, + genesis_hash: info.chain.genesis_hash, + sync, + specialization: specialization, + consensus_gossip: ConsensusGossip::new(), + handshaking_peers: HashMap::new(), + connected_peers, + transaction_pool: transaction_pool, + }; + let tick_timeout = channel::tick(TICK_TIMEOUT); + let propagate_timeout = channel::tick(PROPAGATE_TIMEOUT); + let status_interval = channel::tick(STATUS_INTERVAL); + while protocol.run(&tick_timeout, &propagate_timeout, &status_interval) { + // Running until all senders have been dropped... + } + }) + .expect("Protocol thread spawning failed"); + Ok((protocol_sender, from_network_sender)) + } + + fn run( + &mut self, + tick_timeout: &Receiver, + propagate_timeout: &Receiver, + status_interval: &Receiver, + ) -> bool { + let msg = select! { + recv(self.port) -> event => { + match event { + Ok(msg) => Incoming::FromClient(msg), + // Our sender has been dropped, quit. + Err(_) => { + Incoming::FromClient(ProtocolMsg::Stop) + }, + } + }, + recv(self.from_network_port) -> event => { + match event { + Ok(msg) => Incoming::FromNetwork(msg), + // Our sender has been dropped, quit. + Err(_) => { + Incoming::FromClient(ProtocolMsg::Stop) + }, + } + }, + recv(tick_timeout) -> _ => { + Incoming::FromClient(ProtocolMsg::Tick) + }, + recv(propagate_timeout) -> _ => { + Incoming::FromClient(ProtocolMsg::PropagateExtrinsics) + }, + recv(status_interval) -> _ => { + Incoming::FromClient(ProtocolMsg::Status) }, - on_demand, - genesis_hash: info.chain.genesis_hash, - sync: Arc::new(RwLock::new(sync)), - specialization: RwLock::new(specialization), - consensus_gossip: RwLock::new(ConsensusGossip::new()), - handshaking_peers: RwLock::new(HashMap::new()), - transaction_pool: transaction_pool, }; - Ok(protocol) + self.handle_msg(msg) } - pub(crate) fn context_data(&self) -> &ContextData { - &self.context_data + fn handle_msg(&mut self, msg: Incoming) -> bool { + match msg { + Incoming::FromNetwork(msg) => self.handle_network_msg(msg), + Incoming::FromClient(msg) => self.handle_client_msg(msg), + } } - pub(crate) fn sync(&self) -> &Arc>> { - &self.sync + fn handle_client_msg(&mut self, msg: ProtocolMsg) -> bool { + match msg { + ProtocolMsg::Status => self.on_status(), + ProtocolMsg::BlockImported(hash, header) => self.on_block_imported(hash, &header), + ProtocolMsg::BlockFinalized(hash, header) => self.on_block_finalized(hash, &header), + ProtocolMsg::ExecuteWithSpec(task) => { + let mut context = + ProtocolContext::new(&mut self.context_data, &self.network_chan); + task.call_box(&mut self.specialization, &mut context); + }, + ProtocolMsg::ExecuteWithGossip(task) => { + let mut context = + ProtocolContext::new(&mut self.context_data, &self.network_chan); + task.call_box(&mut self.consensus_gossip, &mut context); + } + ProtocolMsg::GossipConsensusMessage(topic, engine_id, message) => { + self.gossip_consensus_message(topic, engine_id, message) + } + ProtocolMsg::BlocksProcessed(hashes, has_error) => { + self.sync.blocks_processed(hashes, has_error); + let mut context = + ProtocolContext::new(&mut self.context_data, &self.network_chan); + self.sync.maintain_sync(&mut context); + }, + ProtocolMsg::RestartSync => { + let mut context = + ProtocolContext::new(&mut self.context_data, &self.network_chan); + self.sync.restart(&mut context); + } + ProtocolMsg::AnnounceBlock(hash) => self.announce_block(hash), + ProtocolMsg::BlockImportedSync(hash, number) => self.sync.block_imported(&hash, number), + ProtocolMsg::ClearJustificationRequests => self.sync.clear_justification_requests(), + ProtocolMsg::RequestJustification(hash, number) => { + let mut context = + ProtocolContext::new(&mut self.context_data, &self.network_chan); + self.sync.request_justification(&hash, number, &mut context); + }, + ProtocolMsg::JustificationImportResult(hash, number, success) => self.sync.justification_import_result(hash, number, success), + ProtocolMsg::PropagateExtrinsics => self.propagate_extrinsics(), + ProtocolMsg::Tick => self.tick(), + #[cfg(any(test, feature = "test-helpers"))] + ProtocolMsg::Abort => self.abort(), + ProtocolMsg::Stop => { + self.stop(); + return false; + }, + } + true } - pub(crate) fn consensus_gossip<'a>(&'a self) -> &'a RwLock> { - &self.consensus_gossip + fn handle_network_msg(&mut self, msg: FromNetworkMsg) -> bool { + match msg { + FromNetworkMsg::PeerDisconnected(who, debug_info) => self.on_peer_disconnected(who, debug_info), + FromNetworkMsg::PeerConnected(peer_id, who, debug_info) => self.on_peer_connected(peer_id, who, debug_info), + FromNetworkMsg::PeerClogged(who, message) => self.on_clogged_peer(who, message), + FromNetworkMsg::CustomMessage(who, message) => { + self.on_custom_message(who, message) + }, + } + true } - /// Returns protocol status - pub fn status(&self) -> ProtocolStatus { - let sync = self.sync.read(); - let peers = self.context_data.peers.read(); - ProtocolStatus { - sync: sync.status(), - num_peers: peers.values().count(), - num_active_peers: peers.values().filter(|p| p.block_request.is_some()).count(), + fn handle_response(&mut self, who: NodeIndex, response: &message::BlockResponse) -> Option> { + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { + if let Some(_) = peer.obsolete_requests.remove(&response.id) { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id,); + return None; + } + // Clear the request. If the response is invalid peer will be disconnected anyway. + let request = peer.block_request.take(); + if request.as_ref().map_or(false, |(_, r)| r.id == response.id) { + return request.map(|(_, r)| r) + } + trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id,); + let severity = Severity::Bad("Unexpected response packet received from peer".to_string()); + self.network_chan.send(NetworkMsg::ReportPeer(who, severity)) } + None } - pub fn handle_packet(&self, io: &mut SyncIo, who: NodeIndex, mut data: &[u8]) { - let message: Message = match Decode::decode(&mut data) { - Some(m) => m, - None => { - trace!(target: "sync", "Invalid packet from {}", who); - io.report_peer(who, Severity::Bad("Peer sent us a packet with invalid format")); - return; - } + /// Propagates protocol statuses. + fn on_status(&mut self) { + let status = ProtocolStatus { + sync: self.sync.status(), + num_peers: self.context_data.peers.values().count(), + num_active_peers: self + .context_data + .peers + .values() + .filter(|p| p.block_request.is_some()) + .count(), }; + self.status_sinks.lock().retain(|sink| sink.unbounded_send(status.clone()).is_ok()); + } + fn on_custom_message(&mut self, who: NodeIndex, message: Message) { match message { - GenericMessage::Status(s) => self.on_status_message(io, who, s), - GenericMessage::BlockRequest(r) => self.on_block_request(io, who, r), + GenericMessage::Status(s) => self.on_status_message(who, s), + GenericMessage::BlockRequest(r) => self.on_block_request(who, r), GenericMessage::BlockResponse(r) => { - let request = { - let mut peers = self.context_data.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&who) { - peer.request_timestamp = None; - match mem::replace(&mut peer.block_request, None) { - Some(r) => r, - None => { - io.report_peer(who, Severity::Bad("Unexpected response packet received from peer")); - return; - } - } - } else { - io.report_peer(who, Severity::Bad("Unexpected packet received from peer")); - return; - } - }; - if request.id != r.id { - trace!(target: "sync", "Ignoring mismatched response packet from {} (expected {} got {})", who, request.id, r.id); - return; + if let Some(request) = self.handle_response(who, &r) { + self.on_block_response(who, request, r); } - self.on_block_response(io, who, request, r); }, - GenericMessage::BlockAnnounce(announce) => self.on_block_announce(io, who, announce), - GenericMessage::Transactions(m) => self.on_extrinsics(io, who, m), - GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(io, who, request), - GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(io, who, response), - GenericMessage::RemoteReadRequest(request) => self.on_remote_read_request(io, who, request), - GenericMessage::RemoteReadResponse(response) => self.on_remote_read_response(io, who, response), - GenericMessage::RemoteHeaderRequest(request) => self.on_remote_header_request(io, who, request), - GenericMessage::RemoteHeaderResponse(response) => self.on_remote_header_response(io, who, response), - GenericMessage::RemoteChangesRequest(request) => self.on_remote_changes_request(io, who, request), - GenericMessage::RemoteChangesResponse(response) => self.on_remote_changes_response(io, who, response), - GenericMessage::Consensus(topic, msg, broadcast) => { - self.consensus_gossip.write().on_incoming(&mut ProtocolContext::new(&self.context_data, io), who, topic, msg, broadcast); - }, - other => self.specialization.write().on_message(&mut ProtocolContext::new(&self.context_data, io), who, &mut Some(other)), + GenericMessage::BlockAnnounce(announce) => self.on_block_announce(who, announce), + GenericMessage::Transactions(m) => self.on_extrinsics(who, m), + GenericMessage::RemoteCallRequest(request) => self.on_remote_call_request(who, request), + GenericMessage::RemoteCallResponse(response) => self.on_remote_call_response(who, response), + GenericMessage::RemoteReadRequest(request) => self.on_remote_read_request(who, request), + GenericMessage::RemoteReadResponse(response) => self.on_remote_read_response(who, response), + GenericMessage::RemoteHeaderRequest(request) => self.on_remote_header_request(who, request), + GenericMessage::RemoteHeaderResponse(response) => self.on_remote_header_response(who, response), + GenericMessage::RemoteChangesRequest(request) => self.on_remote_changes_request(who, request), + GenericMessage::RemoteChangesResponse(response) => self.on_remote_changes_response(who, response), + GenericMessage::Consensus(msg) => { + self.consensus_gossip.on_incoming( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + who, + msg, + ); + } + other => self.specialization.on_message( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + who, + &mut Some(other), + ), } } - pub fn send_message(&self, io: &mut SyncIo, who: NodeIndex, message: Message) { - send_message::(&self.context_data.peers, io, who, message) + fn send_message(&mut self, who: NodeIndex, message: Message) { + send_message::( + &mut self.context_data.peers, + &self.network_chan, + who, + message, + ); } - pub fn gossip_consensus_message(&self, io: &mut SyncIo, topic: B::Hash, message: Vec, broadcast: bool) { - let gossip = self.consensus_gossip(); - self.with_spec(io, move |_s, context|{ - gossip.write().multicast(context, topic, message, broadcast); - }); + fn gossip_consensus_message(&mut self, topic: B::Hash, engine_id: ConsensusEngineId, message: Vec) { + self.consensus_gossip.multicast( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + topic, + ConsensusMessage{ data: message, engine_id }, + ); } /// Called when a new peer is connected - pub fn on_peer_connected(&self, io: &mut SyncIo, who: NodeIndex) { - trace!(target: "sync", "Connected {}: {}", who, io.peer_debug_info(who)); - self.handshaking_peers.write().insert(who, time::Instant::now()); - self.send_status(io, who); + fn on_peer_connected(&mut self, peer_id: PeerId, who: NodeIndex, debug_info: String) { + trace!(target: "sync", "Connecting {}: {}", who, debug_info); + self.handshaking_peers.insert(who, HandshakingPeer { timestamp: time::Instant::now(), peer_id }); + self.send_status(who); } /// Called by peer when it is disconnecting - pub fn on_peer_disconnected(&self, io: &mut SyncIo, peer: NodeIndex) { - trace!(target: "sync", "Disconnecting {}: {}", peer, io.peer_debug_info(peer)); - - + fn on_peer_disconnected(&mut self, peer: NodeIndex, debug_info: String) { + trace!(target: "sync", "Disconnecting {}: {}", peer, debug_info); // lock all the the peer lists so that add/remove peer events are in order - let mut sync = self.sync.write(); - let mut spec = self.specialization.write(); - let removed = { - let mut peers = self.context_data.peers.write(); - let mut handshaking_peers = self.handshaking_peers.write(); - handshaking_peers.remove(&peer); - peers.remove(&peer).is_some() + self.handshaking_peers.remove(&peer); + self.connected_peers.write().remove(&peer); + self.context_data.peers.remove(&peer).is_some() }; if removed { - let mut context = ProtocolContext::new(&self.context_data, io); - self.consensus_gossip.write().peer_disconnected(&mut context, peer); - sync.peer_disconnected(&mut context, peer); - spec.on_disconnect(&mut context, peer); + let mut context = ProtocolContext::new(&mut self.context_data, &self.network_chan); + self.consensus_gossip.peer_disconnected(&mut context, peer); + self.sync.peer_disconnected(&mut context, peer); + self.specialization.on_disconnect(&mut context, peer); self.on_demand.as_ref().map(|s| s.on_disconnect(peer)); } } - fn on_block_request(&self, io: &mut SyncIo, peer: NodeIndex, request: message::BlockRequest) { - trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", request.id, peer, request.from, request.to, request.max); + /// Called as a back-pressure mechanism if the networking detects that the peer cannot process + /// our messaging rate fast enough. + pub fn on_clogged_peer(&self, who: NodeIndex, _msg: Option>) { + // We don't do anything but print some diagnostics for now. + if let Some(peer) = self.context_data.peers.get(&who) { + debug!(target: "sync", "Clogged peer {} (protocol_version: {:?}; roles: {:?}; \ + known_extrinsics: {:?}; known_blocks: {:?}; best_hash: {:?}; best_number: {:?})", + who, peer.info.protocol_version, peer.info.roles, peer.known_extrinsics, peer.known_blocks, + peer.info.best_hash, peer.info.best_number); + } else { + debug!(target: "sync", "Peer clogged before being properly connected"); + } + } + + fn on_block_request(&mut self, peer: NodeIndex, request: message::BlockRequest) { + trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", + request.id, + peer, + request.from, + request.to, + request.max); let mut blocks = Vec::new(); let mut id = match request.from { message::FromBlock::Hash(h) => BlockId::Hash(h), message::FromBlock::Number(n) => BlockId::Number(n), }; let max = cmp::min(request.max.unwrap_or(u32::max_value()), MAX_BLOCK_DATA_RESPONSE) as usize; - // TODO: receipts, etc. let get_header = request.fields.contains(message::BlockAttributes::HEADER); let get_body = request.fields.contains(message::BlockAttributes::BODY); - let get_justification = request.fields.contains(message::BlockAttributes::JUSTIFICATION); + let get_justification = request + .fields + .contains(message::BlockAttributes::JUSTIFICATION); while let Some(header) = self.context_data.chain.header(&id).unwrap_or(None) { if blocks.len() >= max { break; } let number = header.number().clone(); let hash = header.hash(); - let justification = if get_justification { self.context_data.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) } else { None }; + let parent_hash = header.parent_hash().clone(); + let justification = if get_justification { + self.context_data.chain.justification(&BlockId::Hash(hash)).unwrap_or(None) + } else { + None + }; let block_data = message::generic::BlockData { hash: hash, header: if get_header { Some(header) } else { None }, - body: if get_body { self.context_data.chain.body(&BlockId::Hash(hash)).unwrap_or(None) } else { None }, + body: if get_body { + self.context_data + .chain + .body(&BlockId::Hash(hash)) + .unwrap_or(None) + } else { + None + }, receipt: None, message_queue: None, justification, @@ -368,7 +602,7 @@ impl, H: ExHashT> Protocol { if number == As::sa(0) { break; } - id = BlockId::Number(number - As::sa(1)) + id = BlockId::Hash(parent_hash) } } } @@ -377,11 +611,15 @@ impl, H: ExHashT> Protocol { blocks: blocks, }; trace!(target: "sync", "Sending BlockResponse with {} blocks", response.blocks.len()); - self.send_message(io, peer, GenericMessage::BlockResponse(response)) + self.send_message(peer, GenericMessage::BlockResponse(response)) } - fn on_block_response(&self, io: &mut SyncIo, peer: NodeIndex, request: message::BlockRequest, response: message::BlockResponse) { - // TODO: validate response + fn on_block_response( + &mut self, + peer: NodeIndex, + request: message::BlockRequest, + response: message::BlockResponse, + ) { let blocks_range = match ( response.blocks.first().and_then(|b| b.header.as_ref().map(|h| h.number())), response.blocks.last().and_then(|b| b.header.as_ref().map(|h| h.number())), @@ -390,128 +628,165 @@ impl, H: ExHashT> Protocol { (Some(first), Some(_)) => format!(" ({})", first), _ => Default::default(), }; - trace!(target: "sync", "BlockResponse {} from {} with {} blocks{}", + trace!(target: "sync", "BlockResponse {} from {} with {} blocks {}", response.id, peer, response.blocks.len(), blocks_range); - // import_queue.import_blocks also acquires sync.write(); - // Break the cycle by doing these separately from the outside; - let new_blocks = { - let mut sync = self.sync.write(); - sync.on_block_data(&mut ProtocolContext::new(&self.context_data, io), peer, request, response) - }; - - if let Some((origin, new_blocks)) = new_blocks { - let import_queue = self.sync.read().import_queue(); - import_queue.import_blocks(origin, new_blocks); + // TODO [andre]: move this logic to the import queue so that + // justifications are imported asynchronously (#1482) + if request.fields == message::BlockAttributes::JUSTIFICATION { + self.sync.on_block_justification_data( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + peer, + request, + response, + ); + } else { + self.sync.on_block_data(&mut ProtocolContext::new(&mut self.context_data, &self.network_chan), peer, request, response); } - - } /// Perform time based maintenance. - pub fn tick(&self, io: &mut SyncIo) { - self.consensus_gossip.write().collect_garbage(|_| true); - self.maintain_peers(io); - self.on_demand.as_ref().map(|s| s.maintain_peers(io)); + fn tick(&mut self) { + self.consensus_gossip.collect_garbage(); + self.maintain_peers(); + self.sync.tick(&mut ProtocolContext::new(&mut self.context_data, &self.network_chan)); + self.on_demand + .as_ref() + .map(|s| s.maintain_peers()); } - fn maintain_peers(&self, io: &mut SyncIo) { + fn maintain_peers(&mut self) { let tick = time::Instant::now(); let mut aborting = Vec::new(); { - let peers = self.context_data.peers.read(); - let handshaking_peers = self.handshaking_peers.read(); - for (who, timestamp) in peers.iter() - .filter_map(|(id, peer)| peer.request_timestamp.as_ref().map(|r| (id, r))) - .chain(handshaking_peers.iter()) { - if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC { - trace!(target: "sync", "Timeout {}", who); + for (who, peer) in self.context_data.peers.iter() { + if peer.block_request.as_ref().map_or(false, |(t, _)| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { + trace!(target: "sync", "Reqeust timeout {}", who); + aborting.push(*who); + } else if peer.obsolete_requests.values().any(|t| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { + trace!(target: "sync", "Obsolete timeout {}", who); aborting.push(*who); } } + for (who, _) in self.handshaking_peers.iter().filter(|(_, handshaking)| (tick - handshaking.timestamp).as_secs() > REQUEST_TIMEOUT_SEC) { + trace!(target: "sync", "Handshake timeout {}", who); + aborting.push(*who); + } } - self.specialization.write().maintain_peers(&mut ProtocolContext::new(&self.context_data, io)); + self.specialization.maintain_peers(&mut ProtocolContext::new(&mut self.context_data, &self.network_chan)); for p in aborting { - io.report_peer(p, Severity::Timeout); + let _ = self + .network_chan + .send(NetworkMsg::ReportPeer(p, Severity::Timeout)); } } - #[allow(dead_code)] - pub fn peer_info(&self, peer: NodeIndex) -> Option> { - self.context_data.peers.read().get(&peer).map(|p| { - PeerInfo { - roles: p.roles, - protocol_version: p.protocol_version, - best_hash: p.best_hash, - best_number: p.best_number, - } - }) - } - /// Called by peer to report status - fn on_status_message(&self, io: &mut SyncIo, who: NodeIndex, status: message::Status) { + fn on_status_message(&mut self, who: NodeIndex, status: message::Status) { trace!(target: "sync", "New peer {} {:?}", who, status); - { - let mut peers = self.context_data.peers.write(); - let mut handshaking_peers = self.handshaking_peers.write(); - if peers.contains_key(&who) { - debug!(target: "sync", "Unexpected status packet from {}:{}", who, io.peer_debug_info(who)); + if self.context_data.peers.contains_key(&who) { + debug!("Unexpected status packet from {}", who); return; } if status.genesis_hash != self.genesis_hash { - io.report_peer(who, Severity::Bad(&format!("Peer is on different chain (our genesis: {} theirs: {})", self.genesis_hash, status.genesis_hash))); + let reason = format!( + "Peer is on different chain (our genesis: {} theirs: {})", + self.genesis_hash, status.genesis_hash + ); + self.network_chan.send(NetworkMsg::ReportPeer( + who, + Severity::Bad(reason), + )); return; } - if status.version != CURRENT_VERSION { - io.report_peer(who, Severity::Bad(&format!("Peer using unsupported protocol version {}", status.version))); + if status.version < MIN_VERSION && CURRENT_VERSION < status.min_supported_version { + let reason = format!("Peer using unsupported protocol version {}", status.version); + self.network_chan.send(NetworkMsg::ReportPeer( + who, + Severity::Bad(reason), + )); return; } if self.config.roles & Roles::LIGHT == Roles::LIGHT { - let self_best_block = self.context_data.chain.info().ok() + let self_best_block = self + .context_data + .chain + .info() + .ok() .and_then(|info| info.best_queued_number) .unwrap_or_else(|| Zero::zero()); - let blocks_difference = self_best_block.as_().checked_sub(status.best_number.as_()).unwrap_or(0); + let blocks_difference = self_best_block + .as_() + .checked_sub(status.best_number.as_()) + .unwrap_or(0); if blocks_difference > LIGHT_MAXIMAL_BLOCKS_DIFFERENCE { - io.report_peer(who, Severity::Useless("Peer is far behind us and will unable to serve light requests")); + self.network_chan.send(NetworkMsg::ReportPeer( + who, + Severity::Useless( + "Peer is far behind us and will unable to serve light requests" + .to_string(), + ), + )); return; } } + let cache_limit = NonZeroUsize::new(1_000_000).expect("1_000_000 > 0; qed"); + + let info = match self.handshaking_peers.remove(&who) { + Some(handshaking) => { + let peer_info = PeerInfo { + peer_id: handshaking.peer_id, + protocol_version: status.version, + roles: status.roles, + best_hash: status.best_hash, + best_number: status.best_number + }; + self.connected_peers + .write() + .insert(who, ConnectedPeer { peer_info: peer_info.clone() }); + peer_info + }, + None => { + debug!(target: "sync", "Received status from previously unconnected node {}", who); + return; + }, + }; + let peer = Peer { - protocol_version: status.version, - roles: status.roles, - best_hash: status.best_hash, - best_number: status.best_number, + info, block_request: None, - request_timestamp: None, - known_extrinsics: HashSet::new(), - known_blocks: HashSet::new(), + known_extrinsics: LruHashSet::new(cache_limit), + known_blocks: LruHashSet::new(cache_limit), next_request_id: 0, + obsolete_requests: HashMap::new(), }; - peers.insert(who.clone(), peer); - handshaking_peers.remove(&who); - debug!(target: "sync", "Connected {} {}", who, io.peer_debug_info(who)); + self.context_data.peers.insert(who.clone(), peer); + + debug!(target: "sync", "Connected {}", who); } - let mut context = ProtocolContext::new(&self.context_data, io); - self.on_demand.as_ref().map(|s| s.on_connect(who, status.roles, status.best_number)); - self.sync.write().new_peer(&mut context, who); - self.consensus_gossip.write().new_peer(&mut context, who, status.roles); - self.specialization.write().on_connect(&mut context, who, status); + let mut context = ProtocolContext::new(&mut self.context_data, &self.network_chan); + self.on_demand + .as_ref() + .map(|s| s.on_connect(who, status.roles, status.best_number)); + self.sync.new_peer(&mut context, who); + self.consensus_gossip + .new_peer(&mut context, who, status.roles); + self.specialization.on_connect(&mut context, who, status); } /// Called when peer sends us new extrinsics - fn on_extrinsics(&self, _io: &mut SyncIo, who: NodeIndex, extrinsics: message::Transactions) { + fn on_extrinsics(&mut self, who: NodeIndex, extrinsics: message::Transactions) { // Accept extrinsics only when fully synced - if self.sync.read().status().state != SyncState::Idle { + if self.sync.status().state != SyncState::Idle { trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); return; } trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); - let mut peers = self.context_data.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&who) { + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { for t in extrinsics { if let Some(hash) = self.transaction_pool.import(&t) { peer.known_extrinsics.insert(hash); @@ -523,19 +798,17 @@ impl, H: ExHashT> Protocol { } /// Called when we propagate ready extrinsics to peers. - pub fn propagate_extrinsics(&self, io: &mut SyncIo) { + fn propagate_extrinsics(&mut self) { debug!(target: "sync", "Propagating extrinsics"); // Accept transactions only when fully synced - if self.sync.read().status().state != SyncState::Idle { + if self.sync.status().state != SyncState::Idle { return; } let extrinsics = self.transaction_pool.transactions(); - let mut propagated_to = HashMap::new(); - let mut peers = self.context_data.peers.write(); - for (who, ref mut peer) in peers.iter_mut() { + for (who, peer) in self.context_data.peers.iter_mut() { let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics .iter() .filter(|&(ref hash, _)| peer.known_extrinsics.insert(hash.clone())) @@ -543,75 +816,103 @@ impl, H: ExHashT> Protocol { .unzip(); if !to_send.is_empty() { - let node_id = io.peer_id(*who).map(|id| id.to_base58()); - if let Some(id) = node_id { - for hash in hashes { - propagated_to.entry(hash).or_insert_with(Vec::new).push(id.clone()); - } + for hash in hashes { + propagated_to + .entry(hash) + .or_insert_with(Vec::new) + .push(peer.info.peer_id.to_base58()); } trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); - self.send_message(io, *who, GenericMessage::Transactions(to_send)); + self.network_chan.send(NetworkMsg::Outgoing(*who, GenericMessage::Transactions(to_send))) } } self.transaction_pool.on_broadcasted(propagated_to); } + /// Make sure an important block is propagated to peers. + /// + /// In chain-based consensus, we often need to make sure non-best forks are + /// at least temporarily synced. + pub fn announce_block(&mut self, hash: B::Hash) { + let header = match self.context_data.chain.header(&BlockId::Hash(hash)) { + Ok(Some(header)) => header, + Ok(None) => { + warn!("Trying to announce unknown block: {}", hash); + return; + } + Err(e) => { + warn!("Error reading block header {}: {:?}", hash, e); + return; + } + }; + let hash = header.hash(); + + let message = GenericMessage::BlockAnnounce(message::BlockAnnounce { header: header.clone() }); + + for (who, ref mut peer) in self.context_data.peers.iter_mut() { + trace!(target: "sync", "Reannouncing block {:?} to {}", hash, who); + peer.known_blocks.insert(hash); + self.network_chan.send(NetworkMsg::Outgoing(*who, message.clone())) + } + } + /// Send Status message - fn send_status(&self, io: &mut SyncIo, who: NodeIndex) { + fn send_status(&mut self, who: NodeIndex) { if let Ok(info) = self.context_data.chain.info() { let status = message::generic::Status { version: CURRENT_VERSION, + min_supported_version: MIN_VERSION, genesis_hash: info.chain.genesis_hash, roles: self.config.roles.into(), best_number: info.chain.best_number, best_hash: info.chain.best_hash, - chain_status: self.specialization.read().status(), + chain_status: self.specialization.status(), }; - self.send_message(io, who, GenericMessage::Status(status)) + self.send_message(who, GenericMessage::Status(status)) } } - pub fn abort(&self) { - let mut sync = self.sync.write(); - let mut spec = self.specialization.write(); - let mut peers = self.context_data.peers.write(); - let mut handshaking_peers = self.handshaking_peers.write(); - let mut consensus_gossip = self.consensus_gossip.write(); - sync.clear(); - spec.on_abort(); - peers.clear(); - handshaking_peers.clear(); - consensus_gossip.abort(); + fn abort(&mut self) { + self.sync.clear(); + self.specialization.on_abort(); + self.context_data.peers.clear(); + self.handshaking_peers.clear(); + self.consensus_gossip.abort(); } - pub fn stop(&self) { + fn stop(&mut self) { // stop processing import requests first (without holding a sync lock) - let import_queue = self.sync.read().import_queue(); - import_queue.stop(); + self.sync.stop(); // and then clear all the sync data self.abort(); } - pub fn on_block_announce(&self, io: &mut SyncIo, who: NodeIndex, announce: message::BlockAnnounce) { + fn on_block_announce(&mut self, who: NodeIndex, announce: message::BlockAnnounce) { let header = announce.header; let hash = header.hash(); { - let mut peers = self.context_data.peers.write(); - if let Some(ref mut peer) = peers.get_mut(&who) { + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { peer.known_blocks.insert(hash.clone()); } } - self.on_demand.as_ref().map(|s| s.on_block_announce(who, *header.number())); - self.sync.write().on_block_announce(&mut ProtocolContext::new(&self.context_data, io), who, hash, &header); + self.on_demand + .as_ref() + .map(|s| s.on_block_announce(who, *header.number())); + self.sync.on_block_announce( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + who, + hash, + &header, + ); } - pub fn on_block_imported(&self, io: &mut SyncIo, hash: B::Hash, header: &B::Header) { - self.sync.write().update_chain_info(&header); - self.specialization.write().on_block_imported( - &mut ProtocolContext::new(&self.context_data, io), + fn on_block_imported(&mut self, hash: B::Hash, header: &B::Header) { + self.sync.update_chain_info(header); + self.specialization.on_block_imported( + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), hash.clone(), - header + header, ); // blocks are not announced by light clients @@ -620,60 +921,95 @@ impl, H: ExHashT> Protocol { } // send out block announcements - let mut peers = self.context_data.peers.write(); - for (who, ref mut peer) in peers.iter_mut() { + let message = GenericMessage::BlockAnnounce(message::BlockAnnounce { header: header.clone() }); + + for (who, ref mut peer) in self.context_data.peers.iter_mut() { if peer.known_blocks.insert(hash.clone()) { trace!(target: "sync", "Announcing block {:?} to {}", hash, who); - self.send_message(io, *who, GenericMessage::BlockAnnounce(message::BlockAnnounce { - header: header.clone() - })); + self.network_chan.send(NetworkMsg::Outgoing(*who, message.clone())) } } } - fn on_remote_call_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteCallRequest) { + fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) { + self.sync.on_block_finalized( + &hash, + *header.number(), + &mut ProtocolContext::new(&mut self.context_data, &self.network_chan), + ); + } + + fn on_remote_call_request( + &mut self, + who: NodeIndex, + request: message::RemoteCallRequest, + ) { trace!(target: "sync", "Remote call request {} from {} ({} at {})", request.id, who, request.method, request.block); - let proof = match self.context_data.chain.execution_proof(&request.block, &request.method, &request.data) { + let proof = match self.context_data.chain.execution_proof( + &request.block, + &request.method, + &request.data, + ) { Ok((_, proof)) => proof, Err(error) => { trace!(target: "sync", "Remote call request {} from {} ({} at {}) failed with: {}", request.id, who, request.method, request.block, error); Default::default() - }, + } }; - self.send_message(io, who, GenericMessage::RemoteCallResponse(message::RemoteCallResponse { - id: request.id, proof, - })); + self.send_message( + who, + GenericMessage::RemoteCallResponse(message::RemoteCallResponse { + id: request.id, + proof, + }), + ); } - fn on_remote_call_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteCallResponse) { + fn on_remote_call_response(&mut self, who: NodeIndex, response: message::RemoteCallResponse) { trace!(target: "sync", "Remote call response {} from {}", response.id, who); - self.on_demand.as_ref().map(|s| s.on_remote_call_response(io, who, response)); + self.on_demand + .as_ref() + .map(|s| s.on_remote_call_response(who, response)); } - fn on_remote_read_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteReadRequest) { + fn on_remote_read_request( + &mut self, + who: NodeIndex, + request: message::RemoteReadRequest, + ) { trace!(target: "sync", "Remote read request {} from {} ({} at {})", - request.id, who, request.key.to_hex(), request.block); + request.id, who, request.key.to_hex::(), request.block); let proof = match self.context_data.chain.read_proof(&request.block, &request.key) { Ok(proof) => proof, Err(error) => { trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}", - request.id, who, request.key.to_hex(), request.block, error); + request.id, who, request.key.to_hex::(), request.block, error); Default::default() - }, + } }; - self.send_message(io, who, GenericMessage::RemoteReadResponse(message::RemoteReadResponse { - id: request.id, proof, - })); + self.send_message( + who, + GenericMessage::RemoteReadResponse(message::RemoteReadResponse { + id: request.id, + proof, + }), + ); } - fn on_remote_read_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteReadResponse) { + fn on_remote_read_response(&mut self, who: NodeIndex, response: message::RemoteReadResponse) { trace!(target: "sync", "Remote read response {} from {}", response.id, who); - self.on_demand.as_ref().map(|s| s.on_remote_read_response(io, who, response)); + self.on_demand + .as_ref() + .map(|s| s.on_remote_read_response(who, response)); } - fn on_remote_header_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteHeaderRequest>) { + fn on_remote_header_request( + &mut self, + who: NodeIndex, + request: message::RemoteHeaderRequest>, + ) { trace!(target: "sync", "Remote header proof request {} from {} ({})", request.id, who, request.block); let (header, proof) = match self.context_data.chain.header_proof(request.block) { @@ -682,72 +1018,93 @@ impl, H: ExHashT> Protocol { trace!(target: "sync", "Remote header proof request {} from {} ({}) failed with: {}", request.id, who, request.block, error); (Default::default(), Default::default()) - }, + } }; - self.send_message(io, who, GenericMessage::RemoteHeaderResponse(message::RemoteHeaderResponse { - id: request.id, header, proof, - })); + self.send_message( + who, + GenericMessage::RemoteHeaderResponse(message::RemoteHeaderResponse { + id: request.id, + header, + proof, + }), + ); } - fn on_remote_header_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteHeaderResponse) { + fn on_remote_header_response( + &mut self, + who: NodeIndex, + response: message::RemoteHeaderResponse, + ) { trace!(target: "sync", "Remote header proof response {} from {}", response.id, who); - self.on_demand.as_ref().map(|s| s.on_remote_header_response(io, who, response)); + self.on_demand + .as_ref() + .map(|s| s.on_remote_header_response(who, response)); } - fn on_remote_changes_request(&self, io: &mut SyncIo, who: NodeIndex, request: message::RemoteChangesRequest) { + fn on_remote_changes_request( + &mut self, + who: NodeIndex, + request: message::RemoteChangesRequest, + ) { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})", - request.id, who, request.key.to_hex(), request.first, request.last); - let proof = match self.context_data.chain.key_changes_proof(request.first, request.last, request.min, request.max, &request.key) { + request.id, who, request.key.to_hex::(), request.first, request.last); + let key = StorageKey(request.key); + let proof = match self.context_data.chain.key_changes_proof(request.first, request.last, request.min, request.max, &key) { Ok(proof) => proof, Err(error) => { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}", - request.id, who, request.key.to_hex(), request.first, request.last, error); + request.id, who, key.0.to_hex::(), request.first, request.last, error); ChangesProof:: { max_block: Zero::zero(), proof: vec![], roots: BTreeMap::new(), roots_proof: vec![], } - }, + } }; - self.send_message(io, who, GenericMessage::RemoteChangesResponse(message::RemoteChangesResponse { - id: request.id, - max: proof.max_block, - proof: proof.proof, - roots: proof.roots.into_iter().collect(), - roots_proof: proof.roots_proof, - })); + self.send_message( + who, + GenericMessage::RemoteChangesResponse(message::RemoteChangesResponse { + id: request.id, + max: proof.max_block, + proof: proof.proof, + roots: proof.roots.into_iter().collect(), + roots_proof: proof.roots_proof, + }), + ); } - fn on_remote_changes_response(&self, io: &mut SyncIo, who: NodeIndex, response: message::RemoteChangesResponse, B::Hash>) { + fn on_remote_changes_response( + &mut self, + who: NodeIndex, + response: message::RemoteChangesResponse, B::Hash>, + ) { trace!(target: "sync", "Remote changes proof response {} from {} (max={})", response.id, who, response.max); - self.on_demand.as_ref().map(|s| s.on_remote_changes_response(io, who, response)); - } - - - /// Execute a closure with access to a network context and specialization. - pub fn with_spec(&self, io: &mut SyncIo, f: F) -> U - where F: FnOnce(&mut S, &mut Context) -> U - { - f(&mut* self.specialization.write(), &mut ProtocolContext::new(&self.context_data, io)) + self.on_demand + .as_ref() + .map(|s| s.on_remote_changes_response(who, response)); } } -fn send_message(peers: &RwLock>>, io: &mut SyncIo, who: NodeIndex, mut message: Message) { - match &mut message { - &mut GenericMessage::BlockRequest(ref mut r) => { - let mut peers = peers.write(); - if let Some(ref mut peer) = peers.get_mut(&who) { - r.id = peer.next_request_id; - peer.next_request_id = peer.next_request_id + 1; - peer.block_request = Some(r.clone()); - peer.request_timestamp = Some(time::Instant::now()); +fn send_message( + peers: &mut HashMap>, + network_chan: &NetworkChan, + who: NodeIndex, + mut message: Message, +) { + if let GenericMessage::BlockRequest(ref mut r) = message { + if let Some(ref mut peer) = peers.get_mut(&who) { + r.id = peer.next_request_id; + peer.next_request_id = peer.next_request_id + 1; + if let Some((timestamp, request)) = peer.block_request.take() { + trace!(target: "sync", "Request {} for {} is now obsolete.", request.id, who); + peer.obsolete_requests.insert(request.id, timestamp); } - }, - _ => (), + peer.block_request = Some((time::Instant::now(), r.clone())); + } } - io.send(who, message.encode()); + network_chan.send(NetworkMsg::Outgoing(who, message)); } /// Construct a simple protocol that is composed of several sub protocols. diff --git a/core/network/src/service.rs b/core/network/src/service.rs index d633e0397de00cc1bb40fd28b28cbd4e78da4335..34f82d2ddc7d06be33731e49bfd464613612dbcb 100644 --- a/core/network/src/service.rs +++ b/core/network/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,38 +16,54 @@ use std::collections::HashMap; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::{io, thread}; -use std::time::Duration; -use futures::{self, Future, Stream, stream, sync::oneshot}; +use log::{warn, debug, error, trace, info}; +use futures::{Async, Future, Stream, stream, sync::oneshot, sync::mpsc}; use parking_lot::{Mutex, RwLock}; -use network_libp2p::{ProtocolId, PeerId, NetworkConfiguration, ErrorKind}; -use network_libp2p::{start_service, Service as NetworkService, ServiceEvent as NetworkServiceEvent}; -use network_libp2p::{RegisteredProtocol, parse_str_addr, Protocol as Libp2pProtocol}; -use io::NetSyncIo; -use consensus_gossip::ConsensusGossip; -use protocol::{self, Protocol, ProtocolContext, Context, ProtocolStatus}; -use config::Params; -use error::Error; -use specialization::NetworkSpecialization; -use import_queue::ImportQueue; -use runtime_primitives::traits::{Block as BlockT}; -use tokio::{runtime::Runtime, timer::Interval}; +use network_libp2p::{ProtocolId, NetworkConfiguration, NodeIndex, Severity}; +use network_libp2p::{start_service, parse_str_addr, Service as NetworkService, ServiceEvent as NetworkServiceEvent}; +use network_libp2p::{Protocol as Libp2pProtocol, RegisteredProtocol, NetworkState}; +use consensus::import_queue::{ImportQueue, Link}; +use crate::consensus_gossip::ConsensusGossip; +use crate::message::{Message, ConsensusEngineId}; +use crate::protocol::{self, Context, FromNetworkMsg, Protocol, ConnectedPeer, ProtocolMsg, ProtocolStatus, PeerInfo}; +use crate::config::Params; +use crossbeam_channel::{self as channel, Receiver, Sender, TryRecvError}; +use crate::error::Error; +use runtime_primitives::traits::{Block as BlockT, NumberFor}; +use crate::specialization::NetworkSpecialization; + +use tokio::prelude::task::AtomicTask; +use tokio::runtime::Builder as RuntimeBuilder; + +pub use network_libp2p::PeerId; /// Type that represents fetch completion future. pub type FetchFuture = oneshot::Receiver>; -const TICK_TIMEOUT: Duration = Duration::from_millis(1000); -const PROPAGATE_TIMEOUT: Duration = Duration::from_millis(5000); /// Sync status pub trait SyncProvider: Send + Sync { - /// Get sync status - fn status(&self) -> ProtocolStatus; + /// Get a stream of sync statuses. + fn status(&self) -> mpsc::UnboundedReceiver>; + /// Get network state. + fn network_state(&self) -> NetworkState; + /// Get currently connected peers + fn peers(&self) -> Vec<(NodeIndex, PeerInfo)>; + /// Are we in the process of downloading the chain? + fn is_major_syncing(&self) -> bool; } /// Minimum Requirements for a Hash within Networking -pub trait ExHashT: ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static {} -impl ExHashT for T where T: ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static {} +pub trait ExHashT: + ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static +{ +} +impl ExHashT for T where + T: ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static +{ +} /// Transaction pool interface pub trait TransactionPool: Send + Sync { @@ -59,104 +75,222 @@ pub trait TransactionPool: Send + Sync { fn on_broadcasted(&self, propagations: HashMap>); } -/// Service able to execute closure in the network context. -pub trait ExecuteInContext: Send + Sync { - /// Execute closure in network context. - fn execute_in_context)>(&self, closure: F); +/// A link implementation that connects to the network. +#[derive(Clone)] +pub struct NetworkLink> { + /// The protocol sender + pub(crate) protocol_sender: Sender>, + /// The network sender + pub(crate) network_sender: NetworkChan, +} + +impl> Link for NetworkLink { + fn block_imported(&self, hash: &B::Hash, number: NumberFor) { + let _ = self.protocol_sender.send(ProtocolMsg::BlockImportedSync(hash.clone(), number)); + } + + fn blocks_processed(&self, processed_blocks: Vec, has_error: bool) { + let _ = self.protocol_sender.send(ProtocolMsg::BlocksProcessed(processed_blocks, has_error)); + } + + fn justification_imported(&self, who: NodeIndex, hash: &B::Hash, number: NumberFor, success: bool) { + let _ = self.protocol_sender.send(ProtocolMsg::JustificationImportResult(hash.clone(), number, success)); + if !success { + let reason = Severity::Bad(format!("Invalid justification provided for #{}", hash).to_string()); + let _ = self.network_sender.send(NetworkMsg::ReportPeer(who, reason)); + } + } + + fn clear_justification_requests(&self) { + let _ = self.protocol_sender.send(ProtocolMsg::ClearJustificationRequests); + } + + fn request_justification(&self, hash: &B::Hash, number: NumberFor) { + let _ = self.protocol_sender.send(ProtocolMsg::RequestJustification(hash.clone(), number)); + } + + fn useless_peer(&self, who: NodeIndex, reason: &str) { + trace!(target:"sync", "Useless peer {}, {}", who, reason); + self.network_sender.send(NetworkMsg::ReportPeer(who, Severity::Useless(reason.to_string()))); + } + + fn note_useless_and_restart_sync(&self, who: NodeIndex, reason: &str) { + trace!(target:"sync", "Bad peer {}, {}", who, reason); + // is this actually malign or just useless? + self.network_sender.send(NetworkMsg::ReportPeer(who, Severity::Useless(reason.to_string()))); + let _ = self.protocol_sender.send(ProtocolMsg::RestartSync); + } + + fn restart(&self) { + let _ = self.protocol_sender.send(ProtocolMsg::RestartSync); + } } /// Substrate network service. Handles network IO and manages connectivity. -pub struct Service, H: ExHashT> { +pub struct Service> { + /// Sinks to propagate status updates. + status_sinks: Arc>>>>, + /// Are we connected to any peer? + is_offline: Arc, + /// Are we actively catching up with the chain? + is_major_syncing: Arc, + /// Peers whom we are connected with. + peers: Arc>>>, /// Network service - network: Arc>, - /// Protocol handler - handler: Arc>, - /// Protocol ID. - protocol_id: ProtocolId, + network: Arc>>>, + /// Protocol sender + protocol_sender: Sender>, /// Sender for messages to the background service task, and handle for the background thread. /// Dropping the sender should close the task and the thread. /// This is an `Option` because we need to extract it in the destructor. bg_thread: Option<(oneshot::Sender<()>, thread::JoinHandle<()>)>, } -impl, H: ExHashT> Service { +impl> Service { /// Creates and register protocol with the network service - pub fn new>( + pub fn new( params: Params, protocol_id: ProtocolId, - import_queue: Arc, - ) -> Result>, Error> { - let handler = Arc::new(Protocol::new( + import_queue: Box>, + ) -> Result<(Arc>, NetworkChan), Error> { + let (network_chan, network_port) = network_channel(protocol_id); + let status_sinks = Arc::new(Mutex::new(Vec::new())); + // Start in off-line mode, since we're not connected to any nodes yet. + let is_offline = Arc::new(AtomicBool::new(true)); + let is_major_syncing = Arc::new(AtomicBool::new(false)); + let peers: Arc>>> = Arc::new(Default::default()); + let (protocol_sender, network_to_protocol_sender) = Protocol::new( + status_sinks.clone(), + is_offline.clone(), + is_major_syncing.clone(), + peers.clone(), + network_chan.clone(), params.config, params.chain, import_queue.clone(), params.on_demand, params.transaction_pool, params.specialization, - )?); + )?; let versions = [(protocol::CURRENT_VERSION as u8)]; let registered = RegisteredProtocol::new(protocol_id, &versions[..]); - let (thread, network) = start_thread(params.network_config, handler.clone(), registered)?; + let (thread, network) = start_thread( + network_to_protocol_sender, + network_port, + params.network_config, + registered, + )?; let service = Arc::new(Service { + status_sinks, + is_offline, + is_major_syncing, + peers, network, - protocol_id, - handler, - bg_thread: Some(thread) + protocol_sender: protocol_sender.clone(), + bg_thread: Some(thread), }); // connect the import-queue to the network service. - let link = ::import_queue::NetworkLink { - sync: Arc::downgrade(service.handler.sync()), - context: Arc::downgrade(&service), + let link = NetworkLink { + protocol_sender, + network_sender: network_chan.clone(), }; - import_queue.start(link)?; + import_queue.start(Box::new(link))?; - Ok(service) + Ok((service, network_chan)) + } + + /// Returns the downloaded bytes per second averaged over the past few seconds. + #[inline] + pub fn average_download_per_sec(&self) -> u64 { + self.network.lock().average_download_per_sec() + } + + /// Returns the uploaded bytes per second averaged over the past few seconds. + #[inline] + pub fn average_upload_per_sec(&self) -> u64 { + self.network.lock().average_upload_per_sec() + } + + /// Returns the network identity of the node. + pub fn local_peer_id(&self) -> PeerId { + self.network.lock().peer_id().clone() } /// Called when a new block is imported by the client. - pub fn on_block_imported(&self, hash: B::Hash, header: &B::Header) { - self.handler.on_block_imported(&mut NetSyncIo::new(&self.network, self.protocol_id), hash, header) + pub fn on_block_imported(&self, hash: B::Hash, header: B::Header) { + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockImported(hash, header)); + } + + /// Called when a new block is finalized by the client. + pub fn on_block_finalized(&self, hash: B::Hash, header: B::Header) { + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockFinalized(hash, header)); } /// Called when new transactons are imported by the client. pub fn trigger_repropagate(&self) { - self.handler.propagate_extrinsics(&mut NetSyncIo::new(&self.network, self.protocol_id)); + let _ = self.protocol_sender.send(ProtocolMsg::PropagateExtrinsics); + } + + /// Make sure an important block is propagated to peers. + /// + /// In chain-based consensus, we often need to make sure non-best forks are + /// at least temporarily synced. + pub fn announce_block(&self, hash: B::Hash) { + let _ = self.protocol_sender.send(ProtocolMsg::AnnounceBlock(hash)); } /// Send a consensus message through the gossip - pub fn gossip_consensus_message(&self, topic: B::Hash, message: Vec, broadcast: bool) { - self.handler.gossip_consensus_message( - &mut NetSyncIo::new(&self.network, self.protocol_id), - topic, - message, - broadcast, - ) + pub fn gossip_consensus_message(&self, topic: B::Hash, engine_id: ConsensusEngineId, message: Vec) { + let _ = self + .protocol_sender + .send(ProtocolMsg::GossipConsensusMessage( + topic, engine_id, message, + )); } + /// Execute a closure with the chain-specific network specialization. - pub fn with_spec(&self, f: F) -> U - where F: FnOnce(&mut S, &mut Context) -> U + pub fn with_spec(&self, f: F) + where F: FnOnce(&mut S, &mut Context) + Send + 'static + { + let _ = self + .protocol_sender + .send(ProtocolMsg::ExecuteWithSpec(Box::new(f))); + } + + /// Execute a closure with the consensus gossip. + pub fn with_gossip(&self, f: F) + where F: FnOnce(&mut ConsensusGossip, &mut Context) + Send + 'static { - self.handler.with_spec(&mut NetSyncIo::new(&self.network, self.protocol_id), f) + let _ = self + .protocol_sender + .send(ProtocolMsg::ExecuteWithGossip(Box::new(f))); } - /// access the underlying consensus gossip handler - pub fn consensus_gossip<'a>(&'a self) -> &'a RwLock> { - self.handler.consensus_gossip() + /// Are we in the process of downloading the chain? + /// Used by both SyncProvider and SyncOracle. + fn is_major_syncing(&self) -> bool { + self.is_major_syncing.load(Ordering::Relaxed) } } -impl, H: ExHashT> ::consensus::SyncOracle for Service { +impl> ::consensus::SyncOracle for Service { fn is_major_syncing(&self) -> bool { - self.handler.sync().read().status().is_major_syncing() + self.is_major_syncing() + } + fn is_offline(&self) -> bool { + self.is_offline.load(Ordering::Relaxed) } } -impl, H:ExHashT> Drop for Service { +impl> Drop for Service { fn drop(&mut self) { - self.handler.stop(); if let Some((sender, join)) = self.bg_thread.take() { let _ = sender.send(()); if let Err(e) = join.join() { @@ -166,21 +300,29 @@ impl, H:ExHashT> Drop for Servi } } -impl, H: ExHashT> ExecuteInContext for Service { - fn execute_in_context)>(&self, closure: F) { - closure(&mut ProtocolContext::new(self.handler.context_data(), &mut NetSyncIo::new(&self.network, self.protocol_id))) +impl> SyncProvider for Service { + fn is_major_syncing(&self) -> bool { + self.is_major_syncing() } -} - -impl, H: ExHashT> SyncProvider for Service { /// Get sync status - fn status(&self) -> ProtocolStatus { - self.handler.status() + fn status(&self) -> mpsc::UnboundedReceiver> { + let (sink, stream) = mpsc::unbounded(); + self.status_sinks.lock().push(sink); + stream + } + + fn network_state(&self) -> NetworkState { + self.network.lock().state() + } + + fn peers(&self) -> Vec<(NodeIndex, PeerInfo)> { + let peers = (*self.peers.read()).clone(); + peers.into_iter().map(|(idx, connected)| (idx, connected.peer_info)).collect() } } /// Trait for managing network -pub trait ManageNetwork: Send + Sync { +pub trait ManageNetwork { /// Set to allow unreserved peers to connect fn accept_unreserved_peers(&self); /// Set to deny unreserved peers to connect @@ -193,29 +335,17 @@ pub trait ManageNetwork: Send + Sync { fn node_id(&self) -> Option; } -impl, H: ExHashT> ManageNetwork for Service { +impl> ManageNetwork for Service { fn accept_unreserved_peers(&self) { self.network.lock().accept_unreserved_peers(); } fn deny_unreserved_peers(&self) { - // This method can disconnect nodes, in which case we have to properly close them in the - // protocol. - let disconnected = self.network.lock().deny_unreserved_peers(); - let mut net_sync = NetSyncIo::new(&self.network, self.protocol_id); - for node_index in disconnected { - self.handler.on_peer_disconnected(&mut net_sync, node_index) - } + self.network.lock().deny_unreserved_peers(); } fn remove_reserved_peer(&self, peer: PeerId) { - // This method can disconnect a node, in which case we have to properly close it in the - // protocol. - let disconnected = self.network.lock().remove_reserved_peer(peer); - if let Some(node_index) = disconnected { - let mut net_sync = NetSyncIo::new(&self.network, self.protocol_id); - self.handler.on_peer_disconnected(&mut net_sync, node_index) - } + self.network.lock().remove_reserved_peer(peer); } fn add_reserved_peer(&self, peer: String) -> Result<(), String> { @@ -238,32 +368,117 @@ impl, H: ExHashT> ManageNetwork } } + +/// Create a NetworkPort/Chan pair. +pub fn network_channel(protocol_id: ProtocolId) -> (NetworkChan, NetworkPort) { + let (network_sender, network_receiver) = channel::unbounded(); + let task_notify = Arc::new(AtomicTask::new()); + let network_port = NetworkPort::new(network_receiver, protocol_id, task_notify.clone()); + let network_chan = NetworkChan::new(network_sender, task_notify); + (network_chan, network_port) +} + + +/// A sender of NetworkMsg that notifies a task when a message has been sent. +#[derive(Clone)] +pub struct NetworkChan { + sender: Sender>, + task_notify: Arc, +} + +impl NetworkChan { + /// Create a new network chan. + pub fn new(sender: Sender>, task_notify: Arc) -> Self { + NetworkChan { + sender, + task_notify, + } + } + + /// Send a messaging, to be handled on a stream. Notify the task handling the stream. + pub fn send(&self, msg: NetworkMsg) { + let _ = self.sender.send(msg); + self.task_notify.notify(); + } +} + +impl Drop for NetworkChan { + /// Notifying the task when a sender is dropped(when all are dropped, the stream is finished). + fn drop(&mut self) { + self.task_notify.notify(); + } +} + + +/// A receiver of NetworkMsg that makes the protocol-id available with each message. +pub struct NetworkPort { + receiver: Receiver>, + protocol_id: ProtocolId, + task_notify: Arc, +} + +impl NetworkPort { + /// Create a new network port for a given protocol-id. + pub fn new(receiver: Receiver>, protocol_id: ProtocolId, task_notify: Arc) -> Self { + Self { + receiver, + protocol_id, + task_notify, + } + } + + /// Receive a message, if any is currently-enqueued. + /// Register the current tokio task for notification when a new message is available. + pub fn take_one_message(&self) -> Result)>, ()> { + self.task_notify.register(); + match self.receiver.try_recv() { + Ok(msg) => Ok(Some((self.protocol_id.clone(), msg))), + Err(TryRecvError::Empty) => Ok(None), + Err(TryRecvError::Disconnected) => Err(()), + } + } + + /// Get a reference to the underlying crossbeam receiver. + #[cfg(any(test, feature = "test-helpers"))] + pub fn receiver(&self) -> &Receiver> { + &self.receiver + } +} + +/// Messages to be handled by NetworkService. +#[derive(Debug)] +pub enum NetworkMsg { + /// Ask network to convert a list of nodes, to a list of peers. + PeerIds(Vec, Sender)>>), + /// Send an outgoing custom message. + Outgoing(NodeIndex, Message), + /// Report a peer. + ReportPeer(NodeIndex, Severity), +} + /// Starts the background thread that handles the networking. -fn start_thread, H: ExHashT>( +fn start_thread( + protocol_sender: Sender>, + network_port: NetworkPort, config: NetworkConfiguration, - protocol: Arc>, - registered: RegisteredProtocol, -) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc>), Error> { + registered: RegisteredProtocol>, +) -> Result<((oneshot::Sender<()>, thread::JoinHandle<()>), Arc>>>), Error> { let protocol_id = registered.id(); // Start the main service. let service = match start_service(config, Some(registered)) { Ok(service) => Arc::new(Mutex::new(service)), Err(err) => { - match err.kind() { - ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => - warn!("Network port is already in use, make sure that another instance of Substrate client is not running or change the port using the --port option."), - _ => warn!("Error starting network: {}", err), - }; + warn!("Error starting network: {}", err); return Err(err.into()) }, }; let (close_tx, close_rx) = oneshot::channel(); let service_clone = service.clone(); - let mut runtime = Runtime::new()?; + let mut runtime = RuntimeBuilder::new().name_prefix("libp2p-").build()?; let thread = thread::Builder::new().name("network".to_string()).spawn(move || { - let fut = run_thread(service_clone, protocol, protocol_id) + let fut = run_thread(protocol_sender, service_clone, network_port, protocol_id) .select(close_rx.then(|_| Ok(()))) .map(|(val, _)| val) .map_err(|(err,_ )| err); @@ -280,84 +495,98 @@ fn start_thread, H: ExHashT>( } /// Runs the background thread that handles the networking. -fn run_thread, H: ExHashT>( - network_service: Arc>, - protocol: Arc>, +fn run_thread( + protocol_sender: Sender>, + network_service: Arc>>>, + network_port: NetworkPort, protocol_id: ProtocolId, ) -> impl Future { - // Interval for performing maintenance on the protocol handler. - let tick = Interval::new_interval(TICK_TIMEOUT) - .for_each({ - let protocol = protocol.clone(); - let network_service = network_service.clone(); - move |_| { - protocol.tick(&mut NetSyncIo::new(&network_service, protocol_id)); - Ok(()) - } - }) - .then(|res| { - match res { - Ok(()) => (), - Err(err) => error!("Error in the propagation timer: {:?}", err), - }; - Ok(()) - }); - // Interval at which we gossip extrinsics over the network. - let propagate = Interval::new_interval(PROPAGATE_TIMEOUT) - .for_each({ - let protocol = protocol.clone(); - let network_service = network_service.clone(); - move |_| { - protocol.propagate_extrinsics(&mut NetSyncIo::new(&network_service, protocol_id)); - Ok(()) + let network_service_2 = network_service.clone(); + + // Protocol produces a stream of messages about what happens in sync. + let protocol = stream::poll_fn(move || { + match network_port.take_one_message() { + Ok(Some(message)) => Ok(Async::Ready(Some(message))), + Ok(None) => Ok(Async::NotReady), + Err(_) => Err(()) + } + }).for_each(move |(protocol_id, msg)| { + // Handle message from Protocol. + match msg { + NetworkMsg::PeerIds(node_idxs, sender) => { + let reply = node_idxs.into_iter().map(|idx| { + (idx, network_service_2.lock().peer_id_of_node(idx).map(|p| p.clone())) + }).collect::>(); + let _ = sender.send(reply); } - }) - .then(|res| { - match res { - Ok(()) => (), - Err(err) => error!("Error in the propagation timer: {:?}", err), - }; - Ok(()) - }); + NetworkMsg::Outgoing(who, outgoing_message) => { + network_service_2 + .lock() + .send_custom_message(who, protocol_id, outgoing_message); + }, + NetworkMsg::ReportPeer(who, severity) => { + match severity { + Severity::Bad(message) => { + info!(target: "sync", "Banning {:?} because {:?}", who, message); + network_service_2.lock().ban_node(who) + }, + Severity::Useless(message) => { + info!(target: "sync", "Dropping {:?} because {:?}", who, message); + network_service_2.lock().drop_node(who) + }, + Severity::Timeout => { + info!(target: "sync", "Dropping {:?} because it timed out", who); + network_service_2.lock().drop_node(who) + }, + } + }, + } + Ok(()) + }) + .then(|res| { + match res { + Ok(()) => (), + Err(_) => error!("Protocol disconnected"), + }; + Ok(()) + }); // The network service produces events about what happens on the network. Let's process them. - let network_service2 = network_service.clone(); - let network = stream::poll_fn(move || network_service2.lock().poll()).for_each(move |event| { - let mut net_sync = NetSyncIo::new(&network_service, protocol_id); - + let network = stream::poll_fn(move || network_service.lock().poll()).for_each(move |event| { match event { - NetworkServiceEvent::NodeClosed { node_index, closed_custom_protocols } => { - if !closed_custom_protocols.is_empty() { - debug_assert_eq!(closed_custom_protocols, &[protocol_id]); - protocol.on_peer_disconnected(&mut net_sync, node_index); - } - } - NetworkServiceEvent::ClosedCustomProtocols { node_index, protocols } => { + NetworkServiceEvent::ClosedCustomProtocols { node_index, protocols, debug_info } => { if !protocols.is_empty() { debug_assert_eq!(protocols, &[protocol_id]); - protocol.on_peer_disconnected(&mut net_sync, node_index); + let _ = protocol_sender.send( + FromNetworkMsg::PeerDisconnected(node_index, debug_info)); } } - NetworkServiceEvent::OpenedCustomProtocol { node_index, version, .. } => { + NetworkServiceEvent::OpenedCustomProtocol { peer_id, node_index, version, debug_info, .. } => { debug_assert_eq!(version, protocol::CURRENT_VERSION as u8); - protocol.on_peer_connected(&mut net_sync, node_index); + let _ = protocol_sender.send(FromNetworkMsg::PeerConnected(peer_id, node_index, debug_info)); } - NetworkServiceEvent::ClosedCustomProtocol { node_index, .. } => { - protocol.on_peer_disconnected(&mut net_sync, node_index); + NetworkServiceEvent::ClosedCustomProtocol { node_index, debug_info, .. } => { + let _ = protocol_sender.send(FromNetworkMsg::PeerDisconnected(node_index, debug_info)); } - NetworkServiceEvent::CustomMessage { node_index, data, .. } => { - protocol.handle_packet(&mut net_sync, node_index, &data); + NetworkServiceEvent::CustomMessage { node_index, message, .. } => { + let _ = protocol_sender.send(FromNetworkMsg::CustomMessage(node_index, message)); + return Ok(()) + } + NetworkServiceEvent::Clogged { node_index, messages, .. } => { + debug!(target: "sync", "{} clogging messages:", messages.len()); + for msg in messages.into_iter().take(5) { + debug!(target: "sync", "{:?}", msg); + let _ = protocol_sender.send(FromNetworkMsg::PeerClogged(node_index, Some(msg))); + } } }; - Ok(()) }); // Merge all futures into one. let futures: Vec + Send>> = vec![ - Box::new(tick) as Box<_>, - Box::new(propagate) as Box<_>, + Box::new(protocol) as Box<_>, Box::new(network) as Box<_> ]; diff --git a/core/network/src/specialization.rs b/core/network/src/specialization.rs index d1cde8b33b110c79ba0cbaf7cb66636f6e7000e6..3a772f1f3a9d2972b9140adbf6f479b21269301f 100644 --- a/core/network/src/specialization.rs +++ b/core/network/src/specialization.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,9 @@ //! Specializations of the substrate network protocol to allow more complex forms of communication. -use ::NodeIndex; +use crate::NodeIndex; use runtime_primitives::traits::Block as BlockT; -use protocol::Context; +use crate::protocol::Context; /// A specialization of the substrate network protocol. Handles events and sends messages. pub trait NetworkSpecialization: Send + Sync + 'static { @@ -26,13 +26,13 @@ pub trait NetworkSpecialization: Send + Sync + 'static { fn status(&self) -> Vec; /// Called when a peer successfully handshakes. - fn on_connect(&mut self, ctx: &mut Context, who: NodeIndex, status: ::message::Status); + fn on_connect(&mut self, ctx: &mut Context, who: NodeIndex, status: crate::message::Status); /// Called when a peer is disconnected. If the peer ID is unknown, it should be ignored. fn on_disconnect(&mut self, ctx: &mut Context, who: NodeIndex); /// Called when a network-specific message arrives. - fn on_message(&mut self, ctx: &mut Context, who: NodeIndex, message: &mut Option<::message::Message>); + fn on_message(&mut self, ctx: &mut Context, who: NodeIndex, message: &mut Option>); /// Called on abort. fn on_abort(&mut self) { } diff --git a/core/network/src/sync.rs b/core/network/src/sync.rs index 3a78bd16aaf1cf391dfb7c82e1a63adc4311841d..a4dc1855ef00aa42073fc319d072d230c9401f13 100644 --- a/core/network/src/sync.rs +++ b/core/network/src/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,39 +14,303 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::collections::HashMap; -use std::sync::Arc; -use protocol::Context; +use std::cmp::max; +use std::collections::{HashMap, VecDeque}; +use std::time::{Duration, Instant}; +use log::{debug, trace, warn}; +use crate::protocol::Context; +use fork_tree::ForkTree; use network_libp2p::{Severity, NodeIndex}; use client::{BlockStatus, ClientInfo}; use consensus::BlockOrigin; +use consensus::import_queue::{ImportQueue, IncomingBlock}; use client::error::Error as ClientError; -use blocks::{self, BlockCollection}; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor}; +use crate::blocks::BlockCollection; +use runtime_primitives::Justification; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, CheckedSub}; use runtime_primitives::generic::BlockId; -use message::{self, generic::Message as GenericMessage}; -use config::Roles; -use import_queue::ImportQueue; +use crate::message::{self, generic::Message as GenericMessage}; +use crate::config::Roles; +use std::collections::HashSet; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; // Maximum blocks to request in a single packet. const MAX_BLOCKS_TO_REQUEST: usize = 128; // Maximum blocks to store in the import queue. const MAX_IMPORTING_BLOCKS: usize = 2048; - +// Number of blocks in the queue that prevents ancestry search. +const MAJOR_SYNC_BLOCKS: usize = 5; +// Time to wait before trying to get a justification from the same peer. +const JUSTIFICATION_RETRY_WAIT: Duration = Duration::from_secs(10); +// Number of recently announced blocks to track for each peer. +const ANNOUNCE_HISTORY_SIZE: usize = 64; +// Max number of blocks to download for unknown forks. +// TODO: this should take finality into account. See https://github.com/paritytech/substrate/issues/1606 +const MAX_UNKNOWN_FORK_DOWNLOAD_LEN: u32 = 32; + +#[derive(Debug)] struct PeerSync { - pub common_hash: B::Hash, pub common_number: NumberFor, pub best_hash: B::Hash, pub best_number: NumberFor, pub state: PeerSyncState, + pub recently_announced: VecDeque, +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum AncestorSearchState { + /// Use exponential backoff to find an ancestor, then switch to binary search. + /// We keep track of the exponent. + ExponentialBackoff(NumberFor), + /// Using binary search to find the best ancestor. + /// We keep track of left and right bounds. + BinarySearch(NumberFor, NumberFor), } #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum PeerSyncState { - AncestorSearch(NumberFor), + AncestorSearch(NumberFor, AncestorSearchState), Available, DownloadingNew(NumberFor), DownloadingStale(B::Hash), + DownloadingJustification(B::Hash), +} + +/// Pending justification request for the given block (hash and number). +type PendingJustification = (::Hash, NumberFor); + +/// Manages pending block justification requests. Multiple justifications may be +/// requested for competing forks, or for the same branch at different +/// (increasing) heights. This structure will guarantee that justifications are +/// fetched in-order, and that obsolete changes are pruned (when finalizing a +/// competing fork). +struct PendingJustifications { + justifications: ForkTree, ()>, + pending_requests: VecDeque>, + peer_requests: HashMap>, + previous_requests: HashMap, Vec<(NodeIndex, Instant)>>, +} + +impl PendingJustifications { + fn new() -> PendingJustifications { + PendingJustifications { + justifications: ForkTree::new(), + pending_requests: VecDeque::new(), + peer_requests: HashMap::new(), + previous_requests: HashMap::new(), + } + } + + /// Dispatches all possible pending requests to the given peers. Peers are + /// filtered according to the current known best block (i.e. we won't send a + /// justification request for block #10 to a peer at block #2), and we also + /// throttle requests to the same peer if a previous justification request + /// yielded no results. + fn dispatch(&mut self, peers: &mut HashMap>, protocol: &mut Context) { + if self.pending_requests.is_empty() { + return; + } + + let initial_pending_requests = self.pending_requests.len(); + + // clean up previous failed requests so we can retry again + for (_, requests) in self.previous_requests.iter_mut() { + requests.retain(|(_, instant)| instant.elapsed() < JUSTIFICATION_RETRY_WAIT); + } + + let mut available_peers = peers.iter().filter_map(|(peer, sync)| { + // don't request to any peers that already have pending requests or are unavailable + if sync.state != PeerSyncState::Available || self.peer_requests.contains_key(&peer) { + None + } else { + Some((*peer, sync.best_number)) + } + }).collect::>(); + + let mut last_peer = available_peers.back().map(|p| p.0); + let mut unhandled_requests = VecDeque::new(); + + loop { + let (peer, peer_best_number) = match available_peers.pop_front() { + Some(p) => p, + _ => break, + }; + + // only ask peers that have synced past the block number that we're + // asking the justification for and to whom we haven't already made + // the same request recently + let peer_eligible = { + let request = match self.pending_requests.front() { + Some(r) => r.clone(), + _ => break, + }; + + peer_best_number >= request.1 && + !self.previous_requests + .get(&request) + .map(|requests| requests.iter().any(|i| i.0 == peer)) + .unwrap_or(false) + }; + + if !peer_eligible { + available_peers.push_back((peer, peer_best_number)); + + // we tried all peers and none can answer this request + if Some(peer) == last_peer { + last_peer = available_peers.back().map(|p| p.0); + + let request = self.pending_requests.pop_front() + .expect("verified to be Some in the beginning of the loop; qed"); + + unhandled_requests.push_back(request); + } + + continue; + } + + last_peer = available_peers.back().map(|p| p.0); + + let request = self.pending_requests.pop_front() + .expect("verified to be Some in the beginning of the loop; qed"); + + self.peer_requests.insert(peer, request); + + peers.get_mut(&peer) + .expect("peer was is taken from available_peers; available_peers is a subset of peers; qed") + .state = PeerSyncState::DownloadingJustification(request.0); + + trace!(target: "sync", "Requesting justification for block #{} from {}", request.0, peer); + let request = message::generic::BlockRequest { + id: 0, + fields: message::BlockAttributes::JUSTIFICATION, + from: message::FromBlock::Hash(request.0), + to: None, + direction: message::Direction::Ascending, + max: Some(1), + }; + + protocol.send_message(peer, GenericMessage::BlockRequest(request)); + } + + self.pending_requests.append(&mut unhandled_requests); + + trace!(target: "sync", "Dispatched {} justification requests ({} pending)", + initial_pending_requests - self.pending_requests.len(), + self.pending_requests.len(), + ); + } + + /// Queue a justification request (without dispatching it). + fn queue_request( + &mut self, + justification: &PendingJustification, + is_descendent_of: F, + ) where F: Fn(&B::Hash, &B::Hash) -> Result { + match self.justifications.import(justification.0.clone(), justification.1.clone(), (), &is_descendent_of) { + Ok(true) => { + // this is a new root so we add it to the current `pending_requests` + self.pending_requests.push_back((justification.0, justification.1)); + }, + Err(err) => { + warn!(target: "sync", "Failed to insert requested justification {:?} {:?} into tree: {:?}", + justification.0, + justification.1, + err, + ); + return; + }, + _ => {}, + }; + } + + /// Retry any pending request if a peer disconnected. + fn peer_disconnected(&mut self, who: NodeIndex) { + if let Some(request) = self.peer_requests.remove(&who) { + self.pending_requests.push_front(request); + } + } + + /// Process the import of a justification. + /// Queues a retry in case the import failed. + fn justification_import_result(&mut self, hash: B::Hash, number: NumberFor, success: bool) { + let request = (hash, number); + if success { + if self.justifications.finalize_root(&request.0).is_none() { + warn!(target: "sync", "Imported justification for {:?} {:?} which isn't a root in the tree: {:?}", + request.0, + request.1, + self.justifications.roots().collect::>(), + ); + return; + }; + + self.previous_requests.clear(); + self.peer_requests.clear(); + self.pending_requests = + self.justifications.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect(); + + return; + } + self.pending_requests.push_front(request); + } + + /// Processes the response for the request previously sent to the given + /// peer. Queues a retry in case the given justification + /// was `None`. + fn on_response( + &mut self, + who: NodeIndex, + justification: Option, + import_queue: &ImportQueue, + ) { + // we assume that the request maps to the given response, this is + // currently enforced by the outer network protocol before passing on + // messages to chain sync. + if let Some(request) = self.peer_requests.remove(&who) { + if let Some(justification) = justification { + import_queue.import_justification(who.clone(), request.0, request.1, justification); + return + } + + self.previous_requests + .entry(request) + .or_insert(Vec::new()) + .push((who, Instant::now())); + self.pending_requests.push_front(request); + } + } + + /// Removes any pending justification requests for blocks lower than the + /// given best finalized. + fn on_block_finalized( + &mut self, + best_finalized_hash: &B::Hash, + best_finalized_number: NumberFor, + is_descendent_of: F, + ) -> Result<(), fork_tree::Error> + where F: Fn(&B::Hash, &B::Hash) -> Result + { + use std::collections::HashSet; + + self.justifications.finalize(best_finalized_hash, best_finalized_number, &is_descendent_of)?; + + let roots = self.justifications.roots().collect::>(); + + self.pending_requests.retain(|(h, n)| roots.contains(&(h, n, &()))); + self.peer_requests.retain(|_, (h, n)| roots.contains(&(h, n, &()))); + self.previous_requests.retain(|(h, n), _| roots.contains(&(h, n, &()))); + + Ok(()) + } + + /// Clear all data. + fn clear(&mut self) { + self.justifications = ForkTree::new(); + self.pending_requests.clear(); + self.peer_requests.clear(); + self.previous_requests.clear(); + } } /// Relay chain sync strategy. @@ -57,7 +321,13 @@ pub struct ChainSync { best_queued_number: NumberFor, best_queued_hash: B::Hash, required_block_attributes: message::BlockAttributes, - import_queue: Arc>, + justifications: PendingJustifications, + import_queue: Box>, + queue_blocks: HashSet, + best_importing_number: NumberFor, + is_stopping: AtomicBool, + is_offline: Arc, + is_major_syncing: Arc, } /// Reported sync state. @@ -76,6 +346,8 @@ pub struct Status { pub state: SyncState, /// Target sync block number. pub best_seen_block: Option>, + /// Number of peers participating in syncing. + pub num_peers: u32, } impl Status { @@ -87,11 +359,22 @@ impl Status { SyncState::Downloading => true, } } + + /// Are we all alone? + pub fn is_offline(&self) -> bool { + self.num_peers == 0 + } } impl ChainSync { /// Create a new instance. - pub(crate) fn new(role: Roles, info: &ClientInfo, import_queue: Arc>) -> Self { + pub(crate) fn new( + is_offline: Arc, + is_major_syncing: Arc, + role: Roles, + info: &ClientInfo, + import_queue: Box> + ) -> Self { let mut required_block_attributes = message::BlockAttributes::HEADER | message::BlockAttributes::JUSTIFICATION; if role.intersects(Roles::FULL | Roles::AUTHORITY) { required_block_attributes |= message::BlockAttributes::BODY; @@ -103,8 +386,14 @@ impl ChainSync { blocks: BlockCollection::new(), best_queued_hash: info.best_queued_hash.unwrap_or(info.chain.best_hash), best_queued_number: info.best_queued_number.unwrap_or(info.chain.best_number), + justifications: PendingJustifications::new(), required_block_attributes, import_queue, + queue_blocks: Default::default(), + best_importing_number: Zero::zero(), + is_stopping: Default::default(), + is_offline, + is_major_syncing, } } @@ -112,60 +401,82 @@ impl ChainSync { self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number) } - /// Returns import queue reference. - pub(crate) fn import_queue(&self) -> Arc> { - self.import_queue.clone() + fn state(&self, best_seen: &Option>) -> SyncState { + match best_seen { + &Some(n) if n > self.best_queued_number && n - self.best_queued_number > As::sa(5) => SyncState::Downloading, + _ => SyncState::Idle, + } } /// Returns sync status. pub(crate) fn status(&self) -> Status { let best_seen = self.best_seen_block(); - let state = match &best_seen { - &Some(n) if n > self.best_queued_number && n - self.best_queued_number > As::sa(5) => SyncState::Downloading, - _ => SyncState::Idle, - }; + let state = self.state(&best_seen); Status { state: state, best_seen_block: best_seen, + num_peers: self.peers.len() as u32, } } /// Handle new connected peer. pub(crate) fn new_peer(&mut self, protocol: &mut Context, who: NodeIndex) { + // Initialize some variables to determine if + // is_offline or is_major_syncing should be updated + // after processing this new peer. + let previous_len = self.peers.len(); + let previous_best_seen = self.best_seen_block(); + let previous_state = self.state(&previous_best_seen); + if let Some(info) = protocol.peer_info(who) { - match (block_status(&*protocol.client(), &*self.import_queue, info.best_hash), info.best_number) { + let status = block_status(&*protocol.client(), &self.queue_blocks, info.best_hash); + match (status, info.best_number) { (Err(e), _) => { debug!(target:"sync", "Error reading blockchain: {:?}", e); - protocol.report_peer(who, Severity::Useless(&format!("Error legimimately reading blockchain status: {:?}", e))); + let reason = format!("Error legimimately reading blockchain status: {:?}", e); + protocol.report_peer(who, Severity::Useless(reason)); }, (Ok(BlockStatus::KnownBad), _) => { - protocol.report_peer(who, Severity::Bad(&format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number))); + let reason = format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number); + protocol.report_peer(who, Severity::Bad(reason)); }, (Ok(BlockStatus::Unknown), b) if b == As::sa(0) => { - protocol.report_peer(who, Severity::Bad(&format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number))); + let reason = format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number); + protocol.report_peer(who, Severity::Bad(reason)); }, + (Ok(BlockStatus::Unknown), _) if self.queue_blocks.len() > MAJOR_SYNC_BLOCKS => { + // when actively syncing the common point moves too fast. + debug!(target:"sync", "New peer with unknown best hash {} ({}), assuming common block.", self.best_queued_hash, self.best_queued_number); + self.peers.insert(who, PeerSync { + common_number: self.best_queued_number, + best_hash: info.best_hash, + best_number: info.best_number, + state: PeerSyncState::Available, + recently_announced: Default::default(), + }); + } (Ok(BlockStatus::Unknown), _) => { let our_best = self.best_queued_number; if our_best > As::sa(0) { let common_best = ::std::cmp::min(our_best, info.best_number); debug!(target:"sync", "New peer with unknown best hash {} ({}), searching for common ancestor.", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: self.genesis_hash, common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, - state: PeerSyncState::AncestorSearch(common_best), + state: PeerSyncState::AncestorSearch(common_best, AncestorSearchState::ExponentialBackoff(As::sa(1))), + recently_announced: Default::default(), }); Self::request_ancestry(protocol, who, common_best) } else { // We are at genesis, just start downloading debug!(target:"sync", "New peer with best hash {} ({}).", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: self.genesis_hash, common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, state: PeerSyncState::Available, + recently_announced: Default::default(), }); self.download_new(protocol, who) } @@ -173,123 +484,321 @@ impl ChainSync { (Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChain), _) => { debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: info.best_hash, common_number: info.best_number, best_hash: info.best_hash, best_number: info.best_number, state: PeerSyncState::Available, + recently_announced: Default::default(), }); } } } + + let current_best_seen = self.best_seen_block(); + let current_state = self.state(¤t_best_seen); + let current_len = self.peers.len(); + if previous_len == 0 && current_len > 0 { + // We were offline, and now we're connected to at least one peer. + self.is_offline.store(false, Ordering::Relaxed); + } + if previous_len < current_len { + // We added a peer, let's see if major_syncing should be updated. + match (previous_state, current_state) { + (SyncState::Idle, SyncState::Downloading) => self.is_major_syncing.store(true, Ordering::Relaxed), + (SyncState::Downloading, SyncState::Idle) => self.is_major_syncing.store(false, Ordering::Relaxed), + _ => {}, + } + } + } + + fn handle_ancestor_search_state( + state: AncestorSearchState, + curr_block_num: NumberFor, + block_hash_match: bool, + ) -> Option<(AncestorSearchState, NumberFor)> { + match state { + AncestorSearchState::ExponentialBackoff(next_distance_to_tip) => { + if block_hash_match && next_distance_to_tip == As::sa(1) { + // We found the ancestor in the first step so there is no need to execute binary search. + return None; + } + if block_hash_match { + let left = curr_block_num; + let right = left + next_distance_to_tip / As::sa(2); + let middle = left + (right - left) / As::sa(2); + Some((AncestorSearchState::BinarySearch(left, right), middle)) + } else { + let next_block_num = curr_block_num.checked_sub(&next_distance_to_tip).unwrap_or(As::sa(0)); + let next_distance_to_tip = next_distance_to_tip * As::sa(2); + Some((AncestorSearchState::ExponentialBackoff(next_distance_to_tip), next_block_num)) + } + }, + AncestorSearchState::BinarySearch(mut left, mut right) => { + if left >= curr_block_num { + return None; + } + if block_hash_match { + left = curr_block_num; + } else { + right = curr_block_num; + } + assert!(right >= left); + let middle = left + (right - left) / As::sa(2); + Some((AncestorSearchState::BinarySearch(left, right), middle)) + }, + } } + /// Handle new block data. pub(crate) fn on_block_data( &mut self, protocol: &mut Context, who: NodeIndex, - _request: message::BlockRequest, + request: message::BlockRequest, response: message::BlockResponse - ) -> Option<(BlockOrigin, Vec>)> { - let new_blocks = if let Some(ref mut peer) = self.peers.get_mut(&who) { - match peer.state { + ) { + let new_blocks: Vec> = if let Some(ref mut peer) = self.peers.get_mut(&who) { + let mut blocks = response.blocks; + if request.direction == message::Direction::Descending { + trace!(target: "sync", "Reversing incoming block list"); + blocks.reverse(); + } + let peer_state = peer.state.clone(); + match peer_state { PeerSyncState::DownloadingNew(start_block) => { self.blocks.clear_peer_download(who); peer.state = PeerSyncState::Available; - - self.blocks.insert(start_block, response.blocks, who); - self.blocks.drain(self.best_queued_number + As::sa(1)) + self.blocks.insert(start_block, blocks, who); + self.blocks + .drain(self.best_queued_number + As::sa(1)) + .into_iter() + .map(|block_data| { + IncomingBlock { + hash: block_data.block.hash, + header: block_data.block.header, + body: block_data.block.body, + justification: block_data.block.justification, + origin: block_data.origin, + } + }).collect() }, PeerSyncState::DownloadingStale(_) => { peer.state = PeerSyncState::Available; - response.blocks.into_iter().map(|b| blocks::BlockData { - origin: Some(who), - block: b + blocks.into_iter().map(|b| { + IncomingBlock { + hash: b.hash, + header: b.header, + body: b.body, + justification: b.justification, + origin: Some(who), + } }).collect() }, - PeerSyncState::AncestorSearch(n) => { - match response.blocks.get(0) { - Some(ref block) => { - trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", n, block.hash, who); - match protocol.client().block_hash(n) { - Ok(Some(block_hash)) if block_hash == block.hash => { - if peer.common_number < n { - peer.common_hash = block.hash; - peer.common_number = n; - } - peer.state = PeerSyncState::Available; - trace!(target:"sync", "Found common ancestor for peer {}: {} ({})", who, block.hash, n); - vec![] - }, - Ok(our_best) if n > As::sa(0) => { - trace!(target:"sync", "Ancestry block mismatch for peer {}: theirs: {} ({}), ours: {:?}", who, block.hash, n, our_best); - let n = n - As::sa(1); - peer.state = PeerSyncState::AncestorSearch(n); - Self::request_ancestry(protocol, who, n); - return None; - }, - Ok(_) => { // genesis mismatch - trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); - protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer")); - return None; - }, - Err(e) => { - protocol.report_peer(who, Severity::Useless(&format!("Error answering legitimate blockchain query: {:?}", e))); - return None; - } - } + PeerSyncState::AncestorSearch(num, state) => { + let block_hash_match = match (blocks.get(0), protocol.client().block_hash(num)) { + (Some(ref block), Ok(maybe_our_block_hash)) => { + trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", num, block.hash, who); + maybe_our_block_hash.map_or(false, |x| x == block.hash) }, - None => { + (None, _) => { trace!(target:"sync", "Invalid response when searching for ancestor from {}", who); - protocol.report_peer(who, Severity::Bad("Invalid response when searching for ancestor")); - return None; - } + protocol.report_peer(who, Severity::Bad("Invalid response when searching for ancestor".to_string())); + return; + }, + (_, Err(e)) => { + let reason = format!("Error answering legitimate blockchain query: {:?}", e); + protocol.report_peer(who, Severity::Useless(reason)); + return; + }, + }; + if block_hash_match && peer.common_number < num { + peer.common_number = num; + } + if !block_hash_match && num == As::sa(0) { + trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); + protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer".to_string())); + return; + } + if let Some((next_state, next_block_num)) = Self::handle_ancestor_search_state(state, num, block_hash_match) { + peer.state = PeerSyncState::AncestorSearch(next_block_num, next_state); + Self::request_ancestry(protocol, who, next_block_num); + return; + } else { + peer.state = PeerSyncState::Available; + vec![] } }, - PeerSyncState::Available => Vec::new(), + PeerSyncState::Available | PeerSyncState::DownloadingJustification(..) => Vec::new(), } } else { - vec![] + Vec::new() }; - let best_seen = self.best_seen_block(); - let is_best = new_blocks.first().and_then(|b| b.block.header.as_ref()).map(|h| best_seen.as_ref().map_or(false, |n| h.number() >= n)); - let origin = if is_best.unwrap_or_default() { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync }; + let is_recent = new_blocks + .first() + .map(|block| self.peers.iter().any(|(_, peer)| peer.recently_announced.contains(&block.hash))) + .unwrap_or(false); + let origin = if is_recent { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync }; if let Some((hash, number)) = new_blocks.last() - .and_then(|b| b.block.header.as_ref().map(|h| (b.block.hash.clone(), *h.number()))) + .and_then(|b| b.header.as_ref().map(|h| (b.hash.clone(), *h.number()))) { + trace!(target:"sync", "Accepted {} blocks ({:?}) with origin {:?}", new_blocks.len(), hash, origin); self.block_queued(&hash, number); } self.maintain_sync(protocol); - Some((origin, new_blocks)) + let new_best_importing_number = new_blocks + .last() + .and_then(|b| b.header.as_ref().map(|h| h.number().clone())) + .unwrap_or_else(|| Zero::zero()); + self.queue_blocks + .extend(new_blocks.iter().map(|b| b.hash.clone())); + self.best_importing_number = max(new_best_importing_number, self.best_importing_number); + self.import_queue.import_blocks(origin, new_blocks); } + /// Handle new justification data. + pub(crate) fn on_block_justification_data( + &mut self, + protocol: &mut Context, + who: NodeIndex, + _request: message::BlockRequest, + response: message::BlockResponse, + ) { + if let Some(ref mut peer) = self.peers.get_mut(&who) { + if let PeerSyncState::DownloadingJustification(hash) = peer.state { + peer.state = PeerSyncState::Available; + + // we only request one justification at a time + match response.blocks.into_iter().next() { + Some(response) => { + if hash != response.hash { + let msg = format!( + "Invalid block justification provided: requested: {:?} got: {:?}", + hash, + response.hash, + ); + + protocol.report_peer(who, Severity::Bad(msg)); + return; + } + + self.justifications.on_response( + who, + response.justification, + &*self.import_queue, + ); + }, + None => { + // we might have asked the peer for a justification on a block that we thought it had + // (regardless of whether it had a justification for it or not). + trace!(target: "sync", "Peer {:?} provided empty response for justification request {:?}", + who, + hash, + ); + return; + }, + } + } + } + + self.maintain_sync(protocol); + } + + /// A batch of blocks have been processed, with or without errors. + pub fn blocks_processed(&mut self, processed_blocks: Vec, has_error: bool) { + for hash in processed_blocks { + self.queue_blocks.remove(&hash); + } + if has_error { + self.best_importing_number = Zero::zero(); + } + } + + /// Maintain the sync process (download new blocks, fetch justifications). pub fn maintain_sync(&mut self, protocol: &mut Context) { + if self.is_stopping.load(Ordering::SeqCst) { + return + } let peers: Vec = self.peers.keys().map(|p| *p).collect(); for peer in peers { self.download_new(protocol, peer); } + self.justifications.dispatch(&mut self.peers, protocol); + } + + /// Called periodically to perform any time-based actions. + pub fn tick(&mut self, protocol: &mut Context) { + self.justifications.dispatch(&mut self.peers, protocol); + } + + /// Request a justification for the given block. + /// + /// Queues a new justification request and tries to dispatch all pending requests. + pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor, protocol: &mut Context) { + self.justifications.queue_request( + &(*hash, number), + |base, block| protocol.client().is_descendent_of(base, block), + ); + + self.justifications.dispatch(&mut self.peers, protocol); + } + + /// Clears all pending justification requests. + pub fn clear_justification_requests(&mut self) { + self.justifications.clear(); + } + + pub fn justification_import_result(&mut self, hash: B::Hash, number: NumberFor, success: bool) { + self.justifications.justification_import_result(hash, number, success); + } + + pub fn stop(&self) { + self.is_stopping.store(true, Ordering::SeqCst); + self.import_queue.stop(); } + /// Notify about successful import of the given block. pub fn block_imported(&mut self, hash: &B::Hash, number: NumberFor) { trace!(target: "sync", "Block imported successfully {} ({})", number, hash); } + /// Notify about finalization of the given block. + pub fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor, protocol: &mut Context) { + if let Err(err) = self.justifications.on_block_finalized( + hash, + number, + |base, block| protocol.client().is_descendent_of(base, block), + ) { + warn!(target: "sync", "Error cleaning up pending justification requests: {:?}", err); + }; + } + fn block_queued(&mut self, hash: &B::Hash, number: NumberFor) { + let best_seen = self.best_seen_block(); + let previous_state = self.state(&best_seen); if number > self.best_queued_number { self.best_queued_number = number; self.best_queued_hash = *hash; } + let current_state = self.state(&best_seen); + // If the latest queued block changed our state, update is_major_syncing. + match (previous_state, current_state) { + (SyncState::Idle, SyncState::Downloading) => self.is_major_syncing.store(true, Ordering::Relaxed), + (SyncState::Downloading, SyncState::Idle) => self.is_major_syncing.store(false, Ordering::Relaxed), + _ => {}, + } // Update common blocks - for (_, peer) in self.peers.iter_mut() { - trace!(target: "sync", "Updating peer info ours={}, theirs={}", number, peer.best_number); + for (n, peer) in self.peers.iter_mut() { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + // Abort search. + peer.state = PeerSyncState::Available; + } + trace!(target: "sync", "Updating peer {} info, ours={}, common={}, their best={}", n, number, peer.common_number, peer.best_number); if peer.best_number >= number { peer.common_number = number; - peer.common_hash = *hash; } else { peer.common_number = peer.best_number; - peer.common_hash = peer.best_hash; } } } @@ -299,25 +808,43 @@ impl ChainSync { self.block_queued(&hash, best_header.number().clone()) } + /// Handle new block announcement. pub(crate) fn on_block_announce(&mut self, protocol: &mut Context, who: NodeIndex, hash: B::Hash, header: &B::Header) { let number = *header.number(); + if number <= As::sa(0) { + trace!(target: "sync", "Ignored invalid block announcement from {}: {}", who, hash); + return; + } + let known_parent = self.is_known(protocol, &header.parent_hash()); + let known = self.is_known(protocol, &hash); if let Some(ref mut peer) = self.peers.get_mut(&who) { + while peer.recently_announced.len() >= ANNOUNCE_HISTORY_SIZE { + peer.recently_announced.pop_front(); + } + peer.recently_announced.push_back(hash.clone()); if number > peer.best_number { + // update their best block peer.best_number = number; peer.best_hash = hash; } - if number <= self.best_queued_number && number > peer.common_number { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + return; + } + if header.parent_hash() == &self.best_queued_hash || known_parent { + peer.common_number = number - As::sa(1); + } else if known { peer.common_number = number } } else { return; } - if !self.is_known_or_already_downloading(protocol, &hash) { + if !(known || self.is_already_downloading(&hash)) { let stale = number <= self.best_queued_number; if stale { - if !self.is_known_or_already_downloading(protocol, header.parent_hash()) { - trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", who, hash, header); + if !(known_parent || self.is_already_downloading(header.parent_hash())) { + trace!(target: "sync", "Considering new unknown stale block announced from {}: {} {:?}", who, hash, header); + self.download_unknown_stale(protocol, who, &hash); } else { trace!(target: "sync", "Considering new stale block announced from {}: {} {:?}", who, hash, header); self.download_stale(protocol, who, &hash); @@ -331,24 +858,40 @@ impl ChainSync { } } - fn is_known_or_already_downloading(&self, protocol: &mut Context, hash: &B::Hash) -> bool { + fn is_already_downloading(&self, hash: &B::Hash) -> bool { self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash)) - || block_status(&*protocol.client(), &*self.import_queue, *hash).ok().map_or(false, |s| s != BlockStatus::Unknown) } + fn is_known(&self, protocol: &mut Context, hash: &B::Hash) -> bool { + block_status(&*protocol.client(), &self.queue_blocks, *hash).ok().map_or(false, |s| s != BlockStatus::Unknown) + } + + /// Handle disconnected peer. pub(crate) fn peer_disconnected(&mut self, protocol: &mut Context, who: NodeIndex) { + let previous_best_seen = self.best_seen_block(); + let previous_state = self.state(&previous_best_seen); self.blocks.clear_peer_download(who); self.peers.remove(&who); + if self.peers.len() == 0 { + // We're not connected to any peer anymore. + self.is_offline.store(true, Ordering::Relaxed); + } + let current_best_seen = self.best_seen_block(); + let current_state = self.state(¤t_best_seen); + // We removed a peer, let's see if this put us in idle state and is_major_syncing should be updated. + match (previous_state, current_state) { + (SyncState::Downloading, SyncState::Idle) => self.is_major_syncing.store(false, Ordering::Relaxed), + _ => {}, + } + self.justifications.peer_disconnected(who); self.maintain_sync(protocol); } + /// Restart the sync process. pub(crate) fn restart(&mut self, protocol: &mut Context) { - self.import_queue.clear(); + self.queue_blocks.clear(); + self.best_importing_number = Zero::zero(); self.blocks.clear(); - let ids: Vec = self.peers.keys().map(|p| *p).collect(); - for id in ids { - self.new_peer(protocol, id); - } match protocol.client().info() { Ok(info) => { self.best_queued_hash = info.best_queued_hash.unwrap_or(info.chain.best_hash); @@ -361,14 +904,19 @@ impl ChainSync { self.best_queued_number = As::sa(0); } } + let ids: Vec = self.peers.drain().map(|(id, _)| id).collect(); + for id in ids { + self.new_peer(protocol, id); + } } + /// Clear all sync data. pub(crate) fn clear(&mut self) { self.blocks.clear(); self.peers.clear(); } - // Download old block. + // Download old block with known parent. fn download_stale(&mut self, protocol: &mut Context, who: NodeIndex, hash: &B::Hash) { if let Some(ref mut peer) = self.peers.get_mut(&who) { match peer.state { @@ -389,12 +937,32 @@ impl ChainSync { } } + // Download old block with unknown parent. + fn download_unknown_stale(&mut self, protocol: &mut Context, who: NodeIndex, hash: &B::Hash) { + if let Some(ref mut peer) = self.peers.get_mut(&who) { + match peer.state { + PeerSyncState::Available => { + let request = message::generic::BlockRequest { + id: 0, + fields: self.required_block_attributes.clone(), + from: message::FromBlock::Hash(*hash), + to: None, + direction: message::Direction::Descending, + max: Some(MAX_UNKNOWN_FORK_DOWNLOAD_LEN), + }; + peer.state = PeerSyncState::DownloadingStale(*hash); + protocol.send_message(who, GenericMessage::BlockRequest(request)); + }, + _ => (), + } + } + } + // Issue a request for a peer to download new blocks, if any are available fn download_new(&mut self, protocol: &mut Context, who: NodeIndex) { if let Some(ref mut peer) = self.peers.get_mut(&who) { - let import_status = self.import_queue.status(); // when there are too many blocks in the queue => do not try to download new blocks - if import_status.importing_count > MAX_IMPORTING_BLOCKS { + if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { trace!(target: "sync", "Too many blocks in the queue."); return; } @@ -438,11 +1006,11 @@ impl ChainSync { /// Get block status, taking into account import queue. fn block_status( - chain: &::chain::Client, - queue: &ImportQueue, + chain: &crate::chain::Client, + queue_blocks: &HashSet, hash: B::Hash) -> Result { - if queue.is_importing(&hash) { + if queue_blocks.contains(&hash) { return Ok(BlockStatus::Queued); } diff --git a/core/network/src/test/block_import.rs b/core/network/src/test/block_import.rs new file mode 100644 index 0000000000000000000000000000000000000000..0916d698c3fc9d869c04b045cde59615a7569a56 --- /dev/null +++ b/core/network/src/test/block_import.rs @@ -0,0 +1,83 @@ +// 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 . + +//! Testing block import logic. + +use consensus::import_queue::{import_single_block, BasicQueue, BlockImportError, BlockImportResult}; +use test_client::{self, TestClient}; +use test_client::runtime::{Block, Hash}; +use runtime_primitives::generic::BlockId; +use super::*; + +struct TestLink {} + +impl Link for TestLink {} + +fn prepare_good_block() -> (client::Client, Hash, u64, IncomingBlock) { + let client = test_client::new(); + let block = client.new_block().unwrap().bake().unwrap(); + client.import(BlockOrigin::File, block).unwrap(); + + let (hash, number) = (client.block_hash(1).unwrap().unwrap(), 1); + let header = client.header(&BlockId::Number(1)).unwrap(); + let justification = client.justification(&BlockId::Number(1)).unwrap(); + (client, hash, number, IncomingBlock { + hash, + header, + body: None, + justification, + origin: Some(0) + }) +} + +#[test] +fn import_single_good_block_works() { + let (_, _hash, number, block) = prepare_good_block(); + assert_eq!( + import_single_block(&test_client::new(), BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), + Ok(BlockImportResult::ImportedUnknown(number, Default::default(), Some(0))) + ); +} + +#[test] +fn import_single_good_known_block_is_ignored() { + let (client, _hash, number, block) = prepare_good_block(); + assert_eq!( + import_single_block(&client, BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), + Ok(BlockImportResult::ImportedKnown(number)) + ); +} + +#[test] +fn import_single_good_block_without_header_fails() { + let (_, _, _, mut block) = prepare_good_block(); + block.header = None; + assert_eq!( + import_single_block(&test_client::new(), BlockOrigin::File, block, Arc::new(PassThroughVerifier(true))), + Err(BlockImportError::IncompleteHeader(Some(0))) + ); +} + +#[test] +fn async_import_queue_drops() { + // Perform this test multiple times since it exhibits non-deterministic behavior. + for _ in 0..100 { + let verifier = Arc::new(PassThroughVerifier(true)); + let queue = BasicQueue::new(verifier, Arc::new(test_client::new()), None); + queue.start(Box::new(TestLink{})).unwrap(); + drop(queue); + } +} diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index f8b67051646ab43819c70a9e53a3cb2113261ca8..24e05daec097e640ec9a8e906b4fd2ccb853100e 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,54 +16,91 @@ #![allow(missing_docs)] +#[cfg(test)] +mod block_import; #[cfg(test)] mod sync; -use std::collections::{VecDeque, HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread; +use std::time::Duration; -use parking_lot::RwLock; +use log::trace; use client; -use client::error::Error as ClientError; use client::block_builder::BlockBuilder; +use crate::config::ProtocolConfig; +use consensus::import_queue::{BasicQueue, ImportQueue, IncomingBlock}; +use consensus::import_queue::{Link, SharedBlockImport, SharedJustificationImport, Verifier}; +use consensus::{Error as ConsensusError, ErrorKind as ConsensusErrorKind}; +use consensus::{BlockOrigin, ForkChoiceStrategy, ImportBlock, JustificationImport}; +use crate::consensus_gossip::ConsensusGossip; +use crossbeam_channel::{self as channel, Sender, select}; +use futures::Future; +use futures::sync::{mpsc, oneshot}; +use crate::message::{Message, ConsensusEngineId}; +use network_libp2p::{NodeIndex, ProtocolId, PeerId}; +use parity_codec::Encode; +use parking_lot::{Mutex, RwLock}; +use primitives::{H256, ed25519::Public as AuthorityId}; +use crate::protocol::{ConnectedPeer, Context, FromNetworkMsg, Protocol, ProtocolMsg}; use runtime_primitives::generic::BlockId; -use io::SyncIo; -use protocol::{Context, Protocol, ProtocolContext}; -use config::ProtocolConfig; -use service::TransactionPool; -use network_libp2p::{NodeIndex, PeerId, Severity}; -use keyring::Keyring; -use codec::Encode; -use import_queue::{SyncImportQueue, PassThroughVerifier, Verifier}; -use consensus::BlockOrigin; -use specialization::NetworkSpecialization; -use consensus_gossip::ConsensusGossip; -use import_queue::{BlockImport, ImportQueue}; -use service::ExecuteInContext; -use test_client; - -pub use test_client::runtime::{Block, Hash, Transfer, Extrinsic}; -pub use test_client::TestClient; +use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor}; +use runtime_primitives::Justification; +use crate::service::{network_channel, NetworkChan, NetworkLink, NetworkMsg, NetworkPort, TransactionPool}; +use crate::specialization::NetworkSpecialization; +use test_client::{self, AccountKeyring}; -struct DummyContextExecutor(Arc>, Arc>>); -unsafe impl Send for DummyContextExecutor {} -unsafe impl Sync for DummyContextExecutor {} +pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; +pub use test_client::TestClient; -impl ExecuteInContext for DummyContextExecutor { - fn execute_in_context)>(&self, closure: F) { - let mut io = TestIo::new(&self.1, None); - let mut context = ProtocolContext::new(&self.0.context_data(), &mut io); - closure(&mut context); +#[cfg(any(test, feature = "test-helpers"))] +/// A Verifier that accepts all blocks and passes them on with the configured +/// finality to be imported. +pub struct PassThroughVerifier(pub bool); + +#[cfg(any(test, feature = "test-helpers"))] +/// This Verifiyer accepts all data as valid +impl Verifier for PassThroughVerifier { + fn verify( + &self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + body: Option> + ) -> Result<(ImportBlock, Option>>), String> { + let new_authorities = header.digest().log(DigestItem::as_authorities_change) + .map(|auth| auth.iter().cloned().collect()); + + Ok((ImportBlock { + origin, + header, + body, + finalized: self.0, + justification, + post_digests: vec![], + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }, new_authorities)) } } +/// A link implementation that does nothing. +pub struct NoopLink { } + +impl Link for NoopLink { } + /// The test specialization. -pub struct DummySpecialization { } +#[derive(Clone)] +pub struct DummySpecialization; impl NetworkSpecialization for DummySpecialization { - fn status(&self) -> Vec { vec![] } + fn status(&self) -> Vec { + vec![] + } - fn on_connect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex, _status: ::message::Status) { + fn on_connect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex, _status: crate::message::Status) { } fn on_disconnect(&mut self, _ctx: &mut Context, _peer_id: NodeIndex) { @@ -73,222 +110,373 @@ impl NetworkSpecialization for DummySpecialization { &mut self, _ctx: &mut Context, _peer_id: NodeIndex, - _message: &mut Option<::message::Message> + _message: &mut Option>, ) { } } -pub struct TestIo<'p> { - queue: &'p RwLock>, - pub to_disconnect: HashSet, - packets: Vec, - _sender: Option, +pub type PeersClient = client::Client; + +#[derive(Clone)] +/// A Link that can wait for a block to have been imported. +pub struct TestLink + Clone> { + import_done: Arc, + hash: Arc>, + link: NetworkLink, } -impl<'p> TestIo<'p> where { - pub fn new(queue: &'p RwLock>, sender: Option) -> TestIo<'p> { - TestIo { - queue: queue, - _sender: sender, - to_disconnect: HashSet::new(), - packets: Vec::new(), +impl + Clone> TestLink { + fn new( + protocol_sender: Sender>, + network_sender: NetworkChan + ) -> TestLink { + TestLink { + import_done: Arc::new(AtomicBool::new(false)), + hash: Arc::new(Mutex::new(Default::default())), + link: NetworkLink { + protocol_sender, + network_sender, + } } } -} -impl<'p> Drop for TestIo<'p> { - fn drop(&mut self) { - self.queue.write().extend(self.packets.drain(..)); + /// Set the hash which will be awaited for import. + fn with_hash(&self, hash: Hash) { + self.import_done.store(false, Ordering::SeqCst); + *self.hash.lock() = hash; + } + + /// Simulate a synchronous import. + fn wait_for_import(&self) { + while !self.import_done.load(Ordering::SeqCst) { + thread::sleep(Duration::from_millis(20)); + } } } -impl<'p> SyncIo for TestIo<'p> { - fn report_peer(&mut self, who: NodeIndex, _reason: Severity) { - self.to_disconnect.insert(who); +impl + Clone> Link for TestLink { + fn block_imported(&self, hash: &Hash, number: NumberFor) { + if hash == &*self.hash.lock() { + self.import_done.store(true, Ordering::SeqCst); + } + self.link.block_imported(hash, number); } - fn send(&mut self, who: NodeIndex, data: Vec) { - self.packets.push(TestPacket { - data: data, - recipient: who, - }); + fn blocks_processed(&self, processed_blocks: Vec, has_error: bool) { + self.link.blocks_processed(processed_blocks, has_error); } - fn peer_debug_info(&self, _who: NodeIndex) -> String { - "unknown".to_string() + fn justification_imported(&self, who: NodeIndex, hash: &Hash, number:NumberFor, success: bool) { + self.link.justification_imported(who, hash, number, success); } - fn peer_id(&self, _peer_id: NodeIndex) -> Option { - None + fn request_justification(&self, hash: &Hash, number: NumberFor) { + self.link.request_justification(hash, number); } -} -/// Mocked subprotocol packet -pub struct TestPacket { - data: Vec, - recipient: NodeIndex, -} + fn useless_peer(&self, who: NodeIndex, reason: &str) { + self.link.useless_peer(who, reason); + } -pub type PeersClient = client::Client; + fn note_useless_and_restart_sync(&self, who: NodeIndex, reason: &str) { + self.link.note_useless_and_restart_sync(who, reason); + } -pub struct Peer, D> { + fn restart(&self) { + self.link.restart(); + } +} + +pub struct Peer + Clone> { + pub is_offline: Arc, + pub is_major_syncing: Arc, + pub peers: Arc>>>, client: Arc, - pub sync: Arc>, - pub queue: Arc>>, - import_queue: Arc>, - executor: Arc, - /// Some custom data set up at initialization time. + network_to_protocol_sender: Sender>, + pub protocol_sender: Sender>, + network_link: TestLink, + network_port: Arc>>, + pub import_queue: Box>, pub data: D, + best_hash: Mutex>, + finalized_hash: Mutex>, } -impl, D> Peer { +impl + Clone> Peer { fn new( + is_offline: Arc, + is_major_syncing: Arc, + peers: Arc>>>, client: Arc, - sync: Arc>, - queue: Arc>>, - import_queue: Arc>, + import_queue: Box>, + network_to_protocol_sender: Sender>, + protocol_sender: Sender>, + network_sender: NetworkChan, + network_port: NetworkPort, data: D, ) -> Self { - let executor = Arc::new(DummyContextExecutor(sync.clone(), queue.clone())); - Peer { client, sync, queue, import_queue, executor, data } + let network_port = Arc::new(Mutex::new(network_port)); + let network_link = TestLink::new(protocol_sender.clone(), network_sender.clone()); + import_queue.start(Box::new(network_link.clone())).expect("Test ImportQueue always starts"); + Peer { + is_offline, + is_major_syncing, + peers, + client, + network_to_protocol_sender, + protocol_sender, + import_queue, + network_link, + network_port, + data, + best_hash: Mutex::new(None), + finalized_hash: Mutex::new(None), + } } /// Called after blockchain has been populated to updated current state. fn start(&self) { // Update the sync state to the latest chain state. let info = self.client.info().expect("In-mem client does not fail"); - let header = self.client.header(&BlockId::Hash(info.chain.best_hash)).unwrap().unwrap(); - let network_link = ::import_queue::NetworkLink { - sync: Arc::downgrade(self.sync.sync()), - context: Arc::downgrade(&self.executor), - }; + let header = self + .client + .header(&BlockId::Hash(info.chain.best_hash)) + .unwrap() + .unwrap(); + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockImported(info.chain.best_hash, header)); + } + + pub fn on_block_imported( + &self, + hash: ::Hash, + header: &::Header, + ) { + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockImported(hash, header.clone())); + } - self.import_queue.start(network_link).expect("Test ImportQueue always starts"); - self.sync.on_block_imported(&mut TestIo::new(&self.queue, None), info.chain.best_hash, &header); + // SyncOracle: are we connected to any peer? + fn is_offline(&self) -> bool { + self.is_offline.load(Ordering::Relaxed) } - /// Called on connection to other indicated peer. - fn on_connect(&self, other: NodeIndex) { - self.sync.on_peer_connected(&mut TestIo::new(&self.queue, Some(other)), other); + // SyncOracle: are we in the process of catching-up with the chain? + fn is_major_syncing(&self) -> bool { + self.is_major_syncing.load(Ordering::Relaxed) } - pub fn consensus_gossip(&self) -> &RwLock> { - self.sync.consensus_gossip() + /// Called on connection to other indicated peer. + fn on_connect(&self, other: NodeIndex) { + let _ = self.network_to_protocol_sender.send(FromNetworkMsg::PeerConnected(PeerId::random(), other, String::new())); } /// Called on disconnect from other indicated peer. fn on_disconnect(&self, other: NodeIndex) { - let mut io = TestIo::new(&self.queue, Some(other)); - self.sync.on_peer_disconnected(&mut io, other); + let _ = self + .network_to_protocol_sender + .send(FromNetworkMsg::PeerDisconnected(other, String::new())); } /// Receive a message from another peer. Return a set of peers to disconnect. - fn receive_message(&self, from: NodeIndex, msg: TestPacket) -> HashSet { - let mut io = TestIo::new(&self.queue, Some(from)); - self.sync.handle_packet(&mut io, from, &msg.data); - self.flush(); - io.to_disconnect.clone() + fn receive_message(&self, from: NodeIndex, msg: Message) { + let _ = self + .network_to_protocol_sender + .send(FromNetworkMsg::CustomMessage(from, msg)); } - #[cfg(test)] - fn with_io<'a, F, U>(&'a self, f: F) -> U where F: FnOnce(&mut TestIo<'a>) -> U { - let mut io = TestIo::new(&self.queue, None); - f(&mut io) + /// Produce the next pending message to send to another peer. + fn pending_message(&self) -> Option> { + select! { + recv(self.network_port.lock().receiver()) -> msg => return msg.ok(), + // If there are no messages ready, give protocol a change to send one. + recv(channel::after(Duration::from_millis(100))) -> _ => return None, + } } - /// Produce the next pending message to send to another peer. - fn pending_message(&self) -> Option { - self.flush(); - self.queue.write().pop_front() + /// Produce the next pending message to send to another peer, without waiting. + fn pending_message_fast(&self) -> Option> { + self.network_port.lock().receiver().try_recv().ok() } /// Whether this peer is done syncing (has no messages to send). fn is_done(&self) -> bool { - self.queue.read().is_empty() + self.network_port.lock().receiver().is_empty() } /// Execute a "sync step". This is called for each peer after it sends a packet. fn sync_step(&self) { - self.flush(); - self.sync.tick(&mut TestIo::new(&self.queue, None)); + let _ = self.protocol_sender.send(ProtocolMsg::Tick); } /// Send block import notifications. fn send_import_notifications(&self) { let info = self.client.info().expect("In-mem client does not fail"); + + let mut best_hash = self.best_hash.lock(); + match *best_hash { + None => {}, + Some(hash) if hash != info.chain.best_hash => {}, + _ => return, + } + let header = self.client.header(&BlockId::Hash(info.chain.best_hash)).unwrap().unwrap(); - self.sync.on_block_imported(&mut TestIo::new(&self.queue, None), info.chain.best_hash, &header); + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockImported(info.chain.best_hash, header)); + + *best_hash = Some(info.chain.best_hash); } - /// Restart sync for a peer. - fn restart_sync(&self) { - self.sync.abort(); + /// Send block finalization notifications. + pub fn send_finality_notifications(&self) { + let info = self.client.info().expect("In-mem client does not fail"); + + let mut finalized_hash = self.finalized_hash.lock(); + match *finalized_hash { + None => {}, + Some(hash) if hash != info.chain.finalized_hash => {}, + _ => return, + } + + let header = self.client.header(&BlockId::Hash(info.chain.finalized_hash)).unwrap().unwrap(); + let _ = self + .protocol_sender + .send(ProtocolMsg::BlockFinalized(info.chain.finalized_hash, header.clone())); + + *finalized_hash = Some(info.chain.finalized_hash); } - fn flush(&self) { + /// Restart sync for a peer. + fn restart_sync(&self) { + let _ = self.protocol_sender.send(ProtocolMsg::Abort); } /// Push a message into the gossip network and relay to peers. /// `TestNet::sync_step` needs to be called to ensure it's propagated. - pub fn gossip_message(&self, topic: Hash, data: Vec, broadcast: bool) { - self.sync.gossip_consensus_message(&mut TestIo::new(&self.queue, None), topic, data, broadcast); + pub fn gossip_message(&self, topic: ::Hash, engine_id: ConsensusEngineId, data: Vec) { + let _ = self + .protocol_sender + .send(ProtocolMsg::GossipConsensusMessage(topic, engine_id, data)); + } + + pub fn consensus_gossip_collect_garbage_for_topic(&self, _topic: ::Hash) { + self.with_gossip(move |gossip, _| gossip.collect_garbage()) + } + + /// access the underlying consensus gossip handler + pub fn consensus_gossip_messages_for( + &self, + engine_id: ConsensusEngineId, + topic: ::Hash, + ) -> mpsc::UnboundedReceiver> { + let (tx, rx) = oneshot::channel(); + self.with_gossip(move |gossip, _| { + let inner_rx = gossip.messages_for(engine_id, topic); + let _ = tx.send(inner_rx); + }); + rx.wait().ok().expect("1. Network is running, 2. it should handle the above closure successfully") + } + + /// Execute a closure with the consensus gossip. + pub fn with_gossip(&self, f: F) + where F: FnOnce(&mut ConsensusGossip, &mut Context) + Send + 'static + { + let _ = self + .protocol_sender + .send(ProtocolMsg::ExecuteWithGossip(Box::new(f))); + } + + /// Announce a block to peers. + pub fn announce_block(&self, block: Hash) { + let _ = self.protocol_sender.send(ProtocolMsg::AnnounceBlock(block)); + } + + /// Request a justification for the given block. + #[cfg(test)] + fn request_justification(&self, hash: &::primitives::H256, number: NumberFor) { + let _ = self + .protocol_sender + .send(ProtocolMsg::RequestJustification(hash.clone(), number)); } /// Add blocks to the peer -- edit the block before adding - pub fn generate_blocks(&self, count: usize, origin: BlockOrigin, mut edit_block: F) - where F: FnMut(BlockBuilder) -> Block + pub fn generate_blocks(&self, count: usize, origin: BlockOrigin, edit_block: F) -> H256 + where F: FnMut(BlockBuilder) -> Block { - use blocks::BlockData; + let best_hash = self.client.info().unwrap().chain.best_hash; + self.generate_blocks_at(BlockId::Hash(best_hash), count, origin, edit_block) + } + /// Add blocks to the peer -- edit the block before adding. The chain will + /// start at the given block iD. + pub fn generate_blocks_at(&self, at: BlockId, count: usize, origin: BlockOrigin, mut edit_block: F) -> H256 + where F: FnMut(BlockBuilder) -> Block + { + let mut at = self.client.header(&at).unwrap().unwrap().hash(); for _ in 0..count { - let builder = self.client.new_block().unwrap(); + let builder = self.client.new_block_at(&BlockId::Hash(at)).unwrap(); let block = edit_block(builder); let hash = block.header.hash(); - trace!("Generating {}, (#{}, parent={})", hash, block.header.number, block.header.parent_hash); + trace!( + "Generating {}, (#{}, parent={})", + hash, + block.header.number, + block.header.parent_hash + ); let header = block.header.clone(); - - // NOTE: if we use a non-synchronous queue in the test-net in the future, - // this may not work. - self.import_queue.import_blocks(origin, vec![BlockData { - origin: None, - block: ::message::BlockData:: { + at = hash; + self.network_link.with_hash(hash); + self.import_queue.import_blocks( + origin, + vec![IncomingBlock { + origin: None, hash, header: Some(header), body: Some(block.extrinsics), - receipt: None, - message_queue: None, justification: None, - }, - }]); + }], + ); + // Simulate a sync import. + self.network_link.wait_for_import(); } - + at } /// Push blocks to the peer (simplified: with or without a TX) - pub fn push_blocks(&self, count: usize, with_tx: bool) { + pub fn push_blocks(&self, count: usize, with_tx: bool) -> H256 { + let best_hash = self.client.info().unwrap().chain.best_hash; + self.push_blocks_at(BlockId::Hash(best_hash), count, with_tx) + } + + /// Push blocks to the peer (simplified: with or without a TX) starting from + /// given hash. + pub fn push_blocks_at(&self, at: BlockId, count: usize, with_tx: bool) -> H256 { let mut nonce = 0; if with_tx { - self.generate_blocks(count, BlockOrigin::File, |mut builder| { + self.generate_blocks_at(at, count, BlockOrigin::File, |mut builder| { let transfer = Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Alice.into(), amount: 1, nonce, }; - let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); - builder.push(Extrinsic { transfer, signature }).unwrap(); + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); + builder.push(Extrinsic::Transfer(transfer, signature)).unwrap(); nonce = nonce + 1; builder.bake().unwrap() - }); + }) } else { - self.generate_blocks(count, BlockOrigin::File, |builder| builder.bake().unwrap()); + self.generate_blocks_at(at, count, BlockOrigin::File, |builder| builder.bake().unwrap()) } } - /// Execute a function with specialization for this peer. - pub fn with_spec(&self, f: F) -> U - where F: FnOnce(&mut DummySpecialization, &mut Context) -> U - { - self.sync.with_spec(&mut TestIo::new(&self.queue, None), f) + pub fn push_authorities_change_block(&self, new_authorities: Vec) -> H256 { + self.generate_blocks(1, BlockOrigin::File, |mut builder| { + builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap(); + builder.bake().unwrap() + }) } /// Get a reference to the client. @@ -311,7 +499,18 @@ impl TransactionPool for EmptyTransactionPool { fn on_broadcasted(&self, _: HashMap>) {} } +pub trait SpecializationFactory { + fn create() -> Self; +} + +impl SpecializationFactory for DummySpecialization { + fn create() -> DummySpecialization { + DummySpecialization + } +} + pub trait TestNetFactory: Sized { + type Specialization: NetworkSpecialization + Clone + SpecializationFactory; type Verifier: 'static + Verifier; type PeerData: Default; @@ -319,20 +518,19 @@ pub trait TestNetFactory: Sized { fn from_config(config: &ProtocolConfig) -> Self; fn make_verifier(&self, client: Arc, config: &ProtocolConfig) -> Arc; - /// Get reference to peer. - fn peer(&self, i: usize) -> &Peer; - fn peers(&self) -> &Vec>>; - fn mut_peers>>)>(&mut self, closure: F); + fn peer(&self, i: usize) -> &Peer; + fn peers(&self) -> &Vec>>; + fn mut_peers>>)>(&mut self, closure: F); fn started(&self) -> bool; fn set_started(&mut self, now: bool); /// Get custom block import handle for fresh client, along with peer data. fn make_block_import(&self, client: Arc) - -> (Arc + Send + Sync>, Self::PeerData) + -> (SharedBlockImport, Option>, Self::PeerData) { - (client, Default::default()) + (client, None, Default::default()) } fn default_config() -> ProtocolConfig { @@ -355,29 +553,45 @@ pub trait TestNetFactory: Sized { let client = Arc::new(test_client::new()); let tx_pool = Arc::new(EmptyTransactionPool); let verifier = self.make_verifier(client.clone(), config); - let (block_import, data) = self.make_block_import(client.clone()); - - let import_queue = Arc::new(SyncImportQueue::new(verifier, block_import)); - let specialization = DummySpecialization { }; - let sync = Protocol::new( + let (block_import, justification_import, data) = self.make_block_import(client.clone()); + let (network_sender, network_port) = network_channel(ProtocolId::default()); + + let import_queue = Box::new(BasicQueue::new(verifier, block_import, justification_import)); + let status_sinks = Arc::new(Mutex::new(Vec::new())); + let is_offline = Arc::new(AtomicBool::new(true)); + let is_major_syncing = Arc::new(AtomicBool::new(false)); + let specialization = self::SpecializationFactory::create(); + let peers: Arc>>> = Arc::new(Default::default()); + + let (protocol_sender, network_to_protocol_sender) = Protocol::new( + status_sinks, + is_offline.clone(), + is_major_syncing.clone(), + peers.clone(), + network_sender.clone(), config.clone(), client.clone(), import_queue.clone(), None, tx_pool, - specialization + specialization, ).unwrap(); let peer = Arc::new(Peer::new( + is_offline, + is_major_syncing, + peers, client, - Arc::new(sync), - Arc::new(RwLock::new(VecDeque::new())), import_queue, + network_to_protocol_sender, + protocol_sender, + network_sender, + network_port, data, )); self.mut_peers(|peers| { - peers.push(peer.clone()) + peers.push(peer) }); } @@ -396,44 +610,58 @@ pub trait TestNetFactory: Sized { } } }); + self.route(None); self.set_started(true); } /// Do one step of routing. - fn route(&mut self) { + fn route(&mut self, disconnected: Option>) { self.mut_peers(move |peers| { + let mut to_disconnect = HashSet::new(); for peer in 0..peers.len() { let packet = peers[peer].pending_message(); - if let Some(packet) = packet { - let disconnecting = { - let recipient = packet.recipient; - trace!(target: "sync", "--- {} -> {} ---", peer, recipient); - let to_disconnect = peers[recipient].receive_message(peer as NodeIndex, packet); - for d in &to_disconnect { - // notify this that disconnecting peers are disconnecting - peers[recipient].on_disconnect(*d as NodeIndex); + match packet { + None => continue, + Some(NetworkMsg::Outgoing(recipient, packet)) => { + if let Some(disconnected) = disconnected.as_ref() { + let mut current = HashSet::new(); + current.insert(peer); + current.insert(recipient); + // Not routing message between "disconnected" nodes. + if disconnected.is_subset(¤t) { + continue; + } } - to_disconnect - }; - for d in &disconnecting { - // notify other peers that this peer is disconnecting - peers[*d].on_disconnect(peer as NodeIndex); + peers[recipient].receive_message(peer as NodeIndex, packet) } + Some(NetworkMsg::ReportPeer(who, _)) => { + to_disconnect.insert(who); + } + Some(_msg) => continue, + } + } + for d in to_disconnect { + for peer in 0..peers.len() { + peers[peer].on_disconnect(d); } } }); } - /// Route messages between peers until all queues are empty. - fn route_until_complete(&mut self) { - while !self.done() { - self.route() - } + /// Route all pending outgoing messages, without waiting or disconnecting. + fn route_fast(&mut self) { + self.mut_peers(move |peers| { + for peer in 0..peers.len() { + while let Some(NetworkMsg::Outgoing(recipient, packet)) = peers[peer].pending_message_fast() { + peers[recipient].receive_message(peer as NodeIndex, packet) + } + } + }); } /// Do a step of synchronization. fn sync_step(&mut self) { - self.route(); + self.route(None); self.mut_peers(|peers| { for peer in peers { @@ -451,23 +679,55 @@ pub trait TestNetFactory: Sized { }) } + /// Send block finalization notifications for all peers. + fn send_finality_notifications(&mut self) { + self.mut_peers(|peers| { + for peer in peers { + peer.send_finality_notifications(); + } + }) + } + /// Restart sync for a peer. fn restart_peer(&mut self, i: usize) { self.peers()[i].restart_sync(); } - /// Perform synchronization until complete. - fn sync(&mut self) -> u32 { + /// Perform synchronization until complete, if provided the + /// given nodes set are excluded from sync. + fn sync_with(&mut self, disconnected: Option>) -> u32 { self.start(); let mut total_steps = 0; - while !self.done() { + let mut done = 0; + + loop { + if done > 3 { break; } + if self.done() { + done += 1; + } else { + done = 0; + } + self.sync_step(); + self.route(disconnected.clone()); + total_steps += 1; - self.route(); } + total_steps } + /// Perform synchronization until complete. + fn sync(&mut self) -> u32 { + self.sync_with(None) + } + + /// Perform synchronization until complete, + /// excluding sync between certain nodes. + fn sync_with_disconnected(&mut self, disconnected: HashSet) -> u32 { + self.sync_with(Some(disconnected)) + } + /// Do the given amount of sync steps. fn sync_steps(&mut self, count: usize) { self.start(); @@ -483,11 +743,12 @@ pub trait TestNetFactory: Sized { } pub struct TestNet { - peers: Vec>>, - started: bool + peers: Vec>>, + started: bool, } impl TestNetFactory for TestNet { + type Specialization = DummySpecialization; type Verifier = PassThroughVerifier; type PeerData = (); @@ -505,15 +766,15 @@ impl TestNetFactory for TestNet { Arc::new(PassThroughVerifier(false)) } - fn peer(&self, i: usize) -> &Peer { + fn peer(&self, i: usize) -> &Peer<(), Self::Specialization> { &self.peers[i] } - fn peers(&self) -> &Vec>> { + fn peers(&self) -> &Vec>> { &self.peers } - fn mut_peers>>)>(&mut self, closure: F ) { + fn mut_peers>>)>(&mut self, closure: F) { closure(&mut self.peers); } @@ -525,3 +786,63 @@ impl TestNetFactory for TestNet { self.started = new; } } + +pub struct ForceFinalized(Arc); + +impl JustificationImport for ForceFinalized { + type Error = ConsensusError; + + fn import_justification( + &self, + hash: H256, + _number: NumberFor, + justification: Justification, + ) -> Result<(), Self::Error> { + self.0.finalize_block(BlockId::Hash(hash), Some(justification), true) + .map_err(|_| ConsensusErrorKind::InvalidJustification.into()) + } +} + +pub struct JustificationTestNet(TestNet); + +impl TestNetFactory for JustificationTestNet { + type Specialization = DummySpecialization; + type Verifier = PassThroughVerifier; + type PeerData = (); + + fn from_config(config: &ProtocolConfig) -> Self { + JustificationTestNet(TestNet::from_config(config)) + } + + fn make_verifier(&self, client: Arc, config: &ProtocolConfig) + -> Arc + { + self.0.make_verifier(client, config) + } + + fn peer(&self, i: usize) -> &Peer { + self.0.peer(i) + } + + fn peers(&self) -> &Vec>> { + self.0.peers() + } + + fn mut_peers>>)>(&mut self, closure: F ) { + self.0.mut_peers(closure) + } + + fn started(&self) -> bool { + self.0.started() + } + + fn set_started(&mut self, new: bool) { + self.0.set_started(new) + } + + fn make_block_import(&self, client: Arc) + -> (SharedBlockImport, Option>, Self::PeerData) + { + (client.clone(), Some(Arc::new(ForceFinalized(client))), Default::default()) + } +} diff --git a/core/network/src/test/sync.rs b/core/network/src/test/sync.rs index 22dedf7b3ed6e386410e27643af30a2e8975f5fa..cb54c0552670589ce7e2b6deebc5b0b028712ad8 100644 --- a/core/network/src/test/sync.rs +++ b/core/network/src/test/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,58 +16,274 @@ use client::backend::Backend; use client::blockchain::HeaderBackend as BlockchainHeaderBackend; -use config::Roles; +use crate::config::Roles; use consensus::BlockOrigin; -use sync::SyncState; +use network_libp2p::NodeIndex; +use std::collections::HashSet; +use std::thread; +use std::time::Duration; use super::*; +fn test_ancestor_search_when_common_is(n: usize) { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(n, false); + net.peer(1).push_blocks(n, false); + net.peer(2).push_blocks(n, false); + + net.peer(0).push_blocks(10, true); + net.peer(1).push_blocks(100, false); + net.peer(2).push_blocks(100, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn sync_peers_works() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + net.sync(); + for peer in 0..3 { + // Assert peers is up to date. + let peers = net.peer(peer).peers.read(); + assert_eq!(peers.len(), 2); + // And then disconnect. + for other in 0..3 { + if other != peer { + net.peer(peer).on_disconnect(other); + } + } + } + net.sync(); + // Now peers are disconnected. + for peer in 0..3 { + let peers = net.peer(peer).peers.read(); + assert_eq!(peers.len(), 0); + } +} + +#[test] +fn sync_cycle_from_offline_to_syncing_to_offline() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + for peer in 0..3 { + // Offline, and not major syncing. + assert!(net.peer(peer).is_offline()); + assert!(!net.peer(peer).is_major_syncing()); + } + + // Generate blocks. + net.peer(2).push_blocks(100, false); + net.start(); + net.route_fast(); + thread::sleep(Duration::from_millis(100)); + net.route_fast(); + for peer in 0..3 { + // Online + assert!(!net.peer(peer).is_offline()); + if peer < 2 { + // Major syncing. + assert!(net.peer(peer).is_major_syncing()); + } + } + net.sync(); + for peer in 0..3 { + // All done syncing. + assert!(!net.peer(peer).is_major_syncing()); + } + + // Now disconnect them all. + for peer in 0..3 { + for other in 0..3 { + if other != peer { + net.peer(peer).on_disconnect(other); + } + } + thread::sleep(Duration::from_millis(100)); + assert!(net.peer(peer).is_offline()); + assert!(!net.peer(peer).is_major_syncing()); + } +} + +#[test] +fn syncing_node_not_major_syncing_when_disconnected() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + // Generate blocks. + net.peer(2).push_blocks(100, false); + net.start(); + net.route_fast(); + thread::sleep(Duration::from_millis(100)); + net.route_fast(); + + // Peer 1 is major-syncing. + assert!(net.peer(1).is_major_syncing()); + + // Disconnect peer 1 form everyone else. + net.peer(1).on_disconnect(0); + net.peer(1).on_disconnect(2); + thread::sleep(Duration::from_millis(100)); + + // Peer 1 is not major-syncing. + assert!(!net.peer(1).is_major_syncing()); +} + #[test] fn sync_from_two_peers_works() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); net.peer(1).push_blocks(100, false); net.peer(2).push_blocks(100, false); net.sync(); - assert!(net.peer(0).client.backend().blockchain().equals_to(net.peer(1).client.backend().blockchain())); - let status = net.peer(0).sync.status(); - assert_eq!(status.sync.state, SyncState::Idle); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); + assert!(!net.peer(0).is_major_syncing()); } #[test] fn sync_from_two_peers_with_ancestry_search_works() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); net.peer(0).push_blocks(10, true); net.peer(1).push_blocks(100, false); net.peer(2).push_blocks(100, false); net.restart_peer(0); net.sync(); - assert!(net.peer(0).client.backend().blockchain().canon_equals_to(net.peer(1).client.backend().blockchain())); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn ancestry_search_works_when_backoff_is_one() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(1, false); + net.peer(1).push_blocks(2, false); + net.peer(2).push_blocks(2, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn ancestry_search_works_when_ancestor_is_genesis() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(3); + + net.peer(0).push_blocks(13, true); + net.peer(1).push_blocks(100, false); + net.peer(2).push_blocks(100, false); + + net.restart_peer(0); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn ancestry_search_works_when_common_is_one() { + test_ancestor_search_when_common_is(1); +} + +#[test] +fn ancestry_search_works_when_common_is_two() { + test_ancestor_search_when_common_is(2); +} + +#[test] +fn ancestry_search_works_when_common_is_hundred() { + test_ancestor_search_when_common_is(100); } #[test] fn sync_long_chain_works() { let mut net = TestNet::new(2); net.peer(1).push_blocks(500, false); - net.sync_steps(3); - assert_eq!(net.peer(0).sync.status().sync.state, SyncState::Downloading); net.sync(); - assert!(net.peer(0).client.backend().blockchain().equals_to(net.peer(1).client.backend().blockchain())); + assert!(net.peer(0).client.backend().as_in_memory().blockchain() + .equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); } #[test] fn sync_no_common_longer_chain_fails() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); net.peer(0).push_blocks(20, true); net.peer(1).push_blocks(20, false); net.sync(); - assert!(!net.peer(0).client.backend().blockchain().canon_equals_to(net.peer(1).client.backend().blockchain())); + assert!(!net.peer(0).client.backend().as_in_memory().blockchain() + .canon_equals_to(net.peer(1).client.backend().as_in_memory().blockchain())); +} + +#[test] +fn sync_justifications() { + let _ = ::env_logger::try_init(); + let mut net = JustificationTestNet::new(3); + net.peer(0).push_blocks(20, false); + net.sync(); + + // there's currently no justification for block #10 + assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), None); + assert_eq!(net.peer(1).client().justification(&BlockId::Number(10)).unwrap(), None); + + // we finalize block #10, #15 and #20 for peer 0 with a justification + net.peer(0).client().finalize_block(BlockId::Number(10), Some(Vec::new()), true).unwrap(); + net.peer(0).client().finalize_block(BlockId::Number(15), Some(Vec::new()), true).unwrap(); + net.peer(0).client().finalize_block(BlockId::Number(20), Some(Vec::new()), true).unwrap(); + + let h1 = net.peer(1).client().header(&BlockId::Number(10)).unwrap().unwrap(); + let h2 = net.peer(1).client().header(&BlockId::Number(15)).unwrap().unwrap(); + let h3 = net.peer(1).client().header(&BlockId::Number(20)).unwrap().unwrap(); + + // peer 1 should get the justifications from the network + net.peer(1).request_justification(&h1.hash().into(), 10); + net.peer(1).request_justification(&h2.hash().into(), 15); + net.peer(1).request_justification(&h3.hash().into(), 20); + + net.sync(); + + for height in (10..21).step_by(5) { + assert_eq!(net.peer(0).client().justification(&BlockId::Number(height)).unwrap(), Some(Vec::new())); + assert_eq!(net.peer(1).client().justification(&BlockId::Number(height)).unwrap(), Some(Vec::new())); + } +} + +#[test] +fn sync_justifications_across_forks() { + let _ = ::env_logger::try_init(); + let mut net = JustificationTestNet::new(3); + // we push 5 blocks + net.peer(0).push_blocks(5, false); + // and then two forks 5 and 6 blocks long + let f1_best = net.peer(0).push_blocks_at(BlockId::Number(5), 5, false); + let f2_best = net.peer(0).push_blocks_at(BlockId::Number(5), 6, false); + + // peer 1 will only see the longer fork. but we'll request justifications + // for both and finalize the small fork instead. + net.sync(); + + net.peer(0).client().finalize_block(BlockId::Hash(f1_best), Some(Vec::new()), true).unwrap(); + + net.peer(1).request_justification(&f1_best, 10); + net.peer(1).request_justification(&f2_best, 11); + + net.sync(); + + assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), Some(Vec::new())); + assert_eq!(net.peer(1).client().justification(&BlockId::Number(10)).unwrap(), Some(Vec::new())); } #[test] fn sync_after_fork_works() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); net.sync_step(); net.peer(0).push_blocks(30, false); @@ -82,33 +298,51 @@ fn sync_after_fork_works() { net.peer(2).push_blocks(1, false); // peer 1 has the best chain - let peer1_chain = net.peer(1).client.backend().blockchain().clone(); + let peer1_chain = net.peer(1).client.backend().as_in_memory().blockchain().clone(); + net.sync(); + assert!(net.peer(0).client.backend().as_in_memory().blockchain().canon_equals_to(&peer1_chain)); + assert!(net.peer(1).client.backend().as_in_memory().blockchain().canon_equals_to(&peer1_chain)); + assert!(net.peer(2).client.backend().as_in_memory().blockchain().canon_equals_to(&peer1_chain)); +} + +#[test] +fn syncs_all_forks() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(4); + net.sync_step(); + net.peer(0).push_blocks(2, false); + net.peer(1).push_blocks(2, false); + + net.peer(0).push_blocks(2, true); + net.peer(1).push_blocks(4, false); + net.sync(); - assert!(net.peer(0).client.backend().blockchain().canon_equals_to(&peer1_chain)); - assert!(net.peer(1).client.backend().blockchain().canon_equals_to(&peer1_chain)); - assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer1_chain)); + // Check that all peers have all of the blocks. + assert_eq!(9, net.peer(0).client.backend().as_in_memory().blockchain().blocks_count()); + assert_eq!(9, net.peer(1).client.backend().as_in_memory().blockchain().blocks_count()); } #[test] fn own_blocks_are_announced() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(3); net.sync(); // connect'em net.peer(0).generate_blocks(1, BlockOrigin::Own, |builder| builder.bake().unwrap()); let header = net.peer(0).client().header(&BlockId::Number(1)).unwrap().unwrap(); - net.peer(0).with_io(|io| net.peer(0).sync.on_block_imported(io, header.hash(), &header)); + net.peer(0).on_block_imported(header.hash(), &header); net.sync(); + assert_eq!(net.peer(0).client.backend().blockchain().info().unwrap().best_number, 1); assert_eq!(net.peer(1).client.backend().blockchain().info().unwrap().best_number, 1); - let peer0_chain = net.peer(0).client.backend().blockchain().clone(); - assert!(net.peer(1).client.backend().blockchain().canon_equals_to(&peer0_chain)); - assert!(net.peer(2).client.backend().blockchain().canon_equals_to(&peer0_chain)); + let peer0_chain = net.peer(0).client.backend().as_in_memory().blockchain().clone(); + assert!(net.peer(1).client.backend().as_in_memory().blockchain().canon_equals_to(&peer0_chain)); + assert!(net.peer(2).client.backend().as_in_memory().blockchain().canon_equals_to(&peer0_chain)); } #[test] fn blocks_are_not_announced_by_light_nodes() { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); let mut net = TestNet::new(0); // full peer0 is connected to light peer @@ -126,10 +360,11 @@ fn blocks_are_not_announced_by_light_nodes() { net.peer(0).on_connect(1); net.peer(1).on_connect(2); - // generate block at peer0 && run sync - while !net.done() { - net.sync_step(); - } + // Only sync between 0 -> 1, and 1 -> 2 + let mut disconnected = HashSet::new(); + disconnected.insert(0 as NodeIndex); + disconnected.insert(2 as NodeIndex); + net.sync_with_disconnected(disconnected); // peer 0 has the best chain // peer 1 has the best chain @@ -138,3 +373,42 @@ fn blocks_are_not_announced_by_light_nodes() { assert_eq!(net.peer(1).client.backend().blockchain().info().unwrap().best_number, 1); assert_eq!(net.peer(2).client.backend().blockchain().info().unwrap().best_number, 0); } + +#[test] +fn can_sync_small_non_best_forks() { + let _ = ::env_logger::try_init(); + let mut net = TestNet::new(2); + net.sync_step(); + net.peer(0).push_blocks(30, false); + net.peer(1).push_blocks(30, false); + + // small fork + reorg on peer 1. + net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); + let small_hash = net.peer(0).client().info().unwrap().chain.best_hash; + net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); + assert_eq!(net.peer(0).client().info().unwrap().chain.best_number, 40); + + // peer 1 only ever had the long fork. + net.peer(1).push_blocks(10, false); + assert_eq!(net.peer(1).client().info().unwrap().chain.best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); + + net.sync(); + + // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. + + assert_eq!(net.peer(0).client().info().unwrap().chain.best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + + net.peer(0).announce_block(small_hash); + net.sync(); + + // after announcing, peer 1 downloads the block. + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); +} diff --git a/core/network/src/util.rs b/core/network/src/util.rs new file mode 100644 index 0000000000000000000000000000000000000000..5e9e64aae7e9c0bb557224cab9562fc4de2f8efd --- /dev/null +++ b/core/network/src/util.rs @@ -0,0 +1,76 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use linked_hash_set::LinkedHashSet; +use std::{hash::Hash, num::NonZeroUsize}; + +/// Wrapper around `LinkedHashSet` which grows bounded. +/// +/// In the limit, for each element inserted the oldest existing element will be removed. +#[derive(Debug, Clone)] +pub(crate) struct LruHashSet { + set: LinkedHashSet, + limit: NonZeroUsize +} + +impl LruHashSet { + /// Create a new `LruHashSet` with the given (exclusive) limit. + pub(crate) fn new(limit: NonZeroUsize) -> Self { + Self { set: LinkedHashSet::new(), limit } + } + + /// Insert element into the set. + /// + /// Returns `true` if this is a new element to the set, `false` otherwise. + /// Maintains the limit of the set by removing the oldest entry if necessary. + /// Inserting the same element will update its LRU position. + pub(crate) fn insert(&mut self, e: T) -> bool { + if self.set.insert(e) { + if self.set.len() == usize::from(self.limit) { + self.set.pop_front(); // remove oldest entry + } + return true + } + false + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn maintains_limit() { + let three = NonZeroUsize::new(3).unwrap(); + let mut set = LruHashSet::::new(three); + + // First element. + assert!(set.insert(1)); + assert_eq!(vec![&1], set.set.iter().collect::>()); + + // Second element. + assert!(set.insert(2)); + assert_eq!(vec![&1, &2], set.set.iter().collect::>()); + + // Inserting the same element updates its LRU position. + assert!(!set.insert(1)); + assert_eq!(vec![&2, &1], set.set.iter().collect::>()); + + // We reached the limit. The next element forces the oldest one out. + assert!(set.insert(3)); + assert_eq!(vec![&1, &3], set.set.iter().collect::>()); + } +} diff --git a/core/panic-handler/Cargo.toml b/core/panic-handler/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..fb870fd8a357e2f14c799dc634c6d64bdacc7b1a --- /dev/null +++ b/core/panic-handler/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "substrate-panic-handler" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Substrate panic handler." +edition = "2018" + +[dependencies] +backtrace = "0.3" +log = "0.4" diff --git a/core/cli/src/panic_hook.rs b/core/panic-handler/src/lib.rs similarity index 59% rename from core/cli/src/panic_hook.rs rename to core/panic-handler/src/lib.rs index 06227d1135b0ce72ffcf736a6fbbdf7135c3ef23..b2fd7238e0d2e77621af4a0c345ed4433b931bab 100644 --- a/core/cli/src/panic_hook.rs +++ b/core/panic-handler/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,20 +19,51 @@ use backtrace::Backtrace; use std::io::{self, Write}; use std::panic::{self, PanicInfo}; +use std::cell::Cell; use std::thread; +thread_local! { + pub static ABORT: Cell = Cell::new(true); +} + /// Set the panic hook -pub fn set() { - panic::set_hook(Box::new(panic_hook)); +pub fn set(bug_url: &'static str) { + panic::set_hook(Box::new(move |c| panic_hook(c, bug_url))); } -static ABOUT_PANIC: &str = " +macro_rules! ABOUT_PANIC { + () => (" This is a bug. Please report it at: - https://github.com/paritytech/polkadot/issues/new -"; + {} +")} + +/// Set aborting flag. Returns previous value of the flag. +pub fn set_abort(enabled: bool) -> bool { + ABORT.with(|flag| { + let prev = flag.get(); + flag.set(enabled); + prev + }) +} + +/// Abort flag guard. Sets abort on construction and reverts to previous setting when dropped. +pub struct AbortGuard(bool); -fn panic_hook(info: &PanicInfo) { +impl AbortGuard { + /// Create a new guard and set abort flag to specified value. + pub fn new(enable: bool) -> AbortGuard { + AbortGuard(set_abort(enable)) + } +} + +impl Drop for AbortGuard { + fn drop(&mut self) { + set_abort(self.0); + } +} + +fn panic_hook(info: &PanicInfo, report_url: &'static str) { let location = info.location(); let file = location.as_ref().map(|l| l.file()).unwrap_or(""); let line = location.as_ref().map(|l| l.line()).unwrap_or(0); @@ -63,7 +94,17 @@ fn panic_hook(info: &PanicInfo) { name, msg, file, line ); - let _ = writeln!(stderr, "{}", ABOUT_PANIC); - ::std::process::exit(1); + let _ = writeln!(stderr, ABOUT_PANIC!(), report_url); + ABORT.with(|flag| { + if flag.get() { + ::std::process::exit(1); + } + }) } +#[test] +fn does_not_abort() { + set("test"); + let _guard = AbortGuard::new(false); + ::std::panic::catch_unwind(|| panic!()).ok(); +} diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 1489b046ba3700a1e058342f32328e3c9758d206..31a0790b58fcf429cb9d1f7cfe1a158781a0f1d6 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -2,56 +2,69 @@ name = "substrate-primitives" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -crunchy = { version = "0.2", default-features = false } -sr-std = { path = "../sr-std", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -fixed-hash = { version = "0.3.0", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } rustc-hex = { version = "2.0", default-features = false } -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -uint = { version = "0.5.0-beta", default-features = false } twox-hash = { version = "1.1.0", optional = true } byteorder = { version = "1.1", default-features = false } -wasmi = { version = "0.4.2", optional = true } -hash-db = { git = "https://github.com/paritytech/trie", default-features = false } -hash256-std-hasher = { git = "https://github.com/paritytech/trie", default-features = false } -ring = { version = "0.12", optional = true } -untrusted = { version = "0.5", optional = true } +primitive-types = { version = "0.2", default-features = false, features = ["codec"] } +impl-serde = { version = "0.1", optional = true } +wasmi = { version = "0.4.3", optional = true } +hash-db = { version = "0.11", default-features = false } +hash256-std-hasher = { version = "0.11", default-features = false } +ring = { version = "0.14", optional = true } +untrusted = { version = "0.6", optional = true } hex-literal = { version = "0.1", optional = true } base58 = { version = "0.1", optional = true } blake2-rfc = { version = "0.2.18", optional = true } +schnorrkel = { git = "https://github.com/w3f/schnorrkel", optional = true, commit = "d3289df76b8ae6dfb68e733204c5c009df5343a9" } +rand = { version = "0.6", optional = true } +sha2 = { version = "0.8", optional = true } +substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39", optional = true } +tiny-bip39 = { version = "0.6.0", optional = true } +hex = { version = "0.3", optional = true } +regex = {version = "1.1", optional = true } [dev-dependencies] substrate-serializer = { path = "../serializer" } -pretty_assertions = "0.4" +pretty_assertions = "0.5" heapsize = "0.4" [features] default = ["std"] std = [ - "crunchy/std", "wasmi", - "uint/std", - "fixed-hash/std", - "fixed-hash/heapsize", - "fixed-hash/byteorder", - "fixed-hash/rustc-hex", - "fixed-hash/libc", + "primitive-types/std", + "primitive-types/serde", + "primitive-types/heapsize", + "primitive-types/byteorder", + "primitive-types/rustc-hex", + "primitive-types/libc", + "impl-serde", "parity-codec/std", "hash256-std-hasher/std", "hash-db/std", - "sr-std/std", - "serde/std", + "rstd/std", + "serde", "rustc-hex/std", "twox-hash", "blake2-rfc", "ring", "untrusted", "hex-literal", + "hex", "base58", + "substrate-bip39", + "tiny-bip39", "serde_derive", "byteorder/std", + "rand", + "sha2", + "schnorrkel", + "regex", ] diff --git a/core/primitives/src/authority_id.rs b/core/primitives/src/authority_id.rs deleted file mode 100644 index 9f5e3c26ac234c1ff9dc6f0775cc6776c92e6707..0000000000000000000000000000000000000000 --- a/core/primitives/src/authority_id.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - - -#[cfg(feature = "std")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use H256; - -/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public. -#[derive(Clone, Copy, PartialEq, Eq, Default, Encode, Decode)] -pub struct AuthorityId(pub [u8; 32]); - -#[cfg(feature = "std")] -impl ::std::fmt::Display for AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", ::ed25519::Public(self.0).to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl ::std::fmt::Debug for AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let h = format!("{}", ::hexdisplay::HexDisplay::from(&self.0)); - write!(f, "{} ({}…{})", ::ed25519::Public(self.0).to_ss58check(), &h[0..8], &h[60..]) - } -} - -#[cfg(feature = "std")] -impl ::std::hash::Hash for AuthorityId { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl AsRef<[u8; 32]> for AuthorityId { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for AuthorityId { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Into<[u8; 32]> for AuthorityId { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl From<[u8; 32]> for AuthorityId { - fn from(a: [u8; 32]) -> Self { - AuthorityId(a) - } -} - -impl AsRef for AuthorityId { - fn as_ref(&self) -> &AuthorityId { - &self - } -} - -impl Into for AuthorityId { - fn into(self) -> H256 { - self.0.into() - } -} - -#[cfg(feature = "std")] -impl Serialize for AuthorityId { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - ::ed25519::serialize(&self, serializer) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for AuthorityId { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - ::ed25519::deserialize(deserializer) - } -} diff --git a/core/primitives/src/bytes.rs b/core/primitives/src/bytes.rs deleted file mode 100644 index ea375a25300943df1e6d3cbe7472fa67819d4a67..0000000000000000000000000000000000000000 --- a/core/primitives/src/bytes.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Simple type for representing Vec with regards to serde. - -use core::fmt; - -use serde::{de, Serializer, Deserializer}; - -#[cfg(not(feature = "std"))] -mod alloc_types { - pub use ::alloc::string::String; - pub use ::alloc::vec::Vec; -} - -#[cfg(feature = "std")] -mod alloc_types { - pub use ::std::vec::Vec; - pub use ::std::string::String; -} - -pub use self::alloc_types::*; - -/// Serializes a slice of bytes. -pub fn serialize(bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - let hex: String = ::rustc_hex::ToHex::to_hex(bytes); - serializer.serialize_str(&format!("0x{}", hex)) -} - -/// Serialize a slice of bytes as uint. -/// -/// The representation will have all leading zeros trimmed. -pub fn serialize_uint(bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - let non_zero = bytes.iter().take_while(|b| **b == 0).count(); - let bytes = &bytes[non_zero..]; - if bytes.is_empty() { - return serializer.serialize_str("0x0"); - } - - let hex: String = ::rustc_hex::ToHex::to_hex(bytes); - let has_leading_zero = !hex.is_empty() && &hex[0..1] == "0"; - serializer.serialize_str( - &format!("0x{}", if has_leading_zero { &hex[1..] } else { &hex }) - ) -} - -/// Expected length of bytes vector. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub enum ExpectedLen { - /// Any length in bytes. - #[cfg_attr(not(feature = "std"), allow(unused))] - Any, - /// Exact length in bytes. - Exact(usize), - /// A bytes length between (min; max]. - Between(usize, usize), -} - -impl fmt::Display for ExpectedLen { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExpectedLen::Any => write!(fmt, "even length"), - ExpectedLen::Exact(v) => write!(fmt, "length of {}", v * 2), - ExpectedLen::Between(min, max) => write!(fmt, "length between ({}; {}]", min * 2, max * 2), - } - } -} - -/// Deserialize into vector of bytes. -#[cfg(feature = "std")] -pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where - D: Deserializer<'de>, -{ - deserialize_check_len(deserializer, ExpectedLen::Any) -} - -/// Deserialize into vector of bytes with additional size check. -pub fn deserialize_check_len<'de, D>(deserializer: D, len: ExpectedLen) -> Result, D::Error> where - D: Deserializer<'de>, -{ - struct Visitor { - len: ExpectedLen, - } - - impl<'a> de::Visitor<'a> for Visitor { - type Value = Vec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 0x-prefixed hex string with {}", self.len) - } - - fn visit_str(self, v: &str) -> Result { - if v.len() < 2 || &v[0..2] != "0x" { - return Err(E::custom("prefix is missing")) - } - - let is_len_valid = match self.len { - // just make sure that we have all nibbles - ExpectedLen::Any => v.len() % 2 == 0, - ExpectedLen::Exact(len) => v.len() == 2 * len + 2, - ExpectedLen::Between(min, max) => v.len() <= 2 * max + 2 && v.len() > 2 * min + 2, - }; - - if !is_len_valid { - return Err(E::invalid_length(v.len() - 2, &self)) - } - - let bytes = match self.len { - ExpectedLen::Between(..) if v.len() % 2 != 0 => { - ::rustc_hex::FromHex::from_hex(&*format!("0{}", &v[2..])) - }, - _ => ::rustc_hex::FromHex::from_hex(&v[2..]) - }; - - #[cfg(feature = "std")] - fn format_err(e: ::rustc_hex::FromHexError) -> String { - format!("invalid hex value: {:?}", e) - } - - #[cfg(not(feature = "std"))] - fn format_err(e: ::rustc_hex::FromHexError) -> String { - match e { - ::rustc_hex::InvalidHexLength => format!("invalid hex value: invalid length"), - ::rustc_hex::InvalidHexCharacter(c, p) => - format!("invalid hex value: invalid character {} at position {}", c, p), - } - } - - bytes.map_err(|e| E::custom(format_err(e))) - } - - #[cfg(feature = "std")] - fn visit_string(self, v: String) -> Result { - self.visit_str(&v) - } - } - // TODO [ToDr] Use raw bytes if we switch to RLP / binencoding - // (visit_bytes, visit_bytes_buf) - deserializer.deserialize_str(Visitor { len }) -} diff --git a/core/primitives/src/changes_trie.rs b/core/primitives/src/changes_trie.rs index 0211b57236a32d6a89ce6976a64ff9fa9300beeb..c8776a6f0873f210f2fac9c246aada2661960fbb 100644 --- a/core/primitives/src/changes_trie.rs +++ b/core/primitives/src/changes_trie.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,6 +16,10 @@ //! Substrate changes trie configuration. +#[cfg(any(feature = "std", test))] +use serde_derive::{Serialize, Deserialize}; +use parity_codec::{Encode, Decode}; + /// Substrate changes trie configuration. #[cfg_attr(any(feature = "std", test), derive(Serialize, Deserialize))] #[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] @@ -49,7 +53,7 @@ impl ChangesTrieConfiguration { return 1; } - // TODO: use saturating_pow when available + // FIXME: use saturating_pow once stabilized - https://github.com/rust-lang/rust/issues/48320 let mut max_digest_interval = self.digest_interval; for _ in 1..self.digest_levels { max_digest_interval = match max_digest_interval.checked_mul(self.digest_interval) { diff --git a/core/primitives/src/crypto.rs b/core/primitives/src/crypto.rs new file mode 100644 index 0000000000000000000000000000000000000000..fe7c1fabb8eccdacb99040b2adf443ff61cd109e --- /dev/null +++ b/core/primitives/src/crypto.rs @@ -0,0 +1,497 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Cryptographic utilities. +// end::description[] + +#[cfg(feature = "std")] +use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use regex::Regex; +#[cfg(feature = "std")] +use base58::{FromBase58, ToBase58}; + +/// The root phrase for our publically known keys. +pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; + +/// The address of the associated root phrase for our publically known keys. +pub const DEV_ADDRESS: &str = "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqAS7"; + +/// The infallible type. +#[derive(Debug)] +pub enum Infallible {} + +/// The length of the junction identifier. Note that this is also referred to as the +/// `CHAIN_CODE_LENGTH` in the context of Schnorrkel. +#[cfg(feature = "std")] +pub const JUNCTION_ID_LEN: usize = 32; + +/// Similar to `From`, except that the onus is on the part of the caller to ensure +/// that data passed in makes sense. Basically, you're not guaranteed to get anything +/// sensible out. +pub trait UncheckedFrom { + /// Convert from an instance of `T` to Self. This is not guaranteed to be + /// whatever counts as a valid instance of `T` and it's up to the caller to + /// ensure that it makes sense. + fn unchecked_from(t: T) -> Self; +} + +/// The counterpart to `UncheckedFrom`. +pub trait UncheckedInto { + /// The counterpart to `unchecked_from`. + fn unchecked_into(self) -> T; +} + +impl> UncheckedInto for S { + fn unchecked_into(self) -> T { + T::unchecked_from(self) + } +} + +/// An error with the interpretation of a secret. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg(feature = "std")] +pub enum SecretStringError { + /// The overall format was invalid (e.g. the seed phrase contained symbols). + InvalidFormat, + /// The seed phrase provided is not a valid BIP39 phrase. + InvalidPhrase, + /// The supplied password was invalid. + InvalidPassword, + /// The seed is invalid (bad content). + InvalidSeed, + /// The seed has an invalid length. + InvalidSeedLength, + /// The derivation path was invalid (e.g. contains soft junctions when they are not supported). + InvalidPath, +} + +/// A since derivation junction description. It is the single parameter used when creating +/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` +/// a new public key from an existing public key. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] +#[cfg(feature = "std")] +pub enum DeriveJunction { + /// Soft (vanilla) derivation. Public keys have a correspondent derivation. + Soft([u8; JUNCTION_ID_LEN]), + /// Hard ("hardened") derivation. Public keys do not have a correspondent derivation. + Hard([u8; JUNCTION_ID_LEN]), +} + +#[cfg(feature = "std")] +impl DeriveJunction { + /// Consume self to return a soft derive junction with the same chain code. + pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } + + /// Consume self to return a hard derive junction with the same chain code. + pub fn harden(self) -> Self { DeriveJunction::Hard(self.unwrap_inner()) } + + /// Create a new soft (vanilla) DeriveJunction from a given, encodable, value. + /// + /// If you need a hard junction, use `hard()`. + pub fn soft(index: T) -> Self { + let mut cc: [u8; JUNCTION_ID_LEN] = Default::default(); + index.using_encoded(|data| if data.len() > JUNCTION_ID_LEN { + let hash_result = blake2_rfc::blake2b::blake2b(JUNCTION_ID_LEN, &[], data); + let hash = hash_result.as_bytes(); + cc.copy_from_slice(hash); + } else { + cc[0..data.len()].copy_from_slice(data); + }); + DeriveJunction::Soft(cc) + } + + /// Create a new hard (hardened) DeriveJunction from a given, encodable, value. + /// + /// If you need a soft junction, use `soft()`. + pub fn hard(index: T) -> Self { + Self::soft(index).harden() + } + + /// Consume self to return the chain code. + pub fn unwrap_inner(self) -> [u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c, + } + } + + /// Get a reference to the inner junction id. + pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(ref c) | DeriveJunction::Soft(ref c) => c, + } + } + + /// Return `true` if the junction is soft. + pub fn is_soft(&self) -> bool { + match *self { + DeriveJunction::Soft(_) => true, + _ => false, + } + } + + /// Return `true` if the junction is hard. + pub fn is_hard(&self) -> bool { + match *self { + DeriveJunction::Hard(_) => true, + _ => false, + } + } +} + +#[cfg(feature = "std")] +impl> From for DeriveJunction { + fn from(j: T) -> DeriveJunction { + let j = j.as_ref(); + let (code, hard) = if j.starts_with("/") { + (&j[1..], true) + } else { + (j, false) + }; + + let res = if let Ok(n) = str::parse::(code) { + // number + DeriveJunction::soft(n) + } else { + // something else + DeriveJunction::soft(code) + }; + + if hard { + res.harden() + } else { + res + } + } +} + +/// An error type for SS58 decoding. +#[cfg(feature = "std")] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + /// Bad alphabet. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, + /// Invalid format. + InvalidFormat, + /// Invalid derivation path. + InvalidPath, +} + +/// Key that can be encoded to/from SS58. +#[cfg(feature = "std")] +pub trait Ss58Codec: Sized { + /// Some if the string is a properly encoded SS58Check address. + fn from_ss58check(s: &str) -> Result; + /// Some if the string is a properly encoded SS58Check address, optionally with + /// a derivation path following. + fn from_string(s: &str) -> Result { Self::from_ss58check(s) } + /// Return the ss58-check string for this key. + fn to_ss58check(&self) -> String; +} + +#[cfg(feature = "std")] +/// Derivable key trait. +pub trait Derive: Sized { + /// Derive a child key from a series of given junctions. + /// + /// Will be `None` for public keys if there are any hard junctions in there. + fn derive>(&self, _path: Iter) -> Option { None } +} + +#[cfg(feature = "std")] +impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { + fn from_ss58check(s: &str) -> Result { + let mut res = T::default(); + let len = res.as_mut().len(); + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != len + 3 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + if d[len+1..len+3] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..len+1]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + res.as_mut().copy_from_slice(&d[1..len+1]); + Ok(res) + } + + fn to_ss58check(&self) -> String { + let mut v = vec![42u8]; + v.extend(self.as_ref()); + let r = blake2_rfc::blake2b::blake2b(64, &[], &v); + v.extend(&r.as_bytes()[0..2]); + v.to_base58() + } + + fn from_string(s: &str) -> Result { + let re = Regex::new(r"^(?P[\w\d]+)?(?P(//?[^/]+)*)$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_ss58check(cap.name("ss58").map(|r| r.as_str()).unwrap_or(DEV_ADDRESS))? + .derive(path) + .ok_or(PublicError::InvalidPath) + } +} + +/// Trait suitable for typical cryptographic PKI key pair type. +/// +/// For now it just specifies how to create a key from a phrase and derivation path. +#[cfg(feature = "std")] +pub trait Pair: Sized { + /// TThe type which is used to encode a public key. + type Public; + + /// The type used to (minimally) encode the data required to securely create + /// a new key pair. + type Seed; + + /// The type used to represent a signature. Can be created from a key pair and a message + /// and verified with the message and a public key. + type Signature; + + /// Error returned from the `derive` function. + type DeriveError; + + /// Generate new secure (random) key pair. + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Self; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + /// + /// This is generally slower than `generate()`, so prefer that unless you need to persist + /// the key from the current session. + fn generate_with_phrase(password: Option<&str>) -> (Self, String); + + /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result; + + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result; + + /// Generate new key pair from the provided `seed`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed(seed: Self::Seed) -> Self; + + /// Make a new key pair from secret seed material. The slice must be the correct size or + /// it will return `None`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed_slice(seed: &[u8]) -> Result; + + /// Construct a key from a phrase, password and path. + fn from_standard_components< + I: Iterator + >(phrase: &str, password: Option<&str>, path: I) -> Result; + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Self::Signature; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool; + + /// Get the public key. + fn public(&self) -> Self::Public; + + /// Interprets the string `s` in order to generate a key Pair. + /// + /// This takes a helper function to do the key generation from a phrase, password and + /// junction iterator. + /// + /// - If `s` is a possibly `0x` prefixed 64-digit hex string, then it will be interpreted + /// directly as a `MiniSecretKey` (aka "seed" in `subkey`). + /// - If `s` is a valid BIP-39 key phrase of 12, 15, 18, 21 or 24 words, then the key will + /// be derived from it. In this case: + /// - the phrase may be followed by one or more items delimited by `/` characters. + /// - the path may be followed by `///`, in which case everything after the `///` is treated + /// as a password. + /// - If `s` begins with a `/` character it is prefixed with the Substrate public `DEV_PHRASE` and + /// interpreted as above. + /// + /// In this case they are interpreted as HDKD junctions; purely numeric items are interpreted as + /// integers, non-numeric items as strings. Junctions prefixed with `/` are interpreted as soft + /// junctions, and with `//` as hard junctions. + /// + /// There is no correspondence mapping between SURI strings and the keys they represent. + /// Two different non-identical strings can actually lead to the same secret being derived. + /// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros. + /// Similarly an empty password (ending the SURI with `///`) is perfectly valid and will generally + /// be equivalent to no password at all. + /// + /// `None` is returned if no matches are found. + fn from_string(s: &str, password_override: Option<&str>) -> Result { + let hex_seed = if s.starts_with("0x") { + &s[2..] + } else { + s + }; + + if let Ok(d) = hex::decode(hex_seed) { + if let Ok(r) = Self::from_seed_slice(&d) { + return Ok(r) + } + } + + let re = Regex::new(r"^(?P\w+( \w+)*)?(?P(//?[^/]+)*)(///(?P.*))?$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_standard_components( + cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE), + password_override.or_else(|| cap.name("password").map(|m| m.as_str())), + path, + ) + } +} + +#[cfg(test)] +mod tests { + use crate::DeriveJunction; + use hex_literal::{hex, hex_impl}; + use super::*; + + #[derive(Eq, PartialEq, Debug)] + enum TestPair { + Generated, + GeneratedWithPhrase, + GeneratedFromPhrase{phrase: String, password: Option}, + Standard{phrase: String, password: Option, path: Vec}, + Seed(Vec), + } + + impl Pair for TestPair { + type Public = (); + type Seed = (); + type Signature = (); + type DeriveError = (); + + fn generate() -> Self { TestPair::Generated } + fn generate_with_phrase(_password: Option<&str>) -> (Self, String) { (TestPair::GeneratedWithPhrase, "".into()) } + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + Ok(TestPair::GeneratedFromPhrase{ phrase: phrase.to_owned(), password: password.map(Into::into) }) + } + fn derive>(&self, _path: Iter) -> Result { + Err(()) + } + fn from_seed(_seed: Self::Seed) -> Self { TestPair::Seed(vec![]) } + fn sign(&self, _message: &[u8]) -> Self::Signature { () } + fn verify, M: AsRef<[u8]>>(_sig: &Self::Signature, _message: M, _pubkey: P) -> bool { true } + fn verify_weak, M: AsRef<[u8]>>(_sig: &[u8], _message: M, _pubkey: P) -> bool { true } + fn public(&self) -> Self::Public { () } + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Ok(TestPair::Standard { phrase: phrase.to_owned(), password: password.map(ToOwned::to_owned), path: path.collect() }) + } + fn from_seed_slice(seed: &[u8]) -> Result { + Ok(TestPair::Seed(seed.to_owned())) + } + } + + #[test] + fn interpret_std_seed_should_work() { + assert_eq!( + TestPair::from_string("0x0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + assert_eq!( + TestPair::from_string("0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + } + + #[test] + fn password_override_should_work() { + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world", Some("password")), + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world///other password", Some("password")), + ); + } + + #[test] + fn interpret_std_secret_string_should_work() { + assert_eq!( + TestPair::from_string("hello world", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT"), DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world/1//DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::soft(1), DeriveJunction::hard("DOT")]}) + ); + } +} diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index c6f28c64c117750d46d9f17f217401a388e4e1e0..586a6fe13c577e9a0e957ebbc74195dd95b3a839 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,57 +18,251 @@ //! Simple Ed25519 API. // end::description[] + +use crate::{hash::H256, hash::H512}; +use parity_codec::{Encode, Decode}; + +#[cfg(feature = "std")] use untrusted; +#[cfg(feature = "std")] use blake2_rfc; -use ring::{rand, signature}; -use {hash::H512, AuthorityId}; +#[cfg(feature = "std")] +use ring::{signature, signature::KeyPair, rand::{SecureRandom, SystemRandom}}; +#[cfg(feature = "std")] use base58::{ToBase58, FromBase58}; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "std")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Derive}; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::crypto::UncheckedFrom; +/// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys +/// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we +/// will need it later (such as for HDKD). #[cfg(feature = "std")] -use serde::{de, Serializer, Deserializer, Deserialize}; +type Seed = [u8; 32]; -/// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = H512; +/// A public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); -/// Length of the PKCS#8 encoding of the key. -pub const PKCS_LEN: usize = 85; +/// A key pair. +#[cfg(feature = "std")] +pub struct Pair(signature::Ed25519KeyPair, Seed); -/// A localized signature also contains sender information. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct LocalizedSignature { - /// The signer of the signature. - pub signer: Public, - /// The signature itself. - pub signature: Signature, +#[cfg(feature = "std")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair::from_seed(self.1.clone()) + } } -/// Verify a message without type checking the parameters' types for the right size. -/// Returns true if the signature is good. -pub fn verify>(sig: &[u8], message: &[u8], public: P) -> bool { - let public_key = untrusted::Input::from(public.as_ref()); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(sig); +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] } } -/// A public key. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct Public(pub [u8; 32]); +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} -/// A key pair. -pub struct Pair(signature::Ed25519KeyPair); +impl From for [u8; 32] { + fn from(x: Public) -> Self { + x.0 + } +} + +#[cfg(feature = "std")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +impl From for H256 { + fn from(x: Public) -> Self { + x.0.into() + } +} +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} + +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] impl ::std::hash::Hash for Public { fn hash(&self, state: &mut H) { self.0.hash(state); } } +/// A signature (a 512-bit value). +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +impl AsRef<[u8; 64]> for Signature { + fn as_ref(&self) -> &[u8; 64] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} + +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } + + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } + + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) + } +} + +/// A localized signature also contains sender information. +#[cfg(feature = "std")] +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct LocalizedSignature { + /// The signer of the signature. + pub signer: Public, + /// The signature itself. + pub signature: Signature, +} + /// An error type for SS58 decoding. +#[cfg(feature = "std")] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { /// Bad alphabet. @@ -83,36 +277,33 @@ pub enum PublicError { impl Public { /// A new instance from the given 32-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_raw(data: [u8; 32]) -> Self { Public(data) } /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! pub fn from_slice(data: &[u8]) -> Self { let mut r = [0u8; 32]; r.copy_from_slice(data); Public(r) } - /// Some if the string is a properly encoded SS58Check address. - pub fn from_ss58check(s: &str) -> Result { - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != 35 { - // Invalid length. - return Err(PublicError::BadLength); - } - if d[0] != 42 { - // Invalid version. - return Err(PublicError::UnknownVersion); - } - if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - Ok(Self::from_slice(&d[1..33])) + /// A new instance from an H256. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_h256(x: H256) -> Self { + Public(x.into()) } /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() @@ -128,6 +319,30 @@ impl Public { pub fn as_array_ref(&self) -> &[u8; 32] { self.as_ref() } +} + +#[cfg(feature = "std")] +impl Derive for Public {} + +#[cfg(feature = "std")] +impl Public { + /// Some if the string is a properly encoded SS58Check address. + pub fn from_ss58check(s: &str) -> Result { + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != 35 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + Ok(Self::from_slice(&d[1..33])) + } /// Return the ss58-check string for this key. pub fn to_ss58check(&self) -> String { @@ -139,185 +354,205 @@ impl Public { } } -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Into<[u8; 32]> for Public { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl AsRef for Public { - fn as_ref(&self) -> &Public { - &self - } -} - +#[cfg(feature = "std")] impl AsRef for Pair { fn as_ref(&self) -> &Pair { &self } } -impl Into for Public { - fn into(self) -> AuthorityId { - AuthorityId(self.0) - } -} - -impl From for Public { - fn from(id: AuthorityId) -> Self { - Public(id.0) - } -} - -impl ::std::fmt::Display for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } +/// Derive a single hard junction. +#[cfg(feature = "std")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| { + let mut res = [0u8; 32]; + res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + res + }) } -impl ::std::fmt::Debug for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", ::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } +/// An error when deriving a key. +#[cfg(feature = "std")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, } -impl Pair { - /// Generate new secure (random) key pair, yielding it and the corresponding pkcs#8 bytes. - pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed"); - let pair = Self::from_pkcs8(&pkcs8_bytes).expect("just-generated pkcs#8 data is valid; qed"); - - (pair, pkcs8_bytes) - } +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; /// Generate new secure (random) key pair. - pub fn generate() -> Pair { - let (pair, _) = Self::generate_with_pkcs8(); - pair - } - - /// Generate from pkcs#8 bytes. - pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result { - signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair) - } - - /// Make a new key pair from a seed phrase. - /// NOTE: prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - pub fn from_seed(seed: &[u8; 32]) -> Pair { + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Pair { + let mut seed: Seed = Default::default(); + SystemRandom::new().fill(seed.as_mut()).expect("system random source should always work! qed"); + Self::from_seed(seed) + } + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) + } + + /// Generate key pair from given recovery phrase and password. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + Self::from_seed_slice(&big_seed[0..32]) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrasee + fn from_seed(seed: Seed) -> Pair { let key = signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])) .expect("seed has valid length; qed"); + Pair(key, seed) + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + if seed_slice.len() != 32 { + Err(SecretStringError::InvalidSeedLength) + } else { + let mut seed = [0u8; 32]; + seed.copy_from_slice(&seed_slice); + Ok(Self::from_seed(seed)) + } + } - Pair(key) + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result { + let mut acc = self.1.clone(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok(Self::from_seed(acc)) } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); - Signature::from(r) + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)?.derive(path).map_err(|_| SecretStringError::InvalidPath) } /// Get the public key. - pub fn public(&self) -> Public { + fn public(&self) -> Public { let mut r = [0u8; 32]; - let pk = self.0.public_key_bytes(); + let pk = self.0.public_key().as_ref(); r.copy_from_slice(pk); Public(r) } - /// Derive a child key. Probably unsafe and broken. - // TODO: proper HD derivation https://cardanolaunch.com/assets/Ed25519_BIP.pdf - pub fn derive_child_probably_bad(&self, chain_data: &[u8]) -> Pair { - let sig = self.sign(chain_data); - let mut seed = [0u8; 32]; - seed.copy_from_slice(&sig[..32]); - - Pair::from_seed(&seed) + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature::from_raw(r) } -} -/// Verify a signature on a message. Returns true if the signature is good. -pub fn verify_strong>(sig: &Signature, message: &[u8], pubkey: P) -> bool { - let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&sig.as_bytes()); + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(&sig.0[..]); - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } -} -/// Something that acts as a signature allowing a message to be verified. -pub trait Verifiable { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool; -} + /// Verify a signature on a message. Returns true if the signature is good. + /// + /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct + /// size. Use it only if you're coming from byte buffers and need the speed. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(pubkey.as_ref()); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(sig); -impl Verifiable for Signature { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - verify_strong(&self, message, pubkey) - } -} - -impl Verifiable for LocalizedSignature { - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey) + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } } -/// Deserialize from `ss58` into something that can be constructed from `[u8; 32]`. #[cfg(feature = "std")] -pub fn deserialize<'de, D, T: From<[u8; 32]>>(deserializer: D) -> Result where - D: Deserializer<'de>, -{ - let ss58 = String::deserialize(deserializer)?; - Public::from_ss58check(&ss58) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - .map(|v| v.0.into()) -} +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> &Seed { + &self.1 + } -/// Serializes something that implements `AsRef<[u8; 32]>` into `ss58`. -#[cfg(feature = "std")] -pub fn serialize>(data: &T, serializer: S) -> Result where - S: Serializer, -{ - serializer.serialize_str(&Public(*data.as_ref()).to_ss58check()) + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(padded_seed) + }) + } } #[cfg(test)] mod test { use super::*; + use hex_literal::{hex, hex_impl}; + use crate::{Pair as _Pair, crypto::DEV_PHRASE}; - fn _test_primitives_signature_and_local_the_same() { - fn takes_two(_: T, _: T) { } - takes_two(Signature::default(), ::Signature::default()) + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); } #[test] fn test_vector_should_work() { - let pair: Pair = Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + let pair: Pair = Pair::from_seed(hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + let public = pair.public(); + assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); + let message = b""; + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn test_vector_by_string_should_work() { + let pair: Pair = Pair::from_string("0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", None).unwrap(); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); let message = b""; - let signature: Signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").into(); + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); assert!(&pair.sign(&message[..]) == &signature); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -326,39 +561,47 @@ mod test { let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] fn seeded_pair_should_work() { - use ::hexdisplay::HexDisplay; - - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee"))); let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); let signature = pair.sign(&message[..]); - println!("Correct signature: {}", HexDisplay::from(&signature.as_bytes())); - assert!(verify_strong(&signature, &message[..], &public)); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] - fn generate_with_pkcs8_recovery_possible() { - let (pair1, pkcs8) = Pair::generate_with_pkcs8(); - let pair2 = Pair::from_pkcs8(&pkcs8).unwrap(); + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(None); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); assert_eq!(pair1.public(), pair2.public()); } #[test] - fn derive_child() { - let pair = Pair::generate(); - let _pair2 = pair.derive_child_probably_bad(b"session_1234"); + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, Some("password")).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn password_does_something() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); } #[test] fn ss58check_roundtrip_works() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); let s = public.to_ss58check(); println!("Correct: {}", s); diff --git a/core/primitives/src/hash.rs b/core/primitives/src/hash.rs index 8d04df26844dbebd6c272f04a80c98ee813f925d..f3e3583be5771b3d0569753393cf232ad9a68cf4 100644 --- a/core/primitives/src/hash.rs +++ b/core/primitives/src/hash.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,65 +16,7 @@ //! A fixed hash type. -#[cfg(feature = "std")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - -#[cfg(feature = "std")] -use bytes; - -macro_rules! impl_rest { - ($name: ident, $len: expr) => { - #[cfg(feature = "std")] - impl Serialize for $name { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - bytes::serialize(&self.0, serializer) - } - } - - #[cfg(feature = "std")] - impl<'de> Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Exact($len)) - .map(|x| $name::from_slice(&x)) - } - } - - impl ::codec::Encode for $name { - fn using_encoded R>(&self, f: F) -> R { - self.0.using_encoded(f) - } - } - impl ::codec::Decode for $name { - fn decode(input: &mut I) -> Option { - <[u8; $len] as ::codec::Decode>::decode(input).map($name) - } - } - - #[cfg(feature = "std")] - impl From for $name { - fn from(val: u64) -> Self { - Self::from_low_u64_be(val) - } - } - } -} - -construct_fixed_hash!{ - /// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size. - pub struct H160(20); -} -construct_fixed_hash!{ - /// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size. - pub struct H256(32); -} -construct_fixed_hash!{ - /// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size. - pub struct H512(64); -} - -impl_rest!(H160, 20); -impl_rest!(H256, 32); -impl_rest!(H512, 64); +pub use primitive_types::{H160, H256, H512}; /// Hash conversion. Used to convert between unbound associated hash types in traits, /// implemented by the same hash type. @@ -95,12 +37,12 @@ mod tests { fn test_h160() { let tests = vec![ (Default::default(), "0x0000000000000000000000000000000000000000"), - (H160::from(2), "0x0000000000000000000000000000000000000002"), - (H160::from(15), "0x000000000000000000000000000000000000000f"), - (H160::from(16), "0x0000000000000000000000000000000000000010"), - (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), - (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), - (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), + (H160::from_low_u64_be(2), "0x0000000000000000000000000000000000000002"), + (H160::from_low_u64_be(15), "0x000000000000000000000000000000000000000f"), + (H160::from_low_u64_be(16), "0x0000000000000000000000000000000000000010"), + (H160::from_low_u64_be(1_000), "0x00000000000000000000000000000000000003e8"), + (H160::from_low_u64_be(100_000), "0x00000000000000000000000000000000000186a0"), + (H160::from_low_u64_be(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), ]; for (number, expected) in tests { @@ -113,12 +55,12 @@ mod tests { fn test_h256() { let tests = vec![ (Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"), - (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), - (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), - (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), - (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), - (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), - (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), + (H256::from_low_u64_be(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), + (H256::from_low_u64_be(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), + (H256::from_low_u64_be(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), + (H256::from_low_u64_be(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), + (H256::from_low_u64_be(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), + (H256::from_low_u64_be(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), ]; for (number, expected) in tests { diff --git a/core/primitives/src/hasher.rs b/core/primitives/src/hasher.rs index f98a0c737205c746fe023f7b13257967f8b6abc8..4562180a1a454c5ba0ebe5e1cb8faffde1744ee9 100644 --- a/core/primitives/src/hasher.rs +++ b/core/primitives/src/hasher.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,12 +18,12 @@ use hash_db::Hasher; use hash256_std_hasher::Hash256StdHasher; -use hash::H256; +use crate::hash::H256; pub mod blake2 { use super::{Hasher, Hash256StdHasher, H256}; #[cfg(feature = "std")] - use hashing::blake2_256; + use crate::hashing::blake2_256; #[cfg(not(feature = "std"))] extern "C" { diff --git a/core/primitives/src/hashing.rs b/core/primitives/src/hashing.rs index 1a149529781633b3f6415e49ec8c46940ffa4daf..814048fea848da3bdc9732b6521ace0220708da1 100644 --- a/core/primitives/src/hashing.rs +++ b/core/primitives/src/hashing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/hexdisplay.rs b/core/primitives/src/hexdisplay.rs index f02b0f19b705f72c4e7c40ba9a629277bbc0e3ed..d748208d0e09ff911be9245a4588ece343191d59 100644 --- a/core/primitives/src/hexdisplay.rs +++ b/core/primitives/src/hexdisplay.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ impl AsBytesRef for [u8] { fn as_bytes_ref(&self) -> &[u8] { &self } } -impl AsBytesRef for ::bytes::Vec { +impl AsBytesRef for Vec { fn as_bytes_ref(&self) -> &[u8] { &self } } @@ -91,4 +91,3 @@ pub fn ascii_format(asciish: &[u8]) -> String { } r } - diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs index 1bbfaafb241387f9d64eb451640b97403912b2ed..67b99f7ebc81b8fd6dd80c4b715698ae90bcfe82 100644 --- a/core/primitives/src/lib.rs +++ b/core/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,58 +21,10 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[macro_use] -extern crate crunchy; -#[macro_use] -extern crate fixed_hash; -#[macro_use] -extern crate uint as uint_crate; -#[macro_use] -extern crate parity_codec_derive; - -extern crate rustc_hex; -extern crate byteorder; -extern crate parity_codec as codec; - -#[cfg(feature = "std")] -extern crate serde; -#[cfg(feature = "std")] -extern crate twox_hash; - -#[cfg(feature = "std")] -extern crate blake2_rfc; -#[cfg(feature = "std")] -extern crate ring; -#[cfg(feature = "std")] -extern crate base58; -#[cfg(feature = "std")] -extern crate untrusted; -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - -#[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; -#[cfg(feature = "std")] -extern crate core; -#[cfg(feature = "std")] -extern crate wasmi; -extern crate hash_db; -extern crate hash256_std_hasher; - -extern crate sr_std as rstd; - -#[cfg(test)] -extern crate substrate_serializer; - -#[cfg(test)] -extern crate heapsize; - -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; - +/// Initalise a key-value collection from array. +/// +/// Creates a vector of given pairs and calls `collect` on the iterator from it. +/// Can be used to create a `HashMap`. #[macro_export] macro_rules! map { ($( $name:expr => $value:expr ),*) => ( @@ -82,26 +34,32 @@ macro_rules! map { use rstd::prelude::*; use rstd::ops::Deref; +use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use std::borrow::Cow; +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; #[cfg(feature = "std")] -pub mod bytes; +pub use impl_serde::serialize as bytes; + #[cfg(feature = "std")] pub mod hashing; #[cfg(feature = "std")] pub use hashing::{blake2_256, twox_128, twox_256}; #[cfg(feature = "std")] pub mod hexdisplay; -#[cfg(feature = "std")] -pub mod ed25519; +pub mod crypto; pub mod u32_trait; +pub mod ed25519; +pub mod sr25519; pub mod hash; mod hasher; pub mod sandbox; pub mod storage; pub mod uint; -mod authority_id; mod changes_trie; #[cfg(test)] @@ -109,17 +67,15 @@ mod tests; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; -pub use authority_id::AuthorityId; pub use changes_trie::ChangesTrieConfiguration; +#[cfg(feature = "std")] +pub use crypto::{DeriveJunction, Pair}; pub use hash_db::Hasher; // Switch back to Blake after PoC-3 is out // pub use self::hasher::blake::BlakeHasher; pub use self::hasher::blake2::Blake2Hasher; -/// A 512-bit value interpreted as a signature. -pub type Signature = hash::H512; - /// Hex-serialised shim for `Vec`. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))] @@ -139,7 +95,7 @@ impl Deref for Bytes { } /// Stores the encoded `RuntimeMetadata` for the native side as opaque type. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, PartialEq)] pub struct OpaqueMetadata(Vec); impl OpaqueMetadata { @@ -156,3 +112,72 @@ impl rstd::ops::Deref for OpaqueMetadata { &self.0 } } + +/// Something that is either a native or an encoded value. +#[cfg(feature = "std")] +pub enum NativeOrEncoded { + /// The native representation. + Native(R), + /// The encoded representation. + Encoded(Vec) +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for NativeOrEncoded { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + self.as_encoded().as_ref().fmt(f) + } +} + +#[cfg(feature = "std")] +impl NativeOrEncoded { + /// Return the value as the encoded format. + pub fn as_encoded<'a>(&'a self) -> Cow<'a, [u8]> { + match self { + NativeOrEncoded::Encoded(e) => Cow::Borrowed(e.as_slice()), + NativeOrEncoded::Native(n) => Cow::Owned(n.encode()), + } + } + + /// Return the value as the encoded format. + pub fn into_encoded(self) -> Vec { + match self { + NativeOrEncoded::Encoded(e) => e, + NativeOrEncoded::Native(n) => n.encode(), + } + } +} + +#[cfg(feature = "std")] +impl PartialEq for NativeOrEncoded { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (NativeOrEncoded::Native(l), NativeOrEncoded::Native(r)) => l == r, + (NativeOrEncoded::Native(n), NativeOrEncoded::Encoded(e)) | + (NativeOrEncoded::Encoded(e), NativeOrEncoded::Native(n)) => + Some(n) == parity_codec::Decode::decode(&mut &e[..]).as_ref(), + (NativeOrEncoded::Encoded(l), NativeOrEncoded::Encoded(r)) => l == r, + } + } +} + +/// A value that is never in a native representation. +/// This is type is useful in conjuction with `NativeOrEncoded`. +#[cfg(feature = "std")] +#[derive(PartialEq)] +pub enum NeverNativeValue {} + +#[cfg(feature = "std")] +impl parity_codec::Encode for NeverNativeValue { + fn encode(&self) -> Vec { + // The enum is not constructable, so this function should never be callable! + unreachable!() + } +} + +#[cfg(feature = "std")] +impl parity_codec::Decode for NeverNativeValue { + fn decode(_: &mut I) -> Option { + None + } +} diff --git a/core/primitives/src/sandbox.rs b/core/primitives/src/sandbox.rs index 2e3144b24ff25552657460e9b44066838f62c8f8..773a6b489330986c2e60a91c182a6bdd2ab187a0 100644 --- a/core/primitives/src/sandbox.rs +++ b/core/primitives/src/sandbox.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,7 @@ //! Definition of a sandbox environment. -#[cfg(test)] -use codec::Encode; +use parity_codec::{Encode, Decode}; use rstd::vec::Vec; /// Error error that can be returned from host function. @@ -165,7 +164,7 @@ pub const MEM_UNLIMITED: u32 = -1i32 as u32; /// For FFI purposes. pub const ERR_OK: u32 = 0; -/// Validation or instantiation error occured when creating new +/// Validation or instantiation error occurred when creating new /// sandboxed module instance. /// /// For FFI purposes. @@ -185,7 +184,7 @@ pub const ERR_EXECUTION: u32 = -3i32 as u32; mod tests { use super::*; use std::fmt; - use codec::Codec; + use parity_codec::Codec; fn roundtrip(s: S) { let encoded = s.encode(); diff --git a/core/primitives/src/sr25519.rs b/core/primitives/src/sr25519.rs new file mode 100644 index 0000000000000000000000000000000000000000..f6e135ebef32460ba565390f632a8c64505fc1f0 --- /dev/null +++ b/core/primitives/src/sr25519.rs @@ -0,0 +1,652 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Simple sr25519 (Schnorr-Ristretto) API. +//! +//! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` +//! for this to work. +// end::description[] + +#[cfg(feature = "std")] +use rand::rngs::OsRng; +#[cfg(feature = "std")] +use schnorrkel::{signing_context, Keypair, SecretKey, MiniSecretKey, PublicKey, + derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH} +}; +#[cfg(feature = "std")] +use substrate_bip39::mini_secret_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "std")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Derive, Ss58Codec}; +use crate::{hash::{H256, H512}, crypto::UncheckedFrom}; +use parity_codec::{Encode, Decode}; + +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] +use schnorrkel::keys::MINI_SECRET_KEY_LENGTH; + +// signing context +#[cfg(feature = "std")] +const SIGNING_CTX: &[u8] = b"substrate"; + +/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); + +/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. +#[cfg(feature = "std")] +pub struct Pair(Keypair); + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl From for [u8; 32] { + fn from(x: Public) -> [u8; 32] { + x.0 + } +} + +impl From for H256 { + fn from(x: Public) -> H256 { + x.0.into() + } +} + +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} + +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +/// An Schnorrkel/Ristretto x25519 ("sr25519") signature. +/// +/// Instead of importing it for the local module, alias it to be available as a public type +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +impl AsRef<[u8; 64]> for Signature { + fn as_ref(&self) -> &[u8; 64] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl From for Signature { + fn from(s: schnorrkel::Signature) -> Signature { + Signature(s.to_bytes()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} + +/// A localized signature also contains sender information. +/// NOTE: Encode and Decode traits are supported in ed25519 but not possible for now here. +#[cfg(feature = "std")] +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct LocalizedSignature { + /// The signer of the signature. + pub signer: Public, + /// The signature itself. + pub signature: Signature, +} + +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } + + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } + + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) + } +} + +#[cfg(feature = "std")] +impl Derive for Public { + /// Derive a child key from a series of given junctions. + /// + /// `None` if there are any hard junctions in there. + fn derive>(&self, path: Iter) -> Option { + let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; + for j in path { + match j { + DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(_cc) => return None, + } + } + Some(Self(acc.to_bytes())) + } +} + +impl Public { + /// A new instance from the given 32-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_raw(data: [u8; 32]) -> Self { + Public(data) + } + + /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } + + /// A new instance from an H256. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_h256(x: H256) -> Self { + Public(x.into()) + } + + /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] + pub fn to_raw_vec(self) -> Vec { + let r: &[u8; 32] = self.as_ref(); + r.to_vec() + } + + /// Return a slice filled with raw data. + pub fn as_slice(&self) -> &[u8] { + let r: &[u8; 32] = self.as_ref(); + &r[..] + } + + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 32] { + self.as_ref() + } +} + +#[cfg(feature = "std")] +impl AsRef for Pair { + fn as_ref(&self) -> &Pair { + &self + } +} + +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: MiniSecretKey) -> Pair { + Pair(sec.expand_to_keypair()) + } +} + +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: SecretKey) -> Pair { + Pair(Keypair::from(sec)) + } +} + +#[cfg(feature = "std")] +impl From for Pair { + fn from(p: schnorrkel::Keypair) -> Pair { + Pair(p) + } +} + +#[cfg(feature = "std")] +impl From for schnorrkel::Keypair { + fn from(p: Pair) -> schnorrkel::Keypair { + p.0 + } +} + +#[cfg(feature = "std")] +impl AsRef for Pair { + fn as_ref(&self) -> &schnorrkel::Keypair { + &self.0 + } +} + +/// Derive a single hard junction. +#[cfg(feature = "std")] +fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> SecretKey { + secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0.expand() +} + +#[cfg(feature = "std")] +type Seed = [u8; MINI_SECRET_KEY_LENGTH]; + +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = Infallible; + + /// Generate new secure (random) key pair. + fn generate() -> Pair { + let mut csprng: OsRng = OsRng::new().expect("os random generator works; qed"); + let key_pair: Keypair = Keypair::generate(&mut csprng); + Pair(key_pair) + } + + /// Make a new key pair from raw secret seed material. + /// + /// This is generated using schnorrkel's Mini-Secret-Keys. + /// + /// A MiniSecretKey is literally what Ed25519 calls a SecretKey, which is just 32 random bytes. + fn from_seed(seed: Seed) -> Pair { + let mini_key: MiniSecretKey = MiniSecretKey::from_bytes(&seed[..]) + .expect("32 bytes can always build a key; qed"); + let kp = mini_key.expand_to_keypair(); + Pair(kp) + } + + /// Get the public key. + fn public(&self) -> Public { + let mut pk = [0u8; 32]; + pk.copy_from_slice(&self.0.public.to_bytes()); + Public(pk) + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase(), from_phrase() + fn from_seed_slice(seed: &[u8]) -> Result { + if seed.len() != MINI_SECRET_KEY_LENGTH { + Err(SecretStringError::InvalidSeedLength) + } else { + Ok(Pair( + MiniSecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .expand_to_keypair() + )) + } + } + + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)? + .derive(path) + .map_err(|_| SecretStringError::InvalidPath) + } + + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) + } + + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase) + .map(|m| Self::from_entropy(m.entropy(), password)) + } + + fn derive>(&self, path: Iter) -> Result { + let init = self.0.secret.clone(); + let result = path.fold(init, |acc, j| match j { + DeriveJunction::Soft(cc) => acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(cc) => derive_hard_junction(&acc, &cc), + }); + Ok(Self(result.into())) + } + + fn sign(&self, message: &[u8]) -> Signature { + let context = signing_context(SIGNING_CTX); + self.0.sign(context.bytes(message)).into() + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig.as_ref()) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref().as_slice()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(sig) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } + } +} + +#[cfg(feature = "std")] +impl Pair { + /// Make a new key pair from binary data derived from a valid seed phrase. + /// + /// This uses a key derivation function to convert the entropy into a seed, then returns + /// the pair generated from it. + pub fn from_entropy(entropy: &[u8], password: Option<&str>) -> Pair { + let mini_key: MiniSecretKey = mini_secret_from_entropy(entropy, password.unwrap_or("")) + .expect("32 bytes can always build a key; qed"); + let kp = mini_key.expand_to_keypair(); + Pair(kp) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{Pair as _Pair, crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS}}; + use hex_literal::{hex, hex_impl}; + + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); + assert_eq!( + Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).as_ref().map(Pair::public), + Pair::from_string("/Alice", None).as_ref().map(Pair::public) + ); + } + + #[test] + fn default_address_should_be_used() { + assert_eq!( + Public::from_string(&format!("{}/Alice", DEV_ADDRESS)), + Public::from_string("/Alice") + ); + } + + #[test] + fn default_phrase_should_correspond_to_default_address() { + assert_eq!( + Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).unwrap().public(), + Public::from_string(&format!("{}/Alice", DEV_ADDRESS)).unwrap(), + ); + assert_eq!( + Pair::from_string("/Alice", None).unwrap().public(), + Public::from_string("/Alice").unwrap() + ); + } + + #[test] + fn derive_soft_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter()).unwrap(); + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_hard_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter()).unwrap(); + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_soft_public_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let path = Some(DeriveJunction::soft(1)); + let pair_1 = pair.derive(path.clone().into_iter()).unwrap(); + let public_1 = pair.public().derive(path.into_iter()).unwrap(); + assert_eq!(pair_1.public(), public_1); + } + + #[test] + fn derive_hard_public_should_fail() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let path = Some(DeriveJunction::hard(1)); + assert!(pair.public().derive(path.into_iter()).is_none()); + } + + #[test] + fn sr_test_vector_should_work() { + let pair: Pair = Pair::from_seed(hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let public = pair.public(); + assert_eq!( + public, + Public::from_raw(hex!( + "44a996beb1eef7bdcab976ab6d2ca26104834164ecf28fb375600576fcc6eb0f" + )) + ); + let message = b""; + let signature = pair.sign(message); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::generate(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!( + public, + Public::from_raw(hex!( + "741c08a06f41c596608f6774259bd9043304adfa5d3eea62760bd9be97634d63" + )) + ); + let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); + let signature = pair.sign(&message[..]); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn ss58check_roundtrip_works() { + let pair = Pair::generate(); + let public = pair.public(); + let s = public.to_ss58check(); + println!("Correct: {}", s); + let cmp = Public::from_ss58check(&s).unwrap(); + assert_eq!(cmp, public); + } + + #[test] + fn ss58check_known_works() { + let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9"; + let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"]; + assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc)); + } + + #[test] + fn verify_from_wasm_works() { + // The values in this test case are compared to the output of `node-test.js` in schnorrkel-js. + // + // This is to make sure that the wasm library is compatible. + let pk = Pair::from_seed(hex!("0000000000000000000000000000000000000000000000000000000000000000")); + let public = pk.public(); + let js_signature = Signature::from_raw(hex!("28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00")); + assert!(Pair::verify(&js_signature, b"SUBSTRATE", public)); + } +} diff --git a/core/primitives/src/storage.rs b/core/primitives/src/storage.rs index f3b22294bde1342fb48396447a687dcb4129a5b0..79652a8d4ce3a211ac3490e57ebe4fa27164aabf 100644 --- a/core/primitives/src/storage.rs +++ b/core/primitives/src/storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,9 @@ //! Contract execution data. #[cfg(feature = "std")] -use bytes; +use serde_derive::{Serialize, Deserialize}; +#[cfg(feature = "std")] +use crate::bytes; use rstd::vec::Vec; /// Contract storage key. @@ -32,6 +34,7 @@ pub struct StorageData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec /// Storage change set #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, PartialEq, Eq))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] pub struct StorageChangeSet { /// Block hash pub block: Hash, @@ -70,6 +73,9 @@ pub mod well_known_keys { /// Current extrinsic index (u32) is stored under this key. pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; + /// Sum of all lengths of executed extrinsics (u32). + pub const ALL_EXTRINSICS_LEN: &'static [u8] = b":all_extrinsics_len"; + /// Changes trie configuration is stored under this key. pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; diff --git a/core/primitives/src/tests.rs b/core/primitives/src/tests.rs index 2205e4ac7ac808ee1226f3cd040966068e42ec49..2dbaed2b0faabdf2910f4b91f8b626dc5220c542 100644 --- a/core/primitives/src/tests.rs +++ b/core/primitives/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/u32_trait.rs b/core/primitives/src/u32_trait.rs index 88ee6bf29b277a88c264871dbeb1bad8ce85970d..3fcdceac4cbbfacea532c498648ccee980a0e36c 100644 --- a/core/primitives/src/u32_trait.rs +++ b/core/primitives/src/u32_trait.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/primitives/src/uint.rs b/core/primitives/src/uint.rs index 4727ed54bd0694199b6088d49b63fb358bd7fea1..dfea51921dc331ef5936fac83746da014fa0b5b1 100644 --- a/core/primitives/src/uint.rs +++ b/core/primitives/src/uint.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,60 +16,12 @@ //! An unsigned fixed-size integer. -#[cfg(feature = "std")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - -#[cfg(feature = "std")] -use bytes; - -macro_rules! impl_serde { - ($name: ident, $len: expr) => { - #[cfg(feature = "std")] - impl Serialize for $name { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut bytes = [0u8; $len * 8]; - self.to_big_endian(&mut bytes); - bytes::serialize_uint(&bytes, serializer) - } - } - - #[cfg(feature = "std")] - impl<'de> Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Between(0, $len * 8)) - .map(|x| (&*x).into()) - } - } - } -} - -macro_rules! impl_codec { - ($name: ident, $len: expr) => { - impl ::codec::Encode for $name { - fn using_encoded R>(&self, f: F) -> R { - let mut bytes = [0u8; $len * 8]; - self.to_little_endian(&mut bytes); - bytes.using_encoded(f) - } - } - - impl ::codec::Decode for $name { - fn decode(input: &mut I) -> Option { - <[u8; $len * 8] as ::codec::Decode>::decode(input) - .map(|b| $name::from_little_endian(&b)) - } - } - } -} - -construct_uint!(U256, 4); -impl_serde!(U256, 4); -impl_codec!(U256, 4); +pub use primitive_types::U256; #[cfg(test)] mod tests { use super::*; - use codec::{Encode, Decode}; + use parity_codec::{Encode, Decode}; use substrate_serializer as ser; macro_rules! test { diff --git a/core/rpc-servers/Cargo.toml b/core/rpc-servers/Cargo.toml index f3c0ae9906c3784027c0dc910b5cf4fc49788642..9b744eaaa6f692e494f83ffc03e02c744797f3aa 100644 --- a/core/rpc-servers/Cargo.toml +++ b/core/rpc-servers/Cargo.toml @@ -2,11 +2,12 @@ name = "substrate-rpc-servers" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git" } -jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git" } -jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git" } +http = { package = "jsonrpc-http-server", version = "10.0.1" } +pubsub = { package = "jsonrpc-pubsub", version = "10.0.1" } +ws = { package = "jsonrpc-ws-server", version = "10.0.1" } log = "0.4" serde = "1.0" substrate-rpc = { path = "../rpc", version = "0.1" } diff --git a/core/rpc-servers/src/lib.rs b/core/rpc-servers/src/lib.rs index ec823b15fd2b7cc19362fbd186eab83fa6960ac3..939b2b93aa58abd511d665a50162b252d76cad0e 100644 --- a/core/rpc-servers/src/lib.rs +++ b/core/rpc-servers/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,18 +18,10 @@ #[warn(missing_docs)] -pub extern crate substrate_rpc as apis; - -extern crate jsonrpc_http_server as http; -extern crate jsonrpc_pubsub as pubsub; -extern crate jsonrpc_ws_server as ws; -extern crate serde; -extern crate sr_primitives; - -#[macro_use] -extern crate log; +pub use substrate_rpc as apis; use std::io; +use log::error; use sr_primitives::{traits::{Block as BlockT, NumberFor}, generic::SignedBlock}; /// Maximal payload accepted by RPC servers @@ -49,11 +41,10 @@ pub fn rpc_handler( ) -> RpcHandler where Block: BlockT + 'static, ExHash: Send + Sync + 'static + sr_primitives::Serialize + sr_primitives::DeserializeOwned, - SignedBlock: serde::Serialize + sr_primitives::DeserializeOwned, S: apis::state::StateApi, - C: apis::chain::ChainApi, SignedBlock, Metadata=Metadata>, + C: apis::chain::ChainApi, Block::Hash, Block::Header, SignedBlock, Metadata=Metadata>, A: apis::author::AuthorApi, - Y: apis::system::SystemApi, + Y: apis::system::SystemApi>, { let mut io = pubsub::PubSubHandler::default(); io.extend_with(state.to_delegate()); diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index f3e9489f9e44a4be291379426f56b64d6f21b3d5..8998ebe81f5e4b08217838a3e090f0c0e040a1ae 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -2,30 +2,35 @@ name = "substrate-rpc" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] error-chain = "0.12" -jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" } -jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" } -jsonrpc-pubsub = { git="https://github.com/paritytech/jsonrpc.git" } +jsonrpc-core = "10.0.1" +jsonrpc-pubsub = "10.0.1" +jsonrpc-derive = "10.0.2" log = "0.4" -parking_lot = "0.4" -parity-codec = "2.1" +parking_lot = "0.7.1" +parity-codec = "3.2" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -substrate-client = { path = "../client" } +client = { package = "substrate-client", path = "../client" } substrate-executor = { path = "../executor" } -substrate-network = { path = "../network" } -substrate-primitives = { path = "../primitives" } -substrate-transaction-pool = { path = "../transaction-pool" } -sr-primitives = { path = "../sr-primitives" } -sr-version = { path = "../sr-version" } +network = { package = "substrate-network", path = "../network" } +primitives = { package = "substrate-primitives", path = "../primitives" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } +runtime_version = { package = "sr-version", path = "../sr-version" } tokio = "0.1.7" [dev-dependencies] assert_matches = "1.1" -substrate-test-client = { path = "../test-client" } -substrate-consensus-common = { path = "../consensus/common" } +futures = "0.1.17" +sr-io = { path = "../sr-io" } +test_client = { package = "substrate-test-client", path = "../test-client" } +test_runtime = { package = "substrate-test-runtime", path = "../test-runtime" } +consensus = { package = "substrate-consensus-common", path = "../consensus/common" } rustc-hex = "2.0" hex-literal = "0.1" diff --git a/core/rpc/src/author/error.rs b/core/rpc/src/author/error.rs index 32f48096469d09f64027e808b46c397467380648..9c1ec232252001e10640e655f091cd970417559b 100644 --- a/core/rpc/src/author/error.rs +++ b/core/rpc/src/author/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,11 +16,12 @@ //! Authoring RPC module errors. +use error_chain::*; use client; use transaction_pool::txpool; -use rpc; +use crate::rpc; -use errors; +use crate::errors; error_chain! { links { @@ -46,22 +47,77 @@ error_chain! { } } -const ERROR: i64 = 1000; +/// 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 transaction verification in runtime. +const VERIFICATION_ERROR: i64 = BASE_ERROR + 2; + +/// Pool rejected the transaction as invalid +const POOL_INVALID_TX: i64 = BASE_ERROR + 10; +/// Cannot determine transaction validity. +const POOL_UNKNOWN_VALIDITY: i64 = POOL_INVALID_TX + 1; +/// The transaction is temporarily banned. +const POOL_TEMPORARILY_BANNED: i64 = POOL_INVALID_TX + 2; +/// The transaction is already in the pool +const POOL_ALREADY_IMPORTED: i64 = POOL_INVALID_TX + 3; +/// Transaction has too low priority to replace existing one in the pool. +const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4; +/// Including this transaction would cause a dependency cycle. +const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5; +/// The transaction was not included to the pool because of the limits. +const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6; impl From for rpc::Error { fn from(e: Error) -> Self { match e { Error(ErrorKind::Unimplemented, _) => errors::unimplemented(), Error(ErrorKind::BadFormat, _) => rpc::Error { - code: rpc::ErrorCode::ServerError(ERROR + 1), + code: rpc::ErrorCode::ServerError(BAD_FORMAT), message: "Extrinsic has invalid format.".into(), data: None, }, Error(ErrorKind::Verification(e), _) => rpc::Error { - code: rpc::ErrorCode::ServerError(ERROR + 2), + code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR), message: e.description().into(), data: Some(format!("{:?}", e).into()), }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::InvalidTransaction(code)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), + message: "Invalid Transaction".into(), + data: Some(code.into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::UnknownTransactionValidity(code)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), + message: "Unknown Transaction Validity".into(), + data: Some(code.into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::TemporarilyBanned), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), + message: "Transaction is temporarily banned".into(), + data: None, + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::AlreadyImported(hash)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_ALREADY_IMPORTED), + message: "Transaction Already Imported".into(), + data: Some(format!("{:?}", hash).into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::TooLowPriority(old, new)), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_TOO_LOW_PRIORITY), + message: format!("Priority is too low: ({} vs {})", old, new), + data: Some("The transaction has too low priority to replace another transaction already in the pool.".into()), + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::CycleDetected), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_CYCLE_DETECTED), + message: "Cycle Detected".into(), + data: None, + }, + Error(ErrorKind::Pool(txpool::error::ErrorKind::ImmediatelyDropped), _) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED), + message: "Immediately Dropped" .into(), + data: Some("The transaction couldn't enter the pool because of the limit".into()), + }, e => errors::internal(e), } } diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index 7e2603552533ebbfcdcc2112ac51780b45b2c13e..acd500ba0bfe309ddec5c36c698f0cb5a71473e0 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,8 +18,9 @@ use std::sync::Arc; +use log::warn; use client::{self, Client}; -use codec::{Encode, Decode}; +use parity_codec::{Encode, Decode}; use transaction_pool::{ txpool::{ ChainApi as PoolChainApi, @@ -30,12 +31,12 @@ use transaction_pool::{ watcher::Status, }, }; -use jsonrpc_macros::pubsub; -use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use primitives::{Bytes, Blake2Hasher, H256}; -use rpc::futures::{Sink, Stream, Future}; +use crate::rpc::futures::{Sink, Stream, Future}; use runtime_primitives::{generic, traits}; -use subscriptions::Subscriptions; +use crate::subscriptions::Subscriptions; pub mod error; @@ -44,30 +45,27 @@ mod tests; use self::error::Result; -build_rpc_trait! { - /// Substrate authoring RPC API - pub trait AuthorApi { - type Metadata; +/// Substrate authoring RPC API +#[rpc] +pub trait AuthorApi { + /// RPC metadata + type Metadata; - /// Submit hex-encoded extrinsic for inclusion in block. - #[rpc(name = "author_submitExtrinsic")] - fn submit_extrinsic(&self, Bytes) -> Result; + /// Submit hex-encoded extrinsic for inclusion in block. + #[rpc(name = "author_submitExtrinsic")] + fn submit_extrinsic(&self, extrinsic: Bytes) -> Result; - /// Returns all pending extrinsics, potentially grouped by sender. - #[rpc(name = "author_pendingExtrinsics")] - fn pending_extrinsics(&self) -> Result>; + /// Returns all pending extrinsics, potentially grouped by sender. + #[rpc(name = "author_pendingExtrinsics")] + fn pending_extrinsics(&self) -> Result>; - #[pubsub(name = "author_extrinsicUpdate")] { - /// Submit an extrinsic to watch. - #[rpc(name = "author_submitAndWatchExtrinsic")] - fn watch_extrinsic(&self, Self::Metadata, pubsub::Subscriber>, Bytes); + /// Submit an extrinsic to watch. + #[pubsub(subscription = "author_extrinsicUpdate", subscribe, name = "author_submitAndWatchExtrinsic")] + fn watch_extrinsic(&self, metadata: Self::Metadata, subscriber: Subscriber>, bytes: Bytes); - /// Unsubscribe from extrinsic watching. - #[rpc(name = "author_unwatchExtrinsic")] - fn unwatch_extrinsic(&self, Self::Metadata, SubscriptionId) -> Result; - } - - } + /// Unsubscribe from extrinsic watching. + #[pubsub(subscription = "author_extrinsicUpdate", unsubscribe, name = "author_unwatchExtrinsic")] + fn unwatch_extrinsic(&self, metadata: Option, id: SubscriptionId) -> Result; } /// Authoring API @@ -103,7 +101,7 @@ impl AuthorApi, BlockHash

> for Author whe P::Error: 'static, RA: Send + Sync + 'static { - type Metadata = ::metadata::Metadata; + type Metadata = crate::metadata::Metadata; fn submit_extrinsic(&self, ext: Bytes) -> Result> { let xt = Decode::decode(&mut &ext[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?; @@ -120,7 +118,7 @@ impl AuthorApi, BlockHash

> for Author whe Ok(self.pool.ready().map(|tx| tx.data.encode().into()).collect()) } - fn watch_extrinsic(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber, BlockHash

>>, xt: Bytes) { + fn watch_extrinsic(&self, _metadata: Self::Metadata, subscriber: Subscriber, BlockHash

>>, xt: Bytes) { let submit = || -> Result<_> { let best_block_hash = self.client.info()?.chain.best_hash; let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..]).ok_or(error::Error::from(error::ErrorKind::BadFormat))?; @@ -149,7 +147,7 @@ impl AuthorApi, BlockHash

> for Author whe }) } - fn unwatch_extrinsic(&self, _metadata: Self::Metadata, id: SubscriptionId) -> Result { + fn unwatch_extrinsic(&self, _metadata: Option, id: SubscriptionId) -> Result { Ok(self.subscriptions.cancel(id)) } } diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index 82f5d371626ad590c1bcd2c37af137cbe8d10f4a..53166e76f82ea01f48395472b47e48c5d49c79a0 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,26 +17,25 @@ use super::*; use std::sync::Arc; -use codec::Encode; +use assert_matches::assert_matches; +use parity_codec::Encode; use transaction_pool::{ txpool::Pool, ChainApi, }; -use primitives::H256; -use test_client::keyring::Keyring; -use test_client::runtime::{Extrinsic, Transfer}; -use test_client; +use primitives::{H256, blake2_256, hexdisplay::HexDisplay}; +use test_client::{self, AccountKeyring, runtime::{Extrinsic, Transfer}}; use tokio::runtime; -fn uxt(sender: Keyring, nonce: u64) -> Extrinsic { +fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { let tx = Transfer { amount: Default::default(), nonce, - from: sender.to_raw_public().into(), + from: sender.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); - Extrinsic { transfer: tx, signature } + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); + Extrinsic::Transfer(tx, signature) } #[test] @@ -48,14 +47,15 @@ fn submit_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("e10ad66bce51ef3e2a1167934ce3740d2d8c703810f9b314e89f2e783f75e826").into(); + let xt = uxt(AccountKeyring::Alice, 1).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -68,14 +68,15 @@ fn submit_rich_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("fccc48291473c53746cd267cf848449edd7711ee6511fba96919d5f9f4859e4f").into(); + let xt = uxt(AccountKeyring::Alice, 0).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -90,10 +91,10 @@ fn should_watch_extrinsic() { pool: pool.clone(), subscriptions: Subscriptions::new(runtime.executor()), }; - let (subscriber, id_rx, data) = ::jsonrpc_macros::pubsub::Subscriber::new_test("test"); + let (subscriber, id_rx, data) = ::jsonrpc_pubsub::typed::Subscriber::new_test("test"); // when - p.watch_extrinsic(Default::default(), subscriber, uxt(Keyring::Alice, 0).encode().into()); + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); // then assert_eq!(runtime.block_on(id_rx), Ok(Ok(1.into()))); @@ -102,11 +103,11 @@ fn should_watch_extrinsic() { let tx = Transfer { amount: 5, nonce: 0, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); - Extrinsic { transfer: tx, signature } + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); + Extrinsic::Transfer(tx, signature) }; AuthorApi::submit_extrinsic(&p, replacement.encode().into()).unwrap(); let (res, data) = runtime.block_on(data.into_future()).unwrap(); @@ -114,9 +115,10 @@ fn should_watch_extrinsic() { res, Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) ); + let h = blake2_256(&replacement.encode()); assert_eq!( runtime.block_on(data.into_future()).unwrap().0, - Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"usurped":"0xed454dcee51431679c2559403187a56567fded1fc50b6ae3aada87c1d412df5c"},"subscription":1}}"#.into()) + Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) ); } @@ -130,7 +132,7 @@ fn should_return_pending_extrinsics() { pool: pool.clone(), subscriptions: Subscriptions::new(runtime.executor()), }; - let ex = uxt(Keyring::Alice, 0); + let ex = uxt(AccountKeyring::Alice, 0); AuthorApi::submit_extrinsic(&p, ex.encode().into()).unwrap(); assert_matches!( p.pending_extrinsics(), diff --git a/core/rpc/src/chain/error.rs b/core/rpc/src/chain/error.rs index d7d8b3a63c22d4532cc5700c5ebdbc23dbc60c44..c52d44eddc3392d6a35fa4ec2dc292cb677b2a58 100644 --- a/core/rpc/src/chain/error.rs +++ b/core/rpc/src/chain/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use error_chain::*; use client; -use rpc; - -use errors; +use crate::rpc; +use crate::errors; error_chain! { links { diff --git a/core/rpc/src/chain/mod.rs b/core/rpc/src/chain/mod.rs index c4e0899fa17cddfba61fbde7bcf264b96536c3b3..9b7f5a909e449098c917cc5485e0fb531dc668c8 100644 --- a/core/rpc/src/chain/mod.rs +++ b/core/rpc/src/chain/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,66 +18,82 @@ use std::sync::Arc; +use log::warn; use client::{self, Client, BlockchainEvents}; -use jsonrpc_macros::{pubsub, Trailing}; -use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use primitives::{H256, Blake2Hasher}; -use rpc::Result as RpcResult; -use rpc::futures::{stream, Future, Sink, Stream}; +use crate::rpc::Result as RpcResult; +use crate::rpc::futures::{stream, Future, Sink, Stream}; use runtime_primitives::generic::{BlockId, SignedBlock}; use runtime_primitives::traits::{Block as BlockT, Header, NumberFor}; -use subscriptions::Subscriptions; +use crate::subscriptions::Subscriptions; mod error; #[cfg(test)] mod tests; +mod number; use self::error::Result; -build_rpc_trait! { - /// Substrate blockchain API - pub trait ChainApi { - type Metadata; - - /// Get header of a relay chain block. - #[rpc(name = "chain_getHeader")] - fn header(&self, Trailing) -> Result>; - - /// Get header and body of a relay chain block. - #[rpc(name = "chain_getBlock")] - fn block(&self, Trailing) -> Result>; - - /// Get hash of the n-th block in the canon chain. - /// - /// By default returns latest block hash. - #[rpc(name = "chain_getBlockHash", alias = ["chain_getHead", ])] - fn block_hash(&self, Trailing) -> Result>; - - /// Get hash of the last finalised block in the canon chain. - #[rpc(name = "chain_getFinalisedHead")] - fn finalised_head(&self) -> Result; - - #[pubsub(name = "chain_newHead")] { - /// New head subscription - #[rpc(name = "chain_subscribeNewHead", alias = ["subscribe_newHead", ])] - fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber

); - - /// Unsubscribe from new head subscription. - #[rpc(name = "chain_unsubscribeNewHead", alias = ["unsubscribe_newHead", ])] - fn unsubscribe_new_head(&self, Self::Metadata, SubscriptionId) -> RpcResult; - } - - #[pubsub(name = "chain_finalisedHead")] { - /// New head subscription - #[rpc(name = "chain_subscribeFinalisedHeads")] - fn subscribe_finalised_heads(&self, Self::Metadata, pubsub::Subscriber
); - - /// Unsubscribe from new head subscription. - #[rpc(name = "chain_unsubscribeFinalisedHeads")] - fn unsubscribe_finalised_heads(&self, Self::Metadata, SubscriptionId) -> RpcResult; - } - } +/// Substrate blockchain API +#[rpc] +pub trait ChainApi { + /// RPC metadata + type Metadata; + + /// Get header of a relay chain block. + #[rpc(name = "chain_getHeader")] + fn header(&self, hash: Option) -> Result>; + + /// Get header and body of a relay chain block. + #[rpc(name = "chain_getBlock")] + fn block(&self, hash: Option) -> Result>; + + /// Get hash of the n-th block in the canon chain. + /// + /// By default returns latest block hash. + #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] + fn block_hash(&self, hash: Option>) -> Result>; + + /// Get hash of the last finalised block in the canon chain. + #[rpc(name = "chain_getFinalisedHead")] + fn finalised_head(&self) -> Result; + + /// New head subscription + #[pubsub( + subscription = "chain_newHead", + subscribe, + name = "chain_subscribeNewHead", + alias("subscribe_newHead") + )] + fn subscribe_new_head(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_newHead", + unsubscribe, + name = "chain_unsubscribeNewHead", + alias("unsubscribe_newHead") + )] + fn unsubscribe_new_head(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + + /// New head subscription + #[pubsub( + subscription = "chain_finalisedHead", + subscribe, + name = "chain_subscribeFinalisedHeads" + )] + fn subscribe_finalised_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_finalisedHead", + unsubscribe, + name = "chain_unsubscribeFinalisedHeads" + )] + fn unsubscribe_finalised_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; } /// Chain API with subscriptions support. @@ -104,7 +120,7 @@ impl Chain where E: client::CallExecutor + Send + Sync + 'static, RA: Send + Sync + 'static { - fn unwrap_or_best(&self, hash: Trailing) -> Result { + fn unwrap_or_best(&self, hash: Option) -> Result { Ok(match hash.into() { None => self.client.info()?.chain.best_hash, Some(hash) => hash, @@ -113,7 +129,7 @@ impl Chain where fn subscribe_headers( &self, - subscriber: pubsub::Subscriber, + subscriber: Subscriber, best_block_hash: G, stream: F, ) where @@ -148,30 +164,31 @@ impl Chain where } } -impl ChainApi, SignedBlock> for Chain where +impl ChainApi, Block::Hash, Block::Header, SignedBlock> for Chain where Block: BlockT + 'static, B: client::backend::Backend + Send + Sync + 'static, E: client::CallExecutor + Send + Sync + 'static, RA: Send + Sync + 'static { - type Metadata = ::metadata::Metadata; + type Metadata = crate::metadata::Metadata; - fn header(&self, hash: Trailing) -> Result> { + fn header(&self, hash: Option) -> Result> { let hash = self.unwrap_or_best(hash)?; Ok(self.client.header(&BlockId::Hash(hash))?) } - fn block(&self, hash: Trailing) + fn block(&self, hash: Option) -> Result>> { let hash = self.unwrap_or_best(hash)?; Ok(self.client.block(&BlockId::Hash(hash))?) } - fn block_hash(&self, number: Trailing>) -> Result> { - Ok(match number.into() { + fn block_hash(&self, number: Option>>) -> Result> { + let number: Option>> = number.into(); + Ok(match number { None => Some(self.client.info()?.chain.best_hash), - Some(number) => self.client.header(&BlockId::number(number))?.map(|h| h.hash()), + Some(num_or_hex) => self.client.header(&BlockId::number(num_or_hex.to_number()?))?.map(|h| h.hash()), }) } @@ -179,7 +196,7 @@ impl ChainApi, Sig Ok(self.client.info()?.chain.finalized_hash) } - fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber) { + fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: Subscriber) { self.subscribe_headers( subscriber, || self.block_hash(None.into()), @@ -189,11 +206,11 @@ impl ChainApi, Sig ) } - fn unsubscribe_new_head(&self, _metadata: Self::Metadata, id: SubscriptionId) -> RpcResult { + fn unsubscribe_new_head(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { Ok(self.subscriptions.cancel(id)) } - fn subscribe_finalised_heads(&self, _meta: Self::Metadata, subscriber: pubsub::Subscriber) { + fn subscribe_finalised_heads(&self, _meta: Self::Metadata, subscriber: Subscriber) { self.subscribe_headers( subscriber, || Ok(Some(self.client.info()?.chain.finalized_hash)), @@ -202,7 +219,7 @@ impl ChainApi, Sig ) } - fn unsubscribe_finalised_heads(&self, _metadata: Self::Metadata, id: SubscriptionId) -> RpcResult { + fn unsubscribe_finalised_heads(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { Ok(self.subscriptions.cancel(id)) } } diff --git a/core/rpc/src/chain/number.rs b/core/rpc/src/chain/number.rs new file mode 100644 index 0000000000000000000000000000000000000000..bdf4b4df03e71f28ecf3a933ad26ac086862a43c --- /dev/null +++ b/core/rpc/src/chain/number.rs @@ -0,0 +1,70 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use serde_derive::Deserialize; +use primitives::U256; +use runtime_primitives::traits; + +/// RPC Block number type +/// +/// We allow two representations of the block number as input. +/// Either we deserialize to the type that is specified in the block type +/// or we attempt to parse given hex value. +/// We do that for consistency with the returned type, default generic header +/// serializes block number as hex to avoid overflows in JavaScript. +#[derive(Deserialize)] +#[serde(untagged)] +pub enum NumberOrHex { + /// The original header number type of block. + Number(Number), + /// Hex representation of the block number. + Hex(U256), +} + +impl> NumberOrHex { + /// Attempts to convert into concrete block number. + /// + /// Fails in case hex number is too big. + pub fn to_number(self) -> Result { + match self { + NumberOrHex::Number(n) => Ok(n), + NumberOrHex::Hex(h) => { + // FIXME #1377 this only supports `u64` since `BlockNumber` + // is `As` we could possibly go with `u128`. + let l = h.low_u64(); + if U256::from(l) != h { + Err(format!("`{}` does not fit into the block number type.", h)) + } else { + Ok(traits::As::sa(l)) + } + }, + } + } +} + +#[cfg(test)] +impl From for NumberOrHex { + fn from(n: u64) -> Self { + NumberOrHex::Number(n) + } +} + +#[cfg(test)] +impl From for NumberOrHex { + fn from(n: U256) -> Self { + NumberOrHex::Hex(n) + } +} diff --git a/core/rpc/src/chain/tests.rs b/core/rpc/src/chain/tests.rs index b3f9ee93e275a927d5cc2021962959762f24ac54..bad3c5aeb8735de4196507711de2550577703175 100644 --- a/core/rpc/src/chain/tests.rs +++ b/core/rpc/src/chain/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,9 +15,9 @@ // along with Substrate. If not, see . use super::*; -use jsonrpc_macros::pubsub; +use assert_matches::assert_matches; use test_client::{self, TestClient}; -use test_client::runtime::{Block, Header}; +use test_client::runtime::{H256, Block, Header}; use consensus::BlockOrigin; #[test] @@ -33,7 +33,7 @@ fn should_return_header() { assert_matches!( client.header(Some(client.client.genesis_hash()).into()), Ok(Some(ref x)) if x == &Header { - parent_hash: 0.into(), + parent_hash: H256::from_low_u64_be(0), number: 0, state_root: x.state_root.clone(), extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), @@ -44,7 +44,7 @@ fn should_return_header() { assert_matches!( client.header(None.into()), Ok(Some(ref x)) if x == &Header { - parent_hash: 0.into(), + parent_hash: H256::from_low_u64_be(0), number: 0, state_root: x.state_root.clone(), extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), @@ -53,7 +53,7 @@ fn should_return_header() { ); assert_matches!( - client.header(Some(5.into()).into()), + client.header(Some(H256::from_low_u64_be(5)).into()), Ok(None) ); } @@ -107,7 +107,7 @@ fn should_return_a_block() { ); assert_matches!( - api.block(Some(5.into()).into()), + api.block(Some(H256::from_low_u64_be(5)).into()), Ok(None) ); } @@ -129,12 +129,12 @@ fn should_return_block_hash() { assert_matches!( - client.block_hash(Some(0u64).into()), + client.block_hash(Some(0u64.into()).into()), Ok(Some(ref x)) if x == &client.client.genesis_hash() ); assert_matches!( - client.block_hash(Some(1u64).into()), + client.block_hash(Some(1u64.into()).into()), Ok(None) ); @@ -142,11 +142,15 @@ fn should_return_block_hash() { client.client.import(BlockOrigin::Own, block.clone()).unwrap(); assert_matches!( - client.block_hash(Some(0u64).into()), + client.block_hash(Some(0u64.into()).into()), Ok(Some(ref x)) if x == &client.client.genesis_hash() ); assert_matches!( - client.block_hash(Some(1u64).into()), + client.block_hash(Some(1u64.into()).into()), + Ok(Some(ref x)) if x == &block.hash() + ); + assert_matches!( + client.block_hash(Some(::primitives::U256::from(1u64).into()).into()), Ok(Some(ref x)) if x == &block.hash() ); } @@ -188,7 +192,7 @@ fn should_return_finalised_hash() { fn should_notify_about_latest_block() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); + let (subscriber, id, transport) = Subscriber::new_test("test"); { let api = Chain { @@ -219,7 +223,7 @@ fn should_notify_about_latest_block() { fn should_notify_about_finalised_block() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); + let (subscriber, id, transport) = Subscriber::new_test("test"); { let api = Chain { diff --git a/core/rpc/src/errors.rs b/core/rpc/src/errors.rs index a9b9e27a9cbc6fb7249c9792398afcff57b409f7..a709013ad26801a471f7dd99d94c6ed10390b78b 100644 --- a/core/rpc/src/errors.rs +++ b/core/rpc/src/errors.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use rpc; +use crate::rpc; +use log::warn; pub fn unimplemented() -> rpc::Error { rpc::Error { diff --git a/core/rpc/src/helpers.rs b/core/rpc/src/helpers.rs index dca1a45db563ddf0103b81e4ff230ab728824f8a..e579c743acdad202caedfd39e760559129c6109f 100644 --- a/core/rpc/src/helpers.rs +++ b/core/rpc/src/helpers.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,7 +15,7 @@ // along with Substrate. If not, see . /// Unwraps the trailing parameter or falls back with the closure result. -pub fn unwrap_or_else(or_else: F, optional: ::jsonrpc_macros::Trailing) -> Result where +pub fn unwrap_or_else(or_else: F, optional: Option) -> Result where F: FnOnce() -> Result, { match optional.into() { diff --git a/core/rpc/src/lib.rs b/core/rpc/src/lib.rs index e96078ff6e33c8016766629ff720373a1984db01..6488ea5f49c54120f5a77dbd1c23e8e16004b3d9 100644 --- a/core/rpc/src/lib.rs +++ b/core/rpc/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,41 +18,6 @@ #![warn(missing_docs)] -extern crate jsonrpc_core as rpc; -extern crate jsonrpc_pubsub; -extern crate parity_codec as codec; -extern crate parking_lot; -extern crate serde_json; -extern crate sr_primitives as runtime_primitives; -extern crate sr_version as runtime_version; -extern crate substrate_client as client; -extern crate substrate_network as network; -extern crate substrate_primitives as primitives; -extern crate substrate_transaction_pool as transaction_pool; -extern crate tokio; - -#[macro_use] -extern crate error_chain; -#[macro_use] -extern crate jsonrpc_macros; -#[macro_use] -extern crate log; -#[macro_use] -extern crate serde_derive; - -#[cfg(test)] -#[macro_use] -extern crate assert_matches; -#[cfg(test)] -#[macro_use] -extern crate hex_literal; -#[cfg(test)] -extern crate substrate_test_client as test_client; -#[cfg(test)] -extern crate substrate_consensus_common as consensus; -#[cfg(test)] -extern crate rustc_hex; - mod errors; mod helpers; mod subscriptions; @@ -64,3 +29,5 @@ pub mod chain; pub mod metadata; pub mod state; pub mod system; + +use jsonrpc_core as rpc; diff --git a/core/rpc/src/metadata.rs b/core/rpc/src/metadata.rs index 06d19d11d8cecd5fbb5598e465859f3586737b23..e6af4ef94bc1adf6fee90eb520630da09ed18942 100644 --- a/core/rpc/src/metadata.rs +++ b/core/rpc/src/metadata.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ use std::sync::Arc; use jsonrpc_pubsub::{Session, PubSubMetadata}; -use rpc::futures::sync::mpsc; +use crate::rpc::futures::sync::mpsc; /// RPC Metadata. /// @@ -30,7 +30,7 @@ pub struct Metadata { session: Option>, } -impl ::rpc::Metadata for Metadata {} +impl crate::rpc::Metadata for Metadata {} impl PubSubMetadata for Metadata { fn session(&self) -> Option> { self.session.clone() diff --git a/core/rpc/src/state/error.rs b/core/rpc/src/state/error.rs index 0a9d57944f0f96ce0771330a6eb94c75dbc1f1f6..bd85664099a5bbed55a79884c764b7e37e255c2a 100644 --- a/core/rpc/src/state/error.rs +++ b/core/rpc/src/state/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use error_chain::*; use client; -use rpc; - -use errors; +use crate::rpc; +use crate::errors; error_chain! { links { diff --git a/core/rpc/src/state/mod.rs b/core/rpc/src/state/mod.rs index d044962f0a09e1f7377f5d0d5b4951ad0910edf2..c2e5f885c99e07d927af7fb8f962ddf2e42b13f2 100644 --- a/core/rpc/src/state/mod.rs +++ b/core/rpc/src/state/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,24 +17,27 @@ //! Substrate state API. use std::{ - collections::HashMap, + collections::{BTreeMap, HashMap}, + ops::Range, sync::Arc, }; +use error_chain::bail; +use log::{warn, trace}; use client::{self, Client, CallExecutor, BlockchainEvents, runtime_api::Metadata}; -use jsonrpc_macros::Trailing; -use jsonrpc_macros::pubsub; -use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use primitives::{H256, Blake2Hasher, Bytes}; use primitives::hexdisplay::HexDisplay; use primitives::storage::{self, StorageKey, StorageData, StorageChangeSet}; -use rpc::Result as RpcResult; -use rpc::futures::{stream, Future, Sink, Stream}; +use crate::rpc::Result as RpcResult; +use crate::rpc::futures::{stream, Future, Sink, Stream}; use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{Block as BlockT, Header, ProvideRuntimeApi}; +use runtime_primitives::traits::{Block as BlockT, Header, ProvideRuntimeApi, As, NumberFor}; use runtime_version::RuntimeVersion; +use state_machine::ExecutionStrategy; -use subscriptions::Subscriptions; +use crate::subscriptions::Subscriptions; mod error; #[cfg(test)] @@ -42,62 +45,72 @@ mod tests; use self::error::Result; -build_rpc_trait! { - /// Substrate state API - pub trait StateApi { - type Metadata; - - /// Call a contract at a block's state. - #[rpc(name = "state_call", alias = ["state_callAt", ])] - fn call(&self, String, Bytes, Trailing) -> Result; - - /// Returns a storage entry at a specific block's state. - #[rpc(name = "state_getStorage", alias = ["state_getStorageAt", ])] - fn storage(&self, StorageKey, Trailing) -> Result>; - - /// Returns the hash of a storage entry at a block's state. - #[rpc(name = "state_getStorageHash", alias = ["state_getStorageHashAt", ])] - fn storage_hash(&self, StorageKey, Trailing) -> Result>; - - /// Returns the size of a storage entry at a block's state. - #[rpc(name = "state_getStorageSize", alias = ["state_getStorageSizeAt", ])] - fn storage_size(&self, StorageKey, Trailing) -> Result>; - - /// Returns the runtime metadata as an opaque blob. - #[rpc(name = "state_getMetadata")] - fn metadata(&self, Trailing) -> Result; - - /// Get the runtime version. - #[rpc(name = "state_getRuntimeVersion", alias = ["chain_getRuntimeVersion", ])] - fn runtime_version(&self, Trailing) -> Result; - - /// Query historical storage entries (by key) starting from a block given as the second parameter. - /// - /// NOTE This first returned result contains the initial state of storage for all keys. - /// Subsequent values in the vector represent changes to the previous state (diffs). - #[rpc(name = "state_queryStorage")] - fn query_storage(&self, Vec, Hash, Trailing) -> Result>>; - - #[pubsub(name = "state_runtimeVersion")] { - /// New runtime version subscription - #[rpc(name = "state_subscribeRuntimeVersion", alias = ["chain_subscribeRuntimeVersion", ])] - fn subscribe_runtime_version(&self, Self::Metadata, pubsub::Subscriber); - - /// Unsubscribe from runtime version subscription - #[rpc(name = "state_unsubscribeRuntimeVersion", alias = ["chain_unsubscribeRuntimeVersion", ])] - fn unsubscribe_runtime_version(&self, Self::Metadata, SubscriptionId) -> RpcResult; - } - - #[pubsub(name = "state_storage")] { - /// New storage subscription - #[rpc(name = "state_subscribeStorage")] - fn subscribe_storage(&self, Self::Metadata, pubsub::Subscriber>, Trailing>); - - /// Unsubscribe from storage subscription - #[rpc(name = "state_unsubscribeStorage")] - fn unsubscribe_storage(&self, Self::Metadata, SubscriptionId) -> RpcResult; - } - } +/// Substrate state API +#[rpc] +pub trait StateApi { + /// RPC Metadata + type Metadata; + + /// Call a contract at a block's state. + #[rpc(name = "state_call", alias("state_callAt"))] + fn call(&self, name: String, bytes: Bytes, hash: Option) -> Result; + + /// Returns the keys with prefix, leave empty to get all the keys + #[rpc(name = "state_getKeys")] + fn storage_keys(&self, key: StorageKey, hash: Option) -> Result>; + + /// Returns a storage entry at a specific block's state. + #[rpc(name = "state_getStorage", alias("state_getStorageAt"))] + fn storage(&self, key: StorageKey, hash: Option) -> Result>; + + /// Returns the hash of a storage entry at a block's state. + #[rpc(name = "state_getStorageHash", alias("state_getStorageHashAt"))] + fn storage_hash(&self, key: StorageKey, hash: Option) -> Result>; + + /// Returns the size of a storage entry at a block's state. + #[rpc(name = "state_getStorageSize", alias("state_getStorageSizeAt"))] + fn storage_size(&self, key: StorageKey, hash: Option) -> Result>; + + /// Returns the runtime metadata as an opaque blob. + #[rpc(name = "state_getMetadata")] + fn metadata(&self, hash: Option) -> Result; + + /// Get the runtime version. + #[rpc(name = "state_getRuntimeVersion", alias("chain_getRuntimeVersion"))] + fn runtime_version(&self, hash: Option) -> Result; + + /// Query historical storage entries (by key) starting from a block given as the second parameter. + /// + /// NOTE This first returned result contains the initial state of storage for all keys. + /// Subsequent values in the vector represent changes to the previous state (diffs). + #[rpc(name = "state_queryStorage")] + fn query_storage(&self, keys: Vec, block: Hash, hash: Option) -> Result>>; + + /// New runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + subscribe, + name = "state_subscribeRuntimeVersion", + alias("chain_subscribeRuntimeVersion") + )] + fn subscribe_runtime_version(&self, metadata: Self::Metadata, subscriber: Subscriber); + + /// Unsubscribe from runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + unsubscribe, + name = "state_unsubscribeRuntimeVersion", + alias("chain_unsubscribeRuntimeVersion") + )] + fn unsubscribe_runtime_version(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + + /// New storage subscription + #[pubsub(subscription = "state_storage", subscribe, name = "state_subscribeStorage")] + fn subscribe_storage(&self, metadata: Self::Metadata, subscriber: Subscriber>, keys: Option>); + + /// Unsubscribe from storage subscription + #[pubsub(subscription = "state_storage", unsubscribe, name = "state_unsubscribeStorage")] + fn unsubscribe_storage(&self, metadata: Option, id: SubscriptionId) -> RpcResult; } /// State API with subscriptions support. @@ -108,7 +121,25 @@ pub struct State { subscriptions: Subscriptions, } -impl State { +/// Ranges to query in state_queryStorage. +struct QueryStorageRange { + /// Hashes of all the blocks in the range. + pub hashes: Vec, + /// Number of the first block in the range. + pub first_number: NumberFor, + /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at + /// each state to get changes. + pub unfiltered_range: Range, + /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter + /// blocks-with-changes by using changes tries. + pub filtered_range: Option>, +} + +impl State where + Block: BlockT, + B: client::backend::Backend, + E: CallExecutor, +{ /// Create new State API RPC handler. pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { Self { @@ -116,6 +147,128 @@ impl State { subscriptions, } } + + /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. + /// Blocks that contain changes within filtered subrange could be filtered using changes tries. + /// Blocks that contain changes within unfiltered subrange must be filtered manually. + fn split_query_storage_range( + &self, + from: Block::Hash, + to: Option + ) -> Result> { + let to = self.unwrap_or_best(to)?; + let from_hdr = self.client.header(&BlockId::hash(from))?; + let to_hdr = self.client.header(&BlockId::hash(to))?; + match (from_hdr, to_hdr) { + (Some(ref from), Some(ref to)) if from.number() <= to.number() => { + // check if we can get from `to` to `from` by going through parent_hashes. + let from_number = *from.number(); + let blocks = { + let mut blocks = vec![to.hash()]; + let mut last = to.clone(); + while *last.number() > from_number { + if let Some(hdr) = self.client.header(&BlockId::hash(*last.parent_hash()))? { + blocks.push(hdr.hash()); + last = hdr; + } else { + bail!(invalid_block_range( + Some(from), + Some(to), + format!("Parent of {} ({}) not found", last.number(), last.hash()), + )) + } + } + if last.hash() != from.hash() { + bail!(invalid_block_range( + Some(from), + Some(to), + format!("Expected to reach `from`, got {} ({})", last.number(), last.hash()), + )) + } + blocks.reverse(); + blocks + }; + // check if we can filter blocks-with-changes from some (sub)range using changes tries + let changes_trie_range = self.client.max_key_changes_range(from_number, BlockId::Hash(to.hash()))?; + let filtered_range_begin = changes_trie_range.map(|(begin, _)| (begin - from_number).as_() as usize); + let (unfiltered_range, filtered_range) = split_range(blocks.len(), filtered_range_begin); + Ok(QueryStorageRange { + hashes: blocks, + first_number: from_number, + unfiltered_range, + filtered_range, + }) + }, + (from, to) => bail!( + invalid_block_range(from.as_ref(), to.as_ref(), "Invalid range or unknown block".into()) + ), + } + } + + /// Iterates through range.unfiltered_range and check each block for changes of keys' values. + fn query_storage_unfiltered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + changes: &mut Vec>, + ) -> Result<()> { + let mut last_state: HashMap<_, Option<_>> = Default::default(); + for block in range.unfiltered_range.start..range.unfiltered_range.end { + let block_hash = range.hashes[block].clone(); + let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; + let id = BlockId::hash(block_hash); + for key in keys { + let (has_changed, data) = { + let curr_data = self.client.storage(&id, key)?; + let prev_data = last_state.get(key).and_then(|x| x.as_ref()); + (curr_data.as_ref() != prev_data, curr_data) + }; + if has_changed { + block_changes.changes.push((key.clone(), data.clone())); + } + last_state.insert(key.clone(), data); + } + changes.push(block_changes); + } + Ok(()) + } + + /// Iterates through all blocks that are changing keys within range.filtered_range and collects these changes. + fn query_storage_filtered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + changes: &mut Vec>, + ) -> Result<()> { + let (begin, end) = match range.filtered_range { + Some(ref filtered_range) => ( + range.first_number + As::sa(filtered_range.start as u64), + BlockId::Hash(range.hashes[filtered_range.end - 1].clone()) + ), + None => return Ok(()), + }; + let mut changes_map: BTreeMap, StorageChangeSet> = BTreeMap::new(); + for key in keys { + let mut last_block = None; + for (block, _) in self.client.key_changes(begin, end, key)? { + if last_block == Some(block) { + continue; + } + let block_hash = range.hashes[(block - range.first_number).as_() as usize].clone(); + let id = BlockId::Hash(block_hash); + let value_at_block = self.client.storage(&id, key)?; + changes_map.entry(block) + .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) + .changes.push((key.clone(), value_at_block)); + last_block = Some(block); + } + } + if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { + changes.reserve(additional_capacity); + } + changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); + Ok(()) + } } impl State where @@ -123,8 +276,8 @@ impl State where B: client::backend::Backend, E: CallExecutor, { - fn unwrap_or_best(&self, hash: Trailing) -> Result { - ::helpers::unwrap_or_else(|| Ok(self.client.info()?.chain.best_hash), hash) + fn unwrap_or_best(&self, hash: Option) -> Result { + crate::helpers::unwrap_or_else(|| Ok(self.client.info()?.chain.best_hash), hash) } } @@ -132,116 +285,68 @@ impl StateApi for State where Block: BlockT + 'static, B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static + Clone, - RA: Metadata + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: Metadata { - type Metadata = ::metadata::Metadata; + type Metadata = crate::metadata::Metadata; - fn call(&self, method: String, data: Bytes, block: Trailing) -> Result { + fn call(&self, method: String, data: Bytes, block: Option) -> Result { let block = self.unwrap_or_best(block)?; trace!(target: "rpc", "Calling runtime at {:?} for method {} ({})", block, method, HexDisplay::from(&data.0)); let return_data = self.client .executor() .call( &BlockId::Hash(block), - &method, &data.0 - )? - .return_data; + &method, &data.0, ExecutionStrategy::NativeElseWasm + )?; Ok(Bytes(return_data)) } - fn storage(&self, key: StorageKey, block: Trailing) -> Result> { + fn storage_keys(&self, key_prefix: StorageKey, block: Option) -> Result> { + let block = self.unwrap_or_best(block)?; + trace!(target: "rpc", "Querying storage keys at {:?}", block); + Ok(self.client.storage_keys(&BlockId::Hash(block), &key_prefix)?) + } + + fn storage(&self, key: StorageKey, block: Option) -> Result> { let block = self.unwrap_or_best(block)?; trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0)); Ok(self.client.storage(&BlockId::Hash(block), &key)?) } - fn storage_hash(&self, key: StorageKey, block: Trailing) -> Result> { + fn storage_hash(&self, key: StorageKey, block: Option) -> Result> { use runtime_primitives::traits::{Hash, Header as HeaderT}; Ok(self.storage(key, block)?.map(|x| ::Hashing::hash(&x.0))) } - fn storage_size(&self, key: StorageKey, block: Trailing) -> Result> { + fn storage_size(&self, key: StorageKey, block: Option) -> Result> { Ok(self.storage(key, block)?.map(|x| x.0.len() as u64)) } - fn metadata(&self, block: Trailing) -> Result { + fn metadata(&self, block: Option) -> Result { let block = self.unwrap_or_best(block)?; self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into).map_err(Into::into) } - fn query_storage(&self, keys: Vec, from: Block::Hash, to: Trailing) -> Result>> { - let to = self.unwrap_or_best(to)?; - - let from_hdr = self.client.header(&BlockId::hash(from))?; - let to_hdr = self.client.header(&BlockId::hash(to))?; - - match (from_hdr, to_hdr) { - (Some(ref from), Some(ref to)) if from.number() <= to.number() => { - let from = from.clone(); - let to = to.clone(); - // check if we can get from `to` to `from` by going through parent_hashes. - let blocks = { - let mut blocks = vec![to.hash()]; - let mut last = to.clone(); - while last.number() > from.number() { - if let Some(hdr) = self.client.header(&BlockId::hash(*last.parent_hash()))? { - blocks.push(hdr.hash()); - last = hdr; - } else { - bail!(invalid_block_range( - Some(from), - Some(to), - format!("Parent of {} ({}) not found", last.number(), last.hash()), - )) - } - } - if last.hash() != from.hash() { - bail!(invalid_block_range( - Some(from), - Some(to), - format!("Expected to reach `from`, got {} ({})", last.number(), last.hash()), - )) - } - blocks.reverse(); - blocks - }; - let mut result = Vec::new(); - let mut last_state: HashMap<_, Option<_>> = Default::default(); - for block in blocks { - let mut changes = vec![]; - let id = BlockId::hash(block.clone()); - - for key in &keys { - let (has_changed, data) = { - let curr_data = self.client.storage(&id, key)?; - let prev_data = last_state.get(key).and_then(|x| x.as_ref()); - - (curr_data.as_ref() != prev_data, curr_data) - }; - - if has_changed { - changes.push((key.clone(), data.clone())); - } - - last_state.insert(key.clone(), data); - } - - result.push(StorageChangeSet { - block, - changes, - }); - } - Ok(result) - }, - (from, to) => bail!(invalid_block_range(from, to, "Invalid range or unknown block".into())), - } + fn query_storage( + &self, + keys: Vec, + from: Block::Hash, + to: Option + ) -> Result>> { + let range = self.split_query_storage_range(from, to)?; + let mut changes = Vec::new(); + self.query_storage_unfiltered(&range, &keys, &mut changes)?; + self.query_storage_filtered(&range, &keys, &mut changes)?; + Ok(changes) } fn subscribe_storage( &self, _meta: Self::Metadata, - subscriber: pubsub::Subscriber>, - keys: Trailing> + subscriber: Subscriber>, + keys: Option> ) { let keys = Into::>>::into(keys); let stream = match self.client.storage_changes_notification_stream(keys.as_ref().map(|x| &**x)) { @@ -282,16 +387,16 @@ impl StateApi for State where }) } - fn unsubscribe_storage(&self, _meta: Self::Metadata, id: SubscriptionId) -> RpcResult { + fn unsubscribe_storage(&self, _meta: Option, id: SubscriptionId) -> RpcResult { Ok(self.subscriptions.cancel(id)) } - fn runtime_version(&self, at: Trailing) -> Result { + fn runtime_version(&self, at: Option) -> Result { let at = self.unwrap_or_best(at)?; Ok(self.client.runtime_version_at(&BlockId::Hash(at))?) } - fn subscribe_runtime_version(&self, _meta: Self::Metadata, subscriber: pubsub::Subscriber) { + fn subscribe_runtime_version(&self, _meta: Self::Metadata, subscriber: Subscriber) { let stream = match self.client.storage_changes_notification_stream(Some(&[StorageKey(storage::well_known_keys::CODE.to_vec())])) { Ok(stream) => stream, Err(err) => { @@ -334,13 +439,34 @@ impl StateApi for State where }); } - fn unsubscribe_runtime_version(&self, _meta: Self::Metadata, id: SubscriptionId) -> RpcResult { + fn unsubscribe_runtime_version(&self, _meta: Option, id: SubscriptionId) -> RpcResult { Ok(self.subscriptions.cancel(id)) } } -fn invalid_block_range(from: Option, to: Option, reason: String) -> error::ErrorKind { - let to_string = |x: Option| match x { +/// Splits passed range into two subranges where: +/// - first range has at least one element in it; +/// - second range (optionally) starts at given `middle` element. +pub(crate) fn split_range(size: usize, middle: Option) -> (Range, Option>) { + // check if we can filter blocks-with-changes from some (sub)range using changes tries + let range2_begin = match middle { + // some of required changes tries are pruned => use available tries + Some(middle) if middle != 0 => Some(middle), + // all required changes tries are available, but we still want values at first block + // => do 'unfiltered' read for the first block and 'filtered' for the rest + Some(_) if size > 1 => Some(1), + // range contains single element => do not use changes tries + Some(_) => None, + // changes tries are not available => do 'unfiltered' read for the whole range + None => None, + }; + let range1 = 0..range2_begin.unwrap_or(size); + let range2 = range2_begin.map(|begin| begin..size); + (range1, range2) +} + +fn invalid_block_range(from: Option<&H>, to: Option<&H>, reason: String) -> error::ErrorKind { + let to_string = |x: Option<&H>| match x { None => "unknown hash".into(), Some(h) => format!("{} ({})", h.number(), h.hash()), }; diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index 3fe306d0bce09415c0ef565027c5589ca08050a4..436d413b1a7bedba6333c170f7db7be94c4822bd 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,10 +17,10 @@ use super::*; use self::error::{Error, ErrorKind}; +use sr_io::twox_128; +use assert_matches::assert_matches; use consensus::BlockOrigin; -use jsonrpc_macros::pubsub; -use rustc_hex::FromHex; -use test_client::{self, runtime, keyring::Keyring, TestClient, BlockBuilderExt}; +use test_client::{self, runtime, AccountKeyring, TestClient, BlockBuilderExt}; #[test] fn should_return_storage() { @@ -52,7 +52,7 @@ fn should_call_contract() { fn should_notify_about_storage_changes() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); + let (subscriber, id, transport) = Subscriber::new_test("test"); { let api = State::new(Arc::new(test_client::new()), Subscriptions::new(remote)); @@ -64,8 +64,8 @@ fn should_notify_about_storage_changes() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -83,13 +83,15 @@ fn should_notify_about_storage_changes() { fn should_send_initial_storage_changes_and_notifications() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); + let (subscriber, id, transport) = Subscriber::new_test("test"); { let api = State::new(Arc::new(test_client::new()), Subscriptions::new(remote)); + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); + api.subscribe_storage(Default::default(), subscriber, Some(vec![ - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), ]).into()); // assert id assigned @@ -97,8 +99,8 @@ fn should_send_initial_storage_changes_and_notifications() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -117,66 +119,96 @@ fn should_send_initial_storage_changes_and_notifications() { #[test] fn should_query_storage() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let api = State::new(client.clone(), Subscriptions::new(core.executor())); - - let add_block = |nonce| { - let mut builder = client.new_block().unwrap(); - builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), - amount: 42, - nonce, - }).unwrap(); - let block = builder.bake().unwrap(); - let hash = block.header.hash(); - client.import(BlockOrigin::Own, block).unwrap(); - hash - }; - let block1_hash = add_block(0); - let block2_hash = add_block(1); - let genesis_hash = client.genesis_hash(); - + type TestClient = test_client::client::Client< + test_client::Backend, + test_client::Executor, + runtime::Block, + runtime::RuntimeApi + >; + + fn run_tests(client: Arc) { + let core = ::tokio::runtime::Runtime::new().unwrap(); + let api = State::new(client.clone(), Subscriptions::new(core.executor())); - let mut expected = vec![ - StorageChangeSet { - block: genesis_hash, - changes: vec![ - (StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), Some(StorageData(vec![232, 3, 0, 0, 0, 0, 0, 0]))), - ], - }, - StorageChangeSet { - block: block1_hash, + let add_block = |nonce| { + let mut builder = client.new_block().unwrap(); + builder.push_transfer(runtime::Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce, + }).unwrap(); + let block = builder.bake().unwrap(); + let hash = block.header.hash(); + client.import(BlockOrigin::Own, block).unwrap(); + hash + }; + let block1_hash = add_block(0); + let block2_hash = add_block(1); + let genesis_hash = client.genesis_hash(); + + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); + + let mut expected = vec![ + StorageChangeSet { + block: genesis_hash, + changes: vec![ + ( + StorageKey(alice_balance_key.to_vec()), + Some(StorageData(vec![232, 3, 0, 0, 0, 0, 0, 0])) + ), + ], + }, + StorageChangeSet { + block: block1_hash, + changes: vec![ + ( + StorageKey(alice_balance_key.to_vec()), + Some(StorageData(vec![190, 3, 0, 0, 0, 0, 0, 0])) + ), + ], + }, + ]; + + // Query changes only up to block1 + let result = api.query_storage( + vec![StorageKey(alice_balance_key.to_vec())], + genesis_hash, + Some(block1_hash).into(), + ); + + assert_eq!(result.unwrap(), expected); + + // Query all changes + let result = api.query_storage( + vec![StorageKey(alice_balance_key.to_vec())], + genesis_hash, + None.into(), + ); + + expected.push(StorageChangeSet { + block: block2_hash, changes: vec![ - (StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), Some(StorageData(vec![190, 3, 0, 0, 0, 0, 0, 0]))), + ( + StorageKey(alice_balance_key.to_vec()), + Some(StorageData(vec![148, 3, 0, 0, 0, 0, 0, 0])) + ), ], - }, - ]; - - // Query changes only up to block1 - let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], - genesis_hash, - Some(block1_hash).into(), - ); - - assert_eq!(result.unwrap(), expected); + }); + assert_eq!(result.unwrap(), expected); + } - // Query all changes - let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], - genesis_hash, - None.into(), - ); + run_tests(Arc::new(test_client::new())); + run_tests(Arc::new(test_client::new_with_changes_trie())); +} - expected.push(StorageChangeSet { - block: block2_hash, - changes: vec![ - (StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), Some(StorageData(vec![148, 3, 0, 0, 0, 0, 0, 0]))), - ], - }); - assert_eq!(result.unwrap(), expected); +#[test] +fn should_split_ranges() { + assert_eq!(split_range(1, None), (0..1, None)); + assert_eq!(split_range(100, None), (0..100, None)); + assert_eq!(split_range(1, Some(0)), (0..1, None)); + assert_eq!(split_range(100, Some(50)), (0..50, Some(50..100))); + assert_eq!(split_range(100, Some(99)), (0..99, Some(99..100))); } @@ -187,16 +219,16 @@ fn should_return_runtime_version() { let client = Arc::new(test_client::new()); let api = State::new(client.clone(), Subscriptions::new(core.executor())); - assert_matches!( - api.runtime_version(None.into()), - Ok(ref ver) if ver == &runtime::VERSION + assert_eq!( + ::serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), + r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",1],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",2],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1]]}"# ); } #[test] fn should_notify_on_runtime_version_initially() { let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let (subscriber, id, transport) = pubsub::Subscriber::new_test("test"); + let (subscriber, id, transport) = Subscriber::new_test("test"); { let client = Arc::new(test_client::new()); diff --git a/core/rpc/src/subscriptions.rs b/core/rpc/src/subscriptions.rs index 17ca51b3504b598575963a41e36b613927e48f3c..500f3dac4545ccf966cf558f0dc94ccbb6f192de 100644 --- a/core/rpc/src/subscriptions.rs +++ b/core/rpc/src/subscriptions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,11 +17,11 @@ use std::collections::HashMap; use std::sync::{Arc, atomic::{self, AtomicUsize}}; -use jsonrpc_macros::pubsub; -use jsonrpc_pubsub::SubscriptionId; +use log::warn; +use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}}; use parking_lot::Mutex; -use rpc::futures::sync::oneshot; -use rpc::futures::{Future, future}; +use crate::rpc::futures::sync::oneshot; +use crate::rpc::futures::{Future, future}; use tokio::runtime::TaskExecutor; type Id = u64; @@ -72,8 +72,8 @@ impl Subscriptions { /// Second parameter is a function that converts Subscriber sink into a future. /// This future will be driven to completion bu underlying event loop /// or will be cancelled in case #cancel is invoked. - pub fn add(&self, subscriber: pubsub::Subscriber, into_future: G) where - G: FnOnce(pubsub::Sink) -> R, + pub fn add(&self, subscriber: Subscriber, into_future: G) where + G: FnOnce(Sink) -> R, R: future::IntoFuture, F: future::Future + Send + 'static, { diff --git a/core/rpc/src/system/error.rs b/core/rpc/src/system/error.rs index 844494d248a84c652227c5aac00d29e2703537d1..d3c7e8b33387048385abcad3e620a615646f0dc5 100644 --- a/core/rpc/src/system/error.rs +++ b/core/rpc/src/system/error.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,10 +16,11 @@ //! System RPC module errors. -use rpc; +use error_chain::*; -use errors; -use system::helpers::Health; +use crate::rpc; +use crate::errors; +use crate::system::helpers::Health; error_chain! { errors { diff --git a/core/rpc/src/system/helpers.rs b/core/rpc/src/system/helpers.rs index 0d3b7e56cd81e04e0d87ab2bf0d80773872976fe..ea35b8803ca63e5009f295c0aaacf8b4a3476cd2 100644 --- a/core/rpc/src/system/helpers.rs +++ b/core/rpc/src/system/helpers.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -38,11 +38,34 @@ pub struct SystemInfo { /// Health struct returned by the RPC #[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] pub struct Health { /// Number of connected peers pub peers: usize, /// Is the node syncing pub is_syncing: bool, + /// Should this node have any peers + /// + /// Might be false for local chains or when running without discovery. + pub should_have_peers: bool, +} + +/// Network Peer information +#[derive(Debug, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct PeerInfo { + /// Peer Node Index + pub index: usize, + /// Peer ID + pub peer_id: String, + /// Roles + pub roles: String, + /// Protocol version + pub protocol_version: u32, + /// Peer best block hash + pub best_hash: Hash, + /// Peer best block number + pub best_number: Number, } impl fmt::Display for Health { @@ -52,3 +75,35 @@ impl fmt::Display for Health { } else { "idle" }) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_serialize_health() { + assert_eq!( + ::serde_json::to_string(&Health { + peers: 1, + is_syncing: false, + should_have_peers: true, + }).unwrap(), + r#"{"peers":1,"isSyncing":false,"shouldHavePeers":true}"#, + ); + } + + #[test] + fn should_serialize_peer_info() { + assert_eq!( + ::serde_json::to_string(&PeerInfo { + index: 1, + peer_id: "2".into(), + roles: "a".into(), + protocol_version: 2, + best_hash: 5u32, + best_number: 6u32, + }).unwrap(), + r#"{"index":1,"peerId":"2","roles":"a","protocolVersion":2,"bestHash":5,"bestNumber":6}"#, + ); + } +} diff --git a/core/rpc/src/system/mod.rs b/core/rpc/src/system/mod.rs index 634dd1c0639d6f8bec11696b41b4c7b00f0da7e0..b0fc4e5679e8b30ed2d8a3f1b2db6fddf4d0efca 100644 --- a/core/rpc/src/system/mod.rs +++ b/core/rpc/src/system/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,39 +23,50 @@ mod helpers; mod tests; use std::sync::Arc; +use jsonrpc_derive::rpc; use network; -use runtime_primitives::traits; +use runtime_primitives::traits::{self, Header as HeaderT}; use self::error::Result; -pub use self::helpers::{Properties, SystemInfo, Health}; - -build_rpc_trait! { - /// Substrate system RPC API - pub trait SystemApi { - /// Get the node's implementation name. Plain old string. - #[rpc(name = "system_name")] - fn system_name(&self) -> Result; - - /// Get the node implementation's version. Should be a semver string. - #[rpc(name = "system_version")] - fn system_version(&self) -> Result; - - /// Get the chain's type. Given as a string identifier. - #[rpc(name = "system_chain")] - fn system_chain(&self) -> Result; - - /// Get a custom set of properties as a JSON object, defined in the chain spec. - #[rpc(name = "system_properties")] - fn system_properties(&self) -> Result; - - /// Return health status of the node. - /// - /// Node is considered healthy if it is: - /// - connected to some peers (unless running in dev mode) - /// - not performing a major sync - #[rpc(name = "system_health")] - fn system_health(&self) -> Result; - } +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo}; + +/// Substrate system RPC API +#[rpc] +pub trait SystemApi { + /// Get the node's implementation name. Plain old string. + #[rpc(name = "system_name")] + fn system_name(&self) -> Result; + + /// Get the node implementation's version. Should be a semver string. + #[rpc(name = "system_version")] + fn system_version(&self) -> Result; + + /// Get the chain's type. Given as a string identifier. + #[rpc(name = "system_chain")] + fn system_chain(&self) -> Result; + + /// Get a custom set of properties as a JSON object, defined in the chain spec. + #[rpc(name = "system_properties")] + fn system_properties(&self) -> Result; + + /// Return health status of the node. + /// + /// Node is considered healthy if it is: + /// - connected to some peers (unless running in dev mode) + /// - not performing a major sync + #[rpc(name = "system_health")] + fn system_health(&self) -> Result; + + /// Returns currently connected peers + #[rpc(name = "system_peers")] + fn system_peers(&self) -> Result>>; + + /// Returns current state of the network. + /// + /// **Warning**: This API is not stable. + // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 + #[rpc(name = "system_networkState")] + fn system_network_state(&self) -> Result; } /// System API implementation @@ -80,7 +91,7 @@ impl System { } } -impl SystemApi for System { +impl SystemApi::Number> for System { fn system_name(&self) -> Result { Ok(self.info.impl_name.clone()) } @@ -98,21 +109,25 @@ impl SystemApi for System { } fn system_health(&self) -> Result { - let status = self.sync.status(); - - let is_syncing = status.sync.is_major_syncing(); - let peers = status.num_peers; + Ok(Health { + peers: self.sync.peers().len(), + is_syncing: self.sync.is_major_syncing(), + should_have_peers: self.should_have_peers, + }) + } - let health = Health { - peers, - is_syncing, - }; + fn system_peers(&self) -> Result::Number>>> { + Ok(self.sync.peers().into_iter().map(|(index, p)| PeerInfo { + index, + peer_id: p.peer_id.to_base58(), + roles: format!("{:?}", p.roles), + protocol_version: p.protocol_version, + best_hash: p.best_hash, + best_number: p.best_number, + }).collect()) + } - let has_no_peers = peers == 0 && self.should_have_peers; - if has_no_peers || is_syncing { - Err(error::ErrorKind::NotHealthy(health))? - } else { - Ok(health) - } + fn system_network_state(&self) -> Result { + Ok(self.sync.network_state()) } } diff --git a/core/rpc/src/system/tests.rs b/core/rpc/src/system/tests.rs index 5c8f0b9058d723ebaa23f9c5fdcc3494b741cc72..6aee5c3fa24ac0f30358d45ecf6286d5de14de94 100644 --- a/core/rpc/src/system/tests.rs +++ b/core/rpc/src/system/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,27 +16,69 @@ use super::*; -use network::{self, SyncState, SyncStatus, ProtocolStatus}; +use network::{self, ProtocolStatus, NodeIndex, PeerId, PeerInfo as NetworkPeerInfo}; +use network::config::Roles; use test_client::runtime::Block; +use assert_matches::assert_matches; +use futures::sync::mpsc; -#[derive(Default)] struct Status { pub peers: usize, pub is_syncing: bool, pub is_dev: bool, + pub peer_id: PeerId, +} + +impl Default for Status { + fn default() -> Status { + Status { + peer_id: PeerId::random(), + peers: 0, + is_syncing: false, + is_dev: false, + } + } } impl network::SyncProvider for Status { - fn status(&self) -> ProtocolStatus { - ProtocolStatus { - sync: SyncStatus { - state: if self.is_syncing { SyncState::Downloading } else { SyncState::Idle }, - best_seen_block: None, - }, - num_peers: self.peers, - num_active_peers: 0, + fn status(&self) -> mpsc::UnboundedReceiver> { + let (_sink, stream) = mpsc::unbounded(); + stream + } + + fn network_state(&self) -> network::NetworkState { + network::NetworkState { + peer_id: String::new(), + listened_addresses: Default::default(), + is_reserved_only: false, + reserved_peers: Default::default(), + banned_peers: Default::default(), + connected_peers: Default::default(), + not_connected_peers: Default::default(), + average_download_per_sec: 0, + average_upload_per_sec: 0, } } + + fn peers(&self) -> Vec<(NodeIndex, NetworkPeerInfo)> { + let mut peers = vec![]; + for _peer in 0..self.peers { + peers.push( + (1, NetworkPeerInfo { + peer_id: self.peer_id.clone(), + roles: Roles::FULL, + protocol_version: 1, + best_hash: Default::default(), + best_number: 1 + }) + ); + } + peers + } + + fn is_major_syncing(&self) -> bool { + self.is_syncing + } } @@ -86,27 +128,31 @@ fn system_properties_works() { #[test] fn system_health() { assert_matches!( - api(None).system_health().unwrap_err().kind(), - error::ErrorKind::NotHealthy(Health { + api(None).system_health().unwrap(), + Health { peers: 0, is_syncing: false, - }) + should_have_peers: true, + } ); assert_matches!( api(Status { + peer_id: PeerId::random(), peers: 5, is_syncing: true, is_dev: true, - }).system_health().unwrap_err().kind(), - error::ErrorKind::NotHealthy(Health { + }).system_health().unwrap(), + Health { peers: 5, is_syncing: true, - }) + should_have_peers: false, + } ); assert_eq!( api(Status { + peer_id: PeerId::random(), peers: 5, is_syncing: false, is_dev: false, @@ -114,11 +160,13 @@ fn system_health() { Health { peers: 5, is_syncing: false, + should_have_peers: true, } ); assert_eq!( api(Status { + peer_id: PeerId::random(), peers: 0, is_syncing: false, is_dev: true, @@ -126,6 +174,46 @@ fn system_health() { Health { peers: 0, is_syncing: false, + should_have_peers: false, + } + ); +} + +#[test] +fn system_peers() { + let peer_id = PeerId::random(); + assert_eq!( + api(Status { + peer_id: peer_id.clone(), + peers: 1, + is_syncing: false, + is_dev: true, + }).system_peers().unwrap(), + vec![PeerInfo { + index: 1, + peer_id: peer_id.to_base58(), + roles: "FULL".into(), + protocol_version: 1, + best_hash: Default::default(), + best_number: 1u64, + }] + ); +} + +#[test] +fn system_network_state() { + assert_eq!( + api(None).system_network_state().unwrap(), + network::NetworkState { + peer_id: String::new(), + listened_addresses: Default::default(), + is_reserved_only: false, + reserved_peers: Default::default(), + banned_peers: Default::default(), + connected_peers: Default::default(), + not_connected_peers: Default::default(), + average_download_per_sec: 0, + average_upload_per_sec: 0, } ); } diff --git a/core/serializer/Cargo.toml b/core/serializer/Cargo.toml index db94e81c840dafa8207e8a4d50e4372c2e01ce46..8788f776e5a2842abfb375f3d9023b84a9abbba0 100644 --- a/core/serializer/Cargo.toml +++ b/core/serializer/Cargo.toml @@ -2,7 +2,8 @@ name = "substrate-serializer" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = "1.0" serde_json = "1.0" diff --git a/core/serializer/src/lib.rs b/core/serializer/src/lib.rs index 667c57eb8751dd7c5b15361c88895c1ace955e7d..2586d49f00599ea919ce635092048a9c0f039dd7 100644 --- a/core/serializer/src/lib.rs +++ b/core/serializer/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,9 +21,6 @@ #![warn(missing_docs)] -extern crate serde; -extern crate serde_json; - pub use serde_json::{from_str, from_slice, from_reader, Result, Error}; const PROOF: &str = "Serializers are infallible; qed"; diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index ca8766c707a725365bb764ca88188855543f4932..353a3a99736f94cd31e83ce3cfb8b2618c24bbe7 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -2,10 +2,11 @@ name = "substrate-service" version = "0.3.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] futures = "0.1.17" -parking_lot = "0.4" +parking_lot = "0.7.1" error-chain = "0.12" lazy_static = "1.0" log = "0.4" @@ -16,17 +17,19 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" target_info = "0.1" -substrate-keystore = { path = "../../core/keystore" } +keystore = { package = "substrate-keystore", path = "../../core/keystore" } sr-io = { path = "../../core/sr-io" } -sr-primitives = { path = "../../core/sr-primitives" } -substrate-primitives = { path = "../../core/primitives" } -substrate-consensus-common = { path = "../../core/consensus/common" } -substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives" } -substrate-network = { path = "../../core/network" } -substrate-client = { path = "../../core/client" } -substrate-client-db = { path = "../../core/client/db" } -parity-codec = "2.1" +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } +network = { package = "substrate-network", path = "../../core/network" } +client = { package = "substrate-client", path = "../../core/client" } +client_db = { package = "substrate-client-db", path = "../../core/client/db" } +parity-codec = "3.2" substrate-executor = { path = "../../core/executor" } -substrate-transaction-pool = { path = "../../core/transaction-pool" } -substrate-rpc-servers = { path = "../../core/rpc-servers" } -substrate-telemetry = { path = "../../core/telemetry" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +rpc = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } +tel = { package = "substrate-telemetry", path = "../../core/telemetry" } + +[dev-dependencies] +substrate-test-client = { path = "../test-client" } diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index 6d6dc558f41f8b620e523d9f99d74eceec535ab7..36cbee9039395737edb62df50fa0d54d4a80fac3 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,21 +18,29 @@ use std::{self, io::{Read, Write}}; use futures::Future; +use log::{info, warn}; use runtime_primitives::generic::{SignedBlock, BlockId}; -use runtime_primitives::traits::{As, Block, Header}; -use network::import_queue::{ImportQueue, Link, BlockData}; +use runtime_primitives::traits::{As, Block, Header, NumberFor}; +use consensus_common::import_queue::{ImportQueue, IncomingBlock, Link}; use network::message; use consensus_common::BlockOrigin; -use components::{self, Components, ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis}; -use new_client; -use codec::{Decode, Encode}; -use error; -use chain_spec::ChainSpec; +use crate::components::{self, Components, ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis}; +use crate::new_client; +use parity_codec::{Decode, Encode}; +use crate::error; +use crate::chain_spec::ChainSpec; /// Export a range of blocks to a binary stream. -pub fn export_blocks(config: FactoryFullConfiguration, exit: E, mut output: W, from: FactoryBlockNumber, to: Option>, json: bool) -> error::Result<()> +pub fn export_blocks( + config: FactoryFullConfiguration, + exit: E, + mut output: W, + from: FactoryBlockNumber, + to: Option>, + json: bool +) -> error::Result<()> where F: ServiceFactory, E: Future + Send + 'static, @@ -58,7 +66,10 @@ pub fn export_blocks(config: FactoryFullConfiguration, exit: E, mut }); info!("Exporting blocks from #{} to #{}", block, last); if !json { - output.write(&(last - block + As::sa(1)).encode())?; + let last_: u64 = last.as_(); + let block_: u64 = block.as_(); + let len: u64 = last_ - block_ + 1; + output.write(&len.encode())?; } loop { @@ -68,7 +79,8 @@ pub fn export_blocks(config: FactoryFullConfiguration, exit: E, mut match client.block(&BlockId::number(block))? { Some(block) => { if json { - serde_json::to_writer(&mut output, &block).map_err(|e| format!("Eror writing JSON: {}", e))?; + serde_json::to_writer(&mut output, &block) + .map_err(|e| format!("Error writing JSON: {}", e))?; } else { output.write(&block.encode())?; } @@ -86,17 +98,40 @@ pub fn export_blocks(config: FactoryFullConfiguration, exit: E, mut Ok(()) } +struct WaitLink { + wait_send: std::sync::mpsc::Sender<()>, +} + +impl WaitLink { + fn new(wait_send: std::sync::mpsc::Sender<()>) -> WaitLink { + WaitLink { + wait_send, + } + } +} + +impl Link for WaitLink { + fn block_imported(&self, _hash: &B::Hash, _number: NumberFor) { + self.wait_send.send(()) + .expect("Unable to notify main process; if the main process panicked then this thread would already be dead as well. qed."); + } +} + /// Import blocks from a binary stream. -pub fn import_blocks(mut config: FactoryFullConfiguration, exit: E, mut input: R) -> error::Result<()> +pub fn import_blocks( + mut config: FactoryFullConfiguration, + exit: E, + mut input: R +) -> error::Result<()> where F: ServiceFactory, E: Future + Send + 'static, R: Read, { - struct DummyLink; - impl Link for DummyLink { } - let client = new_client::(&config)?; - // FIXME: this shouldn't need a mutable config. https://github.com/paritytech/substrate/issues/1134 + // FIXME #1134 this shouldn't need a mutable config. let queue = components::FullComponents::::build_import_queue(&mut config, client.clone())?; - queue.start(DummyLink)?; + + let (wait_send, wait_recv) = std::sync::mpsc::channel(); + let wait_link = WaitLink::new(wait_send); + queue.start(Box::new(wait_link))?; let (exit_send, exit_recv) = std::sync::mpsc::channel(); ::std::thread::spawn(move || { @@ -104,7 +139,7 @@ pub fn import_blocks(mut config: FactoryFullConfiguration, exit: E, let _ = exit_send.send(()); }); - let count: u32 = Decode::decode(&mut input).ok_or("Error reading file")?; + let count: u64 = Decode::decode(&mut input).ok_or("Error reading file")?; info!("Importing {} blocks", count); let mut block_count = 0; for b in 0 .. count { @@ -123,7 +158,15 @@ pub fn import_blocks(mut config: FactoryFullConfiguration, exit: E, message_queue: None }; // import queue handles verification and importing it into the client - queue.import_blocks(BlockOrigin::File, vec![BlockData:: { block, origin: None }]); + queue.import_blocks(BlockOrigin::File, vec![ + IncomingBlock::{ + hash: block.hash, + header: block.header, + body: block.body, + justification: block.justification, + origin: None, + } + ]); } else { warn!("Error reading block data at {}.", b); break; @@ -134,19 +177,35 @@ pub fn import_blocks(mut config: FactoryFullConfiguration, exit: E, info!("#{}", b); } } + + let mut blocks_imported = 0; + while blocks_imported < count { + wait_recv.recv() + .expect("Importing thread has panicked. Then the main process will die before this can be reached. qed."); + blocks_imported += 1; + } + info!("Imported {} blocks. Best: #{}", block_count, client.info()?.chain.best_number); Ok(()) } /// Revert the chain. -pub fn revert_chain(config: FactoryFullConfiguration, blocks: FactoryBlockNumber) -> error::Result<()> +pub fn revert_chain( + config: FactoryFullConfiguration, + blocks: FactoryBlockNumber +) -> error::Result<()> where F: ServiceFactory, { let client = new_client::(&config)?; let reverted = client.revert(blocks)?; let info = client.info()?.chain; - info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); + + if reverted.as_() == 0 { + info!("There aren't any non-finalized blocks to revert."); + } else { + info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); + } Ok(()) } diff --git a/core/service/src/chain_spec.rs b/core/service/src/chain_spec.rs index dafae1501c6910f9146d5fbad1554f79ede5d770..45b61f0eebdfeb9a1826f2d2d8952a5483ce1934 100644 --- a/core/service/src/chain_spec.rs +++ b/core/service/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,11 +19,13 @@ use std::collections::HashMap; use std::fs::File; use std::path::PathBuf; +use serde_derive::{Serialize, Deserialize}; use primitives::storage::{StorageKey, StorageData}; -use runtime_primitives::{BuildStorage, StorageMap, ChildrenStorageMap}; +use runtime_primitives::{BuildStorage, StorageOverlay, ChildrenStorageOverlay}; use serde_json as json; -use components::RuntimeGenesis; +use crate::components::RuntimeGenesis; use network::Multiaddr; +use tel::TelemetryEndpoints; enum GenesisSource { File(PathBuf), @@ -64,12 +66,15 @@ impl GenesisSource { } impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { - fn build_storage(self) -> Result<(StorageMap, ChildrenStorageMap), String> { + fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { match self.genesis.resolve()? { Genesis::Runtime(gc) => gc.build_storage(), Genesis::Raw(map) => Ok((map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), Default::default())), } } + fn assimilate_storage(self, _: &mut StorageOverlay, _: &mut ChildrenStorageOverlay) -> Result<(), String> { + Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) + } } #[derive(Serialize, Deserialize)] @@ -86,7 +91,7 @@ struct ChainSpecFile { pub name: String, pub id: String, pub boot_nodes: Vec, - pub telemetry_url: Option, + pub telemetry_endpoints: Option, pub protocol_id: Option, pub consensus_engine: Option, pub properties: Option, @@ -123,8 +128,8 @@ impl ChainSpec { &self.spec.id } - pub fn telemetry_url(&self) -> Option<&str> { - self.spec.telemetry_url.as_ref().map(String::as_str) + pub fn telemetry_endpoints(&self) -> &Option { + &self.spec.telemetry_endpoints } pub fn protocol_id(&self) -> Option<&str> { @@ -169,7 +174,7 @@ impl ChainSpec { id: &str, constructor: fn() -> G, boot_nodes: Vec, - telemetry_url: Option<&str>, + telemetry_endpoints: Option, protocol_id: Option<&str>, consensus_engine: Option<&str>, properties: Option, @@ -179,7 +184,7 @@ impl ChainSpec { name: name.to_owned(), id: id.to_owned(), boot_nodes: boot_nodes, - telemetry_url: telemetry_url.map(str::to_owned), + telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), consensus_engine: consensus_engine.map(str::to_owned), properties, diff --git a/core/service/src/components.rs b/core/service/src/components.rs index d5a4c5bc8a14a4ed3a5c438e330d31834ad3abc5..94f5e69c8f3951f5098a0e2e654527245406bd49 100644 --- a/core/service/src/components.rs +++ b/core/service/src/components.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,15 +19,18 @@ use std::{sync::Arc, net::SocketAddr, marker::PhantomData, ops::Deref, ops::DerefMut}; use serde::{Serialize, de::DeserializeOwned}; use tokio::runtime::TaskExecutor; -use chain_spec::ChainSpec; +use crate::chain_spec::ChainSpec; use client_db; use client::{self, Client, runtime_api::{Metadata, TaggedTransactionQueue}}; -use {error, Service, maybe_start_server}; -use network::{self, OnDemand, import_queue::ImportQueue}; +use crate::{error, Service, maybe_start_server}; +use consensus_common::import_queue::ImportQueue; +use network::{self, OnDemand}; use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool}; -use runtime_primitives::{BuildStorage, traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}, generic::{BlockId, SignedBlock}}; -use config::Configuration; +use runtime_primitives::{ + BuildStorage, traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}, generic::BlockId +}; +use crate::config::Configuration; use primitives::{Blake2Hasher, H256}; use rpc::{self, apis::system::SystemInfo}; use parking_lot::Mutex; @@ -35,11 +38,7 @@ use parking_lot::Mutex; // Type aliases. // These exist mainly to avoid typing `::Foo` all over the code. /// Network service type for a factory. -pub type NetworkService = network::Service< - ::Block, - ::NetworkProtocol, - <::Block as BlockT>::Hash, ->; +pub type NetworkService = network::Service<::Block, ::NetworkProtocol>; /// Code executor type for a factory. pub type CodeExecutor = NativeExecutor<::RuntimeDispatch>; @@ -56,17 +55,33 @@ pub type FullExecutor = client::LocalCallExecutor< /// Light client backend type for a factory. pub type LightBackend = client::light::backend::Backend< client_db::light::LightStorage<::Block>, - network::OnDemand<::Block, NetworkService>, + network::OnDemand<::Block>, + Blake2Hasher, >; /// Light client executor type for a factory. -pub type LightExecutor = client::light::call_executor::RemoteCallExecutor< - client::light::blockchain::Blockchain< +pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor< + ::Block, + client::light::backend::Backend< client_db::light::LightStorage<::Block>, - network::OnDemand<::Block, NetworkService> + network::OnDemand<::Block>, + Blake2Hasher >, - network::OnDemand<::Block, NetworkService>, - Blake2Hasher, + client::light::call_executor::RemoteCallExecutor< + client::light::blockchain::Blockchain< + client_db::light::LightStorage<::Block>, + network::OnDemand<::Block> + >, + network::OnDemand<::Block> + >, + client::LocalCallExecutor< + client::light::backend::Backend< + client_db::light::LightStorage<::Block>, + network::OnDemand<::Block>, + Blake2Hasher + >, + CodeExecutor + > >; /// Full client type for a factory. @@ -134,8 +149,8 @@ pub trait StartRPC { } impl StartRPC for C where - C::RuntimeApi: Metadata>, - for<'de> SignedBlock>: ::serde::Deserialize<'de>, + ComponentClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: Metadata>, { type ServersHandle = (Option, Option>); @@ -184,45 +199,45 @@ pub trait MaintainTransactionPool { ) -> error::Result<()>; } +fn on_block_imported( + id: &BlockId, + client: &Client, + transaction_pool: &TransactionPool, +) -> error::Result<()> where + Block: BlockT::Out>, + Backend: client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue, + Executor: client::CallExecutor, + PoolApi: txpool::ChainApi, +{ + // Avoid calling into runtime if there is nothing to prune from the pool anyway. + if transaction_pool.status().is_empty() { + return Ok(()) + } + + if let Some(block) = client.block(id)? { + let parent_id = BlockId::hash(*block.block.header().parent_hash()); + let extrinsics = block.block.extrinsics(); + transaction_pool.prune(id, &parent_id, extrinsics).map_err(|e| format!("{:?}", e))?; + } + + Ok(()) +} + impl MaintainTransactionPool for C where - ComponentClient: ProvideRuntimeApi, - C::RuntimeApi: TaggedTransactionQueue>, + ComponentClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: TaggedTransactionQueue>, { - // TODO [ToDr] Optimize and re-use tags from the pool. fn on_block_imported( id: &BlockId>, client: &ComponentClient, transaction_pool: &TransactionPool, ) -> error::Result<()> { - use runtime_primitives::transaction_validity::TransactionValidity; - - let block = client.block(id)?; - let tags = match block { - None => return Ok(()), - Some(block) => { - let mut tags = vec![]; - for tx in block.block.extrinsics() { - let tx = client.runtime_api().validate_transaction(id, &tx)?; - match tx { - TransactionValidity::Valid { mut provides, .. } => { - tags.append(&mut provides); - }, - // silently ignore invalid extrinsics, - // cause they might just be inherent - _ => {} - } - - } - tags - } - }; - - transaction_pool.prune_tags(id, tags).map_err(|e| format!("{:?}", e))?; - Ok(()) + on_block_imported(id, client, transaction_pool) } } - /// The super trait that combines all required traits a `Service` needs to implement. pub trait ServiceTrait: Deref> @@ -259,9 +274,9 @@ pub trait ServiceFactory: 'static + Sized { /// Extended light service type. type LightService: ServiceTrait>; /// ImportQueue for full client - type FullImportQueue: network::import_queue::ImportQueue + 'static; + type FullImportQueue: consensus_common::import_queue::ImportQueue + 'static; /// ImportQueue for light clients - type LightImportQueue: network::import_queue::ImportQueue + 'static; + type LightImportQueue: consensus_common::import_queue::ImportQueue + 'static; //TODO: replace these with a constructor trait. that TransactionPool implements. (#1242) /// Extrinsic pool constructor for the full client. @@ -325,7 +340,7 @@ pub trait Components: Sized + 'static { type RuntimeApi: Send + Sync; /// A type that can start the RPC. type RPC: StartRPC; - // TODO [ToDr] Traitify transaction pool and allow people to implement their own. (#1242) + // TODO: Traitify transaction pool and allow people to implement their own. (#1242) /// A type that can maintain transaction pool. type TransactionPool: MaintainTransactionPool; /// Extrinsic pool type. @@ -344,7 +359,7 @@ pub trait Components: Sized + 'static { ) -> Result< ( Arc>, - Option, NetworkService>>> + Option>>> ), error::Error >; @@ -410,7 +425,7 @@ impl Components for FullComponents { ) -> Result<( Arc>, - Option, NetworkService>>> + Option>>> ), error::Error> { let db_settings = client_db::DatabaseSettings { @@ -422,8 +437,7 @@ impl Components for FullComponents { db_settings, executor, &config.chain_spec, - config.block_execution_strategy, - config.api_execution_strategy, + config.execution_strategies.clone(), )?), None)) } @@ -486,7 +500,7 @@ impl Components for LightComponents { -> Result< ( Arc>, - Option, NetworkService>>> + Option>>> ), error::Error> { let db_settings = client_db::DatabaseSettings { @@ -496,10 +510,10 @@ impl Components for LightComponents { }; let db_storage = client_db::light::LightStorage::new(db_settings)?; let light_blockchain = client::light::new_light_blockchain(db_storage); - let fetch_checker = Arc::new(client::light::new_fetch_checker::<_, Blake2Hasher, _, _, _>(light_blockchain.clone(), executor)); + let fetch_checker = Arc::new(client::light::new_fetch_checker(light_blockchain.clone(), executor.clone())); let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); let client_backend = client::light::new_light_backend(light_blockchain, fetcher.clone()); - let client = client::light::new_light(client_backend, fetcher.clone(), &config.chain_spec)?; + let client = client::light::new_light(client_backend, fetcher.clone(), &config.chain_spec, executor)?; Ok((Arc::new(client), Some(fetcher))) } @@ -516,3 +530,48 @@ impl Components for LightComponents { Factory::build_light_import_queue(config, client) } } + +#[cfg(test)] +mod tests { + use super::*; + use parity_codec::Encode; + use consensus_common::BlockOrigin; + use substrate_test_client::{self, TestClient, AccountKeyring, runtime::{Extrinsic, Transfer}}; + + #[test] + fn should_remove_transactions_from_the_pool() { + let client = Arc::new(substrate_test_client::new()); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone())); + let transaction = { + let transfer = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }; + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); + Extrinsic::Transfer(transfer, signature) + }; + // store the transaction in the pool + pool.submit_one(&BlockId::hash(client.best_block_header().unwrap().hash()), transaction.clone()).unwrap(); + + // import the block + let mut builder = client.new_block().unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.bake().unwrap(); + let id = BlockId::hash(block.header().hash()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + on_block_imported( + &id, + &client, + &pool, + ).unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } +} diff --git a/core/service/src/config.rs b/core/service/src/config.rs index 636b555617bdfe618071f918f7b11ddff60966f1..d61f5a23845f92b8f87a3ce8c6a0a44553da4531 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,13 +18,14 @@ use std::net::SocketAddr; use transaction_pool; -use chain_spec::ChainSpec; -pub use client::ExecutionStrategy; +use crate::chain_spec::ChainSpec; +pub use client::ExecutionStrategies; pub use client_db::PruningMode; pub use network::config::{NetworkConfiguration, Roles}; use runtime_primitives::BuildStorage; use serde::{Serialize, de::DeserializeOwned}; use target_info::Target; +use tel::TelemetryEndpoints; /// Service configuration. #[derive(Clone)] @@ -57,16 +58,16 @@ pub struct Configuration { pub custom: C, /// Node name. pub name: String, - /// Block execution strategy. - pub block_execution_strategy: ExecutionStrategy, - /// Runtime API execution strategy. - pub api_execution_strategy: ExecutionStrategy, + /// Execution strategies. + pub execution_strategies: ExecutionStrategies, /// RPC over HTTP binding address. `None` if disabled. pub rpc_http: Option, /// RPC over Websockets binding address. `None` if disabled. pub rpc_ws: Option, /// Telemetry service URL. `None` if disabled. - pub telemetry_url: Option, + pub telemetry_endpoints: Option, + /// The default number of 64KB pages to allocate for Wasm execution + pub default_heap_pages: Option, } impl Configuration { @@ -87,14 +88,16 @@ impl Configuration { @@ -104,14 +76,14 @@ pub struct Service { /// Configuration of this Service pub config: FactoryFullConfiguration, _rpc: Box<::std::any::Any + Send + Sync>, - _telemetry: Option, + _telemetry: Option>, } /// Creates bare client without any networking. pub fn new_client(config: &FactoryFullConfiguration) -> Result>>, error::Error> { - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(config.default_heap_pages); let (client, _) = components::FullComponents::::build_client( config, executor, @@ -130,12 +102,12 @@ impl Service { let (signal, exit) = ::exit_future::signal(); // Create client - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(config.default_heap_pages); let mut keystore = Keystore::open(config.keystore_path.as_str().into())?; // This is meant to be for testing only - // FIXME: remove this - https://github.com/paritytech/substrate/issues/1063 + // FIXME #1063 remove this for seed in &config.keys { keystore.generate_from_seed(seed)?; } @@ -152,12 +124,12 @@ impl Service { }; let (client, on_demand) = Components::build_client(&config, executor)?; - let import_queue = Arc::new(Components::build_import_queue(&mut config, client.clone())?); + let import_queue = Box::new(Components::build_import_queue(&mut config, client.clone())?); let best_header = client.best_block_header()?; let version = config.full_version(); info!("Best block: #{}", best_header.number()); - telemetry!("node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash()); + telemetry!(SUBSTRATE_INFO; "node.start"; "height" => best_header.number().as_(), "best" => ?best_header.hash()); let network_protocol = ::build_network_protocol(&config)?; let transaction_pool = Arc::new( @@ -190,12 +162,12 @@ impl Service { }; let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); - let network = network::Service::new( + let (network, network_chan) = network::Service::new( network_params, protocol_id, import_queue )?; - on_demand.map(|on_demand| on_demand.set_service_link(Arc::downgrade(&network))); + on_demand.map(|on_demand| on_demand.set_network_sender(network_chan)); { // block notifications @@ -206,7 +178,7 @@ impl Service { let events = client.import_notification_stream() .for_each(move |notification| { if let Some(network) = network.upgrade() { - network.on_block_imported(notification.hash, ¬ification.header); + network.on_block_imported(notification.hash, notification.header); } if let (Some(txpool), Some(client)) = (txpool.upgrade(), wclient.upgrade()) { Components::TransactionPool::on_block_imported( @@ -222,11 +194,56 @@ impl Service { task_executor.spawn(events); } + { + // finality notifications + let network = Arc::downgrade(&network); + + // A utility stream that drops all ready items and only returns the last one. + // This is used to only keep the last finality notification and avoid + // overloading the sync module with notifications. + struct MostRecentNotification(futures::stream::Fuse>); + + impl Stream for MostRecentNotification { + type Item = as Stream>::Item; + type Error = as Stream>::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + let mut last = None; + let last = loop { + match self.0.poll()? { + Async::Ready(Some(item)) => { last = Some(item) } + Async::Ready(None) => match last { + None => return Ok(Async::Ready(None)), + Some(last) => break last, + }, + Async::NotReady => match last { + None => return Ok(Async::NotReady), + Some(last) => break last, + }, + } + }; + + Ok(Async::Ready(Some(last))) + } + } + + let events = MostRecentNotification(client.finality_notification_stream().fuse()) + .for_each(move |notification| { + if let Some(network) = network.upgrade() { + network.on_block_finalized(notification.hash, notification.header); + } + Ok(()) + }) + .select(exit.clone()) + .then(|_| Ok(())); + + task_executor.spawn(events); + } + { // extrinsic notifications let network = Arc::downgrade(&network); let events = transaction_pool.import_notification_stream() - // TODO [ToDr] Consider throttling? .for_each(move |_| { if let Some(network) = network.upgrade() { network.trigger_repropagate(); @@ -248,35 +265,35 @@ impl Service { properties: config.chain_spec.properties(), }; let rpc = Components::RPC::start_rpc( - client.clone(), network.clone(), has_bootnodes, system_info, config.rpc_http, config.rpc_ws, task_executor.clone(), transaction_pool.clone(), + client.clone(), network.clone(), has_bootnodes, system_info, config.rpc_http, + config.rpc_ws, task_executor.clone(), transaction_pool.clone(), )?; // Telemetry - let telemetry = match config.telemetry_url.clone() { - Some(url) => { - let is_authority = config.roles == Roles::AUTHORITY; - let pubkey = format!("{}", public_key); - let name = config.name.clone(); - let impl_name = config.impl_name.to_owned(); - let version = version.clone(); - let chain_name = config.chain_spec.name().to_owned(); - Some(tel::init_telemetry(tel::TelemetryConfig { - url: url, - on_connect: Box::new(move || { - telemetry!("system.connected"; - "name" => name.clone(), - "implementation" => impl_name.clone(), - "version" => version.clone(), - "config" => "", - "chain" => chain_name.clone(), - "pubkey" => &pubkey, - "authority" => is_authority - ); - }), - })) - }, - None => None, - }; + let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { + let is_authority = config.roles == Roles::AUTHORITY; + let network_id = network.local_peer_id().to_base58(); + let pubkey = format!("{}", public_key); + let name = config.name.clone(); + let impl_name = config.impl_name.to_owned(); + let version = version.clone(); + let chain_name = config.chain_spec.name().to_owned(); + Arc::new(tel::init_telemetry(tel::TelemetryConfig { + endpoints, + on_connect: Box::new(move || { + telemetry!(SUBSTRATE_INFO; "system.connected"; + "name" => name.clone(), + "implementation" => impl_name.clone(), + "version" => version.clone(), + "config" => "", + "chain" => chain_name.clone(), + "pubkey" => &pubkey, + "authority" => is_authority, + "network_id" => network_id.clone() + ); + }), + })) + }); Ok(Service { client, @@ -303,6 +320,10 @@ impl Service { None } } + + pub fn telemetry(&self) -> Option> { + self._telemetry.as_ref().map(|t| t.clone()) + } } impl Service where Components: components::Components { @@ -345,8 +366,8 @@ impl Drop for Service where Components: components::Comp } } -fn maybe_start_server(address: Option, start: F) -> Result, io::Error> where - F: Fn(&SocketAddr) -> Result, +fn maybe_start_server(address: Option, start: F) -> Result, io::Error> + where F: Fn(&SocketAddr) -> Result, { Ok(match address { Some(mut address) => Some(start(&address) @@ -381,7 +402,9 @@ impl TransactionPoolAdapter { } } -impl network::TransactionPool, ComponentBlock> for TransactionPoolAdapter where ::RuntimeApi: Send + Sync{ +impl network::TransactionPool, ComponentBlock> for + TransactionPoolAdapter where ::RuntimeApi: Send + Sync +{ fn transactions(&self) -> Vec<(ComponentExHash, ComponentExtrinsic)> { self.pool.ready() .map(|t| { @@ -401,16 +424,16 @@ impl network::TransactionPool, ComponentBlock< let encoded = transaction.encode(); if let Some(uxt) = Decode::decode(&mut &encoded[..]) { let best_block_id = self.best_block_id()?; - let hash = self.pool.hash_of(&uxt); match self.pool.submit_one(&best_block_id, uxt) { Ok(hash) => Some(hash), Err(e) => match e.into_pool_error() { - Ok(e) => match e.kind() { - txpool::error::ErrorKind::AlreadyImported => Some(hash), - _ => { - debug!("Error adding transaction to the pool: {:?}", e); - None - }, + Ok(txpool::error::Error(txpool::error::ErrorKind::AlreadyImported(hash), _)) => { + hash.downcast::>().ok() + .map(|x| x.as_ref().clone()) + }, + Ok(e) => { + debug!("Error adding transaction to the pool: {:?}", e); + None }, Err(e) => { debug!("Error converting pool error: {:?}", e); @@ -553,7 +576,7 @@ macro_rules! construct_service_factory { fn new_full( config: $crate::FactoryFullConfiguration, - executor: $crate::TaskExecutor + executor: $crate::TaskExecutor, ) -> Result { ( $( $full_service_init )* ) (config, executor.clone()).and_then(|service| { diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml index 12282b16f15e370771e705c89703406d41cee934..1167bbd9486fc8b78714a00ede412274c7e572c0 100644 --- a/core/service/test/Cargo.toml +++ b/core/service/test/Cargo.toml @@ -2,17 +2,18 @@ name = "substrate-service-test" version = "0.3.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] tempdir = "0.3" tokio = "0.1.7" futures = "0.1" -log = "0.3" -env_logger = "0.4" +log = "0.4" +env_logger = "0.6" fdlimit = "0.1" -substrate-service = { path = "../../../core/service" } -substrate-network = { path = "../../../core/network" } -substrate-consensus-common = { path = "../../../core/consensus/common" } -substrate-primitives = { path = "../../../core/primitives" } -substrate-client = { path = "../../../core/client" } +service = { package = "substrate-service", path = "../../../core/service" } +network = { package = "substrate-network", path = "../../../core/network" } +consensus = { package = "substrate-consensus-common", path = "../../../core/consensus/common" } +primitives = { package = "substrate-primitives", path = "../../../core/primitives" } +client = { package = "substrate-client", path = "../../../core/client" } sr-primitives = { path = "../../../core/sr-primitives" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index d5aafbe675606995d6ddef704e3481394c2e20d6..3a3c4515f71c29e01a8eacaf3f8247e0c85a15f3 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,31 +16,18 @@ //! Service integration test utils. -#[macro_use] -extern crate log; -extern crate tempdir; -extern crate tokio; -extern crate futures; -extern crate env_logger; -extern crate fdlimit; -extern crate substrate_service as service; -extern crate substrate_network as network; -extern crate substrate_primitives as primitives; -extern crate substrate_client as client; -extern crate substrate_consensus_common as consensus; -extern crate sr_primitives; use std::iter; use std::sync::Arc; use std::net::Ipv4Addr; use std::time::Duration; -use futures::Stream; +use log::info; +use futures::{Future, Stream}; use tempdir::TempDir; use tokio::runtime::Runtime; use tokio::timer::Interval; use primitives::blake2_256; use service::{ ServiceFactory, - ExecutionStrategy, Configuration, FactoryFullConfiguration, FactoryChainSpec, @@ -112,6 +99,7 @@ fn node_config ( reserved_nodes: vec![], non_reserved_mode: NonReservedPeerMode::Accept, client_version: "network/test/0.1".to_owned(), + node_name: "unknown".to_owned(), }; Configuration { @@ -129,17 +117,17 @@ fn node_config ( chain_spec: (*spec).clone(), custom: Default::default(), name: format!("Node {}", index), - block_execution_strategy: ExecutionStrategy::NativeWhenPossible, - api_execution_strategy: ExecutionStrategy::NativeWhenPossible, + execution_strategies: Default::default(), rpc_http: None, rpc_ws: None, - telemetry_url: None, + telemetry_endpoints: None, + default_heap_pages: None, } } impl TestNet { fn new(temp: &TempDir, spec: FactoryChainSpec, full: u32, light: u32, authorities: Vec, base_port: u16) -> TestNet { - ::env_logger::init().ok(); + let _ = ::env_logger::try_init(); ::fdlimit::raise_fd_limit(); let runtime = Runtime::new().expect("Error creating tokio runtime"); let mut net = TestNet { @@ -181,14 +169,11 @@ impl TestNet { } } -pub fn connectivity(spec: FactoryChainSpec) where - ::RuntimeApi: - client::block_builder::api::BlockBuilder<::Block, Inherent> -{ +pub fn connectivity(spec: FactoryChainSpec) { const NUM_NODES: u32 = 10; { let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir"); - { + let runtime = { let mut network = TestNet::::new(&temp, spec.clone(), NUM_NODES, 0, vec![], 30400); info!("Checking star topology"); let first_address = network.full_nodes[0].1.network().node_id().expect("No node address"); @@ -196,15 +181,19 @@ pub fn connectivity(spec: FactoryChainSpec) wher service.network().add_reserved_peer(first_address.clone()).expect("Error adding reserved peer"); } network.run_until_all_full(|_index, service| - service.network().status().num_peers == NUM_NODES as usize - 1 + service.network().peers().len() == NUM_NODES as usize - 1 ); - } + network.runtime + }; + + runtime.shutdown_on_idle().wait().expect("Error shutting down runtime"); + temp.close().expect("Error removing temp dir"); } { let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir"); { - let mut network = TestNet::::new(&temp, spec, NUM_NODES, 0, vec![], 30500); + let mut network = TestNet::::new(&temp, spec, NUM_NODES, 0, vec![], 30400); info!("Checking linked topology"); let mut address = network.full_nodes[0].1.network().node_id().expect("No node address"); for (_, service) in network.full_nodes.iter().skip(1) { @@ -212,7 +201,7 @@ pub fn connectivity(spec: FactoryChainSpec) wher address = service.network().node_id().expect("No node address"); } network.run_until_all_full(|_index, service| { - service.network().status().num_peers == NUM_NODES as usize - 1 + service.network().peers().len() == NUM_NODES as usize - 1 }); } temp.close().expect("Error removing temp dir"); @@ -224,9 +213,6 @@ where F: ServiceFactory, B: Fn(&F::FullService) -> ImportBlock, E: Fn(&F::FullService) -> FactoryExtrinsic, - ::RuntimeApi: - client::block_builder::api::BlockBuilder<::Block, ()> + - client::runtime_api::TaggedTransactionQueue<::Block> { const NUM_NODES: u32 = 10; const NUM_BLOCKS: usize = 512; @@ -261,10 +247,8 @@ where } pub fn consensus(spec: FactoryChainSpec, authorities: Vec) -where - F: ServiceFactory, - ::RuntimeApi: - client::block_builder::api::BlockBuilder<::Block, ()> + where + F: ServiceFactory, { const NUM_NODES: u32 = 20; const NUM_BLOCKS: u64 = 200; diff --git a/core/sr-api-macros/Cargo.toml b/core/sr-api-macros/Cargo.toml index 5e6140df9d7f241cec8dfe09fcc898f16a7a9abe..e7f46129db6df4f8559b458746a1fd0442faff57 100644 --- a/core/sr-api-macros/Cargo.toml +++ b/core/sr-api-macros/Cargo.toml @@ -2,6 +2,7 @@ name = "sr-api-macros" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [lib] proc-macro = true @@ -11,10 +12,17 @@ quote = "0.6" syn = { version = "^0.15.22", features = [ "full", "fold", "extra-traits", "visit" ] } proc-macro2 = "0.4" blake2-rfc = "0.2" +proc-macro-crate = "0.1.3" [dev-dependencies] -substrate-client = { path = "../client" } -substrate-test-client = { path = "../test-client" } -sr-primitives = { path = "../sr-primitives" } +client = { package = "substrate-client", path = "../client" } +test_client = { package = "substrate-test-client", path = "../test-client" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } sr-version = { path = "../sr-version" } substrate-primitives = { path = "../primitives" } +criterion = "0.2" + +[[bench]] +name = "bench" +harness = false diff --git a/core/sr-api-macros/benches/bench.rs b/core/sr-api-macros/benches/bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..f4677217897924ef532adca0f2bac520f569c2ee --- /dev/null +++ b/core/sr-api-macros/benches/bench.rs @@ -0,0 +1,69 @@ +// Copyright 2018 - 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{Criterion, criterion_group, criterion_main}; +use test_client::runtime::TestAPI; +use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; +use state_machine::ExecutionStrategy; + +fn sr_api_benchmark(c: &mut Criterion) { + c.bench_function("add one with same runtime api", |b| { + let client = test_client::new(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + b.iter(|| runtime_api.benchmark_add_one(&block_id, &1)) + }); + + c.bench_function("add one with recreating runtime api", |b| { + let client = test_client::new(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + b.iter(|| client.runtime_api().benchmark_add_one(&block_id, &1)) + }); + + c.bench_function("vector add one with same runtime api", |b| { + let client = test_client::new(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + let data = vec![0; 1000]; + + b.iter_with_large_drop(|| runtime_api.benchmark_vector_add_one(&block_id, &data)) + }); + + c.bench_function("vector add one with recreating runtime api", |b| { + let client = test_client::new(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + let data = vec![0; 1000]; + + b.iter_with_large_drop(|| client.runtime_api().benchmark_vector_add_one(&block_id, &data)) + }); + + c.bench_function("calling function by function pointer in wasm", |b| { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + b.iter(|| client.runtime_api().benchmark_indirect_call(&block_id).unwrap()) + }); + + c.bench_function("calling function in wasm", |b| { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + b.iter(|| client.runtime_api().benchmark_direct_call(&block_id).unwrap()) + }); +} + +criterion_group!(benches, sr_api_benchmark); +criterion_main!(benches); diff --git a/core/sr-api-macros/src/compile_fail_tests.rs b/core/sr-api-macros/src/compile_fail_tests.rs index ec2c2387bd2369f8561b7fbcb642a54a546c8683..e562f8b2fe598a7e7a994b3c46748ec0952a0ad6 100644 --- a/core/sr-api-macros/src/compile_fail_tests.rs +++ b/core/sr-api-macros/src/compile_fail_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ mod declaring_own_block { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; use runtime_primitives::traits::Block as BlockT; @@ -40,7 +40,7 @@ mod declaring_own_block_with_different_name { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; use runtime_primitives::traits::Block as BlockT; @@ -60,7 +60,7 @@ mod adding_self_parameter { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; decl_runtime_apis! { @@ -78,7 +78,7 @@ mod adding_at_parameter { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; decl_runtime_apis! { @@ -92,29 +92,11 @@ mod adding_at_parameter { */ } -mod adding_parameter_with_type_reference { - /*! - ```compile_fail - #[macro_use] - extern crate substrate_client; - extern crate sr_primitives as runtime_primitives; - - decl_runtime_apis! { - pub trait Api { - fn test(data: &u64); - } - } - - fn main() {} - ``` - */ -} - mod invalid_api_version { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; decl_runtime_apis! { @@ -133,7 +115,7 @@ mod invalid_api_version_2 { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; decl_runtime_apis! { @@ -152,7 +134,7 @@ mod invalid_api_version_3 { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate sr_primitives as runtime_primitives; decl_runtime_apis! { @@ -171,7 +153,7 @@ mod missing_block_generic_parameter { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -209,7 +191,7 @@ mod missing_path_for_trait { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -247,7 +229,7 @@ mod empty_impl_runtime_apis_call { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -279,7 +261,7 @@ mod type_reference_in_impl_runtime_apis_call { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -317,7 +299,7 @@ mod impl_incorrect_method_signature { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -353,7 +335,7 @@ mod impl_two_traits_with_same_name { /*! ```compile_fail #[macro_use] - extern crate substrate_client; + extern crate client; extern crate substrate_test_client as test_client; extern crate sr_primitives as runtime_primitives; extern crate substrate_primitives as primitives; @@ -396,3 +378,35 @@ mod impl_two_traits_with_same_name { ``` */ } + +mod changed_at_unknown_version { + /*! + ```compile_fail + #[macro_use] + extern crate client; + extern crate substrate_test_client as test_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + + use runtime_primitives::traits::GetNodeBlockType; + use test_client::runtime::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + #[changed_in(2)] + fn test(data: u64); + fn test(data: u64); + } + } + + fn main() {} + ``` + */ +} diff --git a/core/sr-api-macros/src/decl_runtime_apis.rs b/core/sr-api-macros/src/decl_runtime_apis.rs index 376949a628454d3b7f7fb2b5eef4c1840bf437a3..9e4c38f0878e5dad195db76d5a121448c9cb830b 100644 --- a/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/core/sr-api-macros/src/decl_runtime_apis.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,35 +14,47 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use utils::{ +use crate::utils::{ generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait, - fold_fn_decl_for_client_side, unwrap_or_error + fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows, + generate_native_call_generator_fn_name, return_type_extract_type, + generate_method_runtime_api_impl_name }; -use proc_macro; -use proc_macro2::TokenStream; +use proc_macro2::{TokenStream, Span}; use quote::quote; use syn::{ - spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, - fold::{self, Fold}, FnDecl, parse_quote, ItemTrait, Generics, GenericParam, Attribute, - visit::{Visit, self}, FnArg, Pat, TraitBound, Type, Meta, NestedMeta, Lit + spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, ReturnType, + fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, + visit::{Visit, self}, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type, + TraitItemMethod }; use std::collections::HashMap; use blake2_rfc; +/// The ident used for the block generic parameter. +const BLOCK_GENERIC_IDENT: &str = "Block"; + /// Unique identifier used to make the hidden includes unique for this macro. const HIDDEN_INCLUDES_ID: &str = "DECL_RUNTIME_APIS"; /// The `core_trait` attribute. const CORE_TRAIT_ATTRIBUTE: &str = "core_trait"; /// The `api_version` attribute. +/// Is used to set the current version of the trait. const API_VERSION_ATTRIBUTE: &str = "api_version"; -/// All attributes that we support in the declaratio of a runtime api trait. -const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE]; +/// The `changed_in` attribute. +/// Is used when the function signature changed between different versions of a trait. +/// This attribute should be placed on the old signature of the function. +const CHANGED_IN_ATTRIBUTE: &str = "changed_in"; +/// All attributes that we support in the declaration of a runtime api trait. +const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[ + CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE, CHANGED_IN_ATTRIBUTE +]; /// The structure used for parsing the runtime api declarations. struct RuntimeApiDecls { @@ -88,7 +100,181 @@ fn remove_supported_attributes(attrs: &mut Vec) -> HashMap<&'static s result } -/// Generate the decleration of the trait for the runtime. +/// Visits the ast and checks if `Block` ident is used somewhere. +struct IsUsingBlock { + result: bool, +} + +impl<'ast> Visit<'ast> for IsUsingBlock { + fn visit_ident(&mut self, i: &'ast Ident) { + if i == BLOCK_GENERIC_IDENT { + self.result = true; + } + } +} + +/// Visits the ast and checks if `Block` ident is used somewhere. +fn type_is_using_block(ty: &Type) -> bool { + let mut visitor = IsUsingBlock { result: false }; + visitor.visit_type(ty); + visitor.result +} + +/// Visits the ast and checks if `Block` ident is used somewhere. +fn return_type_is_using_block(ty: &ReturnType) -> bool { + let mut visitor = IsUsingBlock { result: false }; + visitor.visit_return_type(ty); + visitor.result +} + +/// Replace all occurrences of `Block` with `NodeBlock` +struct ReplaceBlockWithNodeBlock {} + +impl Fold for ReplaceBlockWithNodeBlock { + fn fold_ident(&mut self, input: Ident) -> Ident { + if input == BLOCK_GENERIC_IDENT { + Ident::new("NodeBlock", Span::call_site()) + } else { + input + } + } +} + +/// Replace all occurrences of `Block` with `NodeBlock` +fn fn_arg_replace_block_with_node_block(fn_arg: FnArg) -> FnArg { + let mut replace = ReplaceBlockWithNodeBlock {}; + fold::fold_fn_arg(&mut replace, fn_arg) +} + +/// Replace all occurrences of `Block` with `NodeBlock` +fn return_type_replace_block_with_node_block(return_type: ReturnType) -> ReturnType { + let mut replace = ReplaceBlockWithNodeBlock {}; + fold::fold_return_type(&mut replace, return_type) +} + +fn generate_native_call_generators(decl: &ItemTrait) -> Result { + let fns = decl.items.iter().filter_map(|i| match i { + TraitItem::Method(ref m) => Some(&m.sig), + _ => None, + }); + + let mut result = Vec::new(); + let trait_ = &decl.ident; + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + + // Auxiliary function that is used to convert between types that use different block types. + // The function expects that both a convertable by encoding the one and decoding the other. + result.push(quote!( + #[cfg(any(feature = "std", test))] + fn convert_between_block_types + ( + input: &I, error_desc: &'static str, + ) -> ::std::result::Result + { + ::decode( + &mut &#crate_::runtime_api::Encode::encode(input)[..] + ).ok_or_else(|| error_desc) + } + )); + + // Generate a native call generator for each function of the given trait. + for fn_ in fns { + let params = extract_parameter_names_types_and_borrows(&fn_.decl)?; + let trait_fn_name = &fn_.ident; + let fn_name = generate_native_call_generator_fn_name(&fn_.ident); + let output = return_type_replace_block_with_node_block(fn_.decl.output.clone()); + let output_ty = return_type_extract_type(&output); + let output = quote!( ::std::result::Result<#output_ty, &'static str> ); + + // Every type that is using the `Block` generic parameter, we need to encode/decode, + // to make it compatible between the runtime/node. + let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| { + let name_str = format!( + "Could not convert parameter `{}` between node and runtime!", quote!(#n) + ); + quote!( + let #n: #t = convert_between_block_types(&#n, #name_str)?; + ) + }); + // Same as for the input types, we need to check if we also need to convert the output, + // before returning it. + let output_conversion = if return_type_is_using_block(&fn_.decl.output) { + quote!( + convert_between_block_types( + &res, + "Could not convert return value from runtime to node!" + ) + ) + } else { + quote!( Ok(res) ) + }; + + let input_names = params.iter().map(|v| &v.0); + // If the type is using the block generic type, we will encode/decode it to make it + // compatible. To ensure that we forward it by ref/value, we use the value given by the + // the user. Otherwise if it is not using the block, we don't need to add anything. + let input_borrows = params + .iter() + .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() }); + + // Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect + // all the function inputs. + let fn_inputs = fn_ + .decl + .inputs + .iter() + .map(|v| fn_arg_replace_block_with_node_block(v.clone())) + .map(|v| match v { + FnArg::Captured(ref arg) => { + let mut arg = arg.clone(); + match arg.ty { + Type::Reference(ref mut r) => { + r.lifetime = Some(parse_quote!( 'a )); + }, + _ => {} + } + FnArg::Captured(arg) + }, + r => r.clone(), + }); + + let (impl_generics, ty_generics, where_clause) = decl.generics.split_for_impl(); + // We need to parse them again, to get an easy access to the actual parameters. + let impl_generics: Generics = parse_quote!(#impl_generics); + let impl_generics_params = impl_generics.params.iter().map(|p| { + match p { + GenericParam::Type(ref ty) => { + let mut ty = ty.clone(); + ty.bounds.push(parse_quote!( 'a )); + GenericParam::Type(ty) + }, + // We should not see anything different than type params here. + r => r.clone(), + } + }); + + // Generate the generator function + result.push(quote!( + #[cfg(any(feature = "std", test))] + pub fn #fn_name< + 'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::runtime_api::BlockT + #(, #impl_generics_params)* + >( + #( #fn_inputs ),* + ) -> impl FnOnce() -> #output + 'a #where_clause { + move || { + #( #conversions )* + let res = ApiImpl::#trait_fn_name(#( #input_borrows #input_names ),*); + #output_conversion + } + } + )); + } + + Ok(quote!( #( #result )* )) +} + +/// Generate the declaration of the trait for the runtime. fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { let mut result = Vec::new(); @@ -102,8 +288,24 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { })); let id = generate_runtime_api_id(&decl.ident.to_string()); + // Remove methods that have the `changed_in` attribute as they are not required for the + // runtime anymore. + decl.items = decl.items.iter_mut().filter_map(|i| match i { + TraitItem::Method(ref mut method) => { + if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { + None + } else { + Some(TraitItem::Method(method.clone())) + } + } + r => Some(r.clone()), + }).collect(); + + let native_call_generators = unwrap_or_error(generate_native_call_generators(&decl)); + result.push(quote!( #[doc(hidden)] + #[allow(dead_code)] pub mod #mod_name { use super::*; @@ -112,6 +314,8 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { pub #api_version pub #id + + #native_call_generators } )); } @@ -124,25 +328,187 @@ struct ToClientSideDecl<'a> { block_id: &'a TokenStream, crate_: &'a TokenStream, found_attributes: &'a mut HashMap<&'static str, Attribute>, + /// Any error that we found while converting this declaration. + errors: &'a mut Vec, } -impl<'a> Fold for ToClientSideDecl<'a> { - fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { - let input = fold_fn_decl_for_client_side( - input, +impl<'a> ToClientSideDecl<'a> { + fn fold_item_trait_items(&mut self, items: Vec) -> Vec { + let mut result = Vec::new(); + + items.into_iter().for_each(|i| match i { + TraitItem::Method(method) => { + let (fn_decl, fn_impl, fn_decl_ctx) = self.fold_trait_item_method(method); + result.push(fn_decl.into()); + result.push(fn_decl_ctx.into()); + + if let Some(fn_impl) = fn_impl { + result.push(fn_impl.into()); + } + }, + r => result.push(r), + }); + + result + } + + fn fold_trait_item_method(&mut self, method: TraitItemMethod) + -> (TraitItemMethod, Option, TraitItemMethod) { + let crate_ = self.crate_; + let context_other = quote!( #crate_::runtime_api::ExecutionContext::Other ); + let fn_impl = self.create_method_runtime_api_impl(method.clone()); + let fn_decl = self.create_method_decl(method.clone(), context_other); + let fn_decl_ctx = self.create_method_decl_with_context(method); + + (fn_decl, fn_impl, fn_decl_ctx) + } + + fn create_method_decl_with_context(&mut self, method: TraitItemMethod) -> TraitItemMethod { + let crate_ = self.crate_; + let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext ); + let mut fn_decl_ctx = self.create_method_decl(method, quote!( context )); + fn_decl_ctx.sig.ident = Ident::new(&format!("{}_with_context", &fn_decl_ctx.sig.ident), Span::call_site()); + fn_decl_ctx.sig.decl.inputs.insert(2, context_arg); + + fn_decl_ctx + } + + /// Takes the given method and creates a `method_runtime_api_impl` method that will be + /// implemented in the runtime for the client side. + fn create_method_runtime_api_impl(&mut self, mut method: TraitItemMethod) -> Option { + if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { + return None; + } + + let fn_decl = &method.sig.decl; + let ret_type = return_type_extract_type(&fn_decl.output); + + // Get types and if the value is borrowed from all parameters. + // If there is an error, we push it as the block to the user. + let param_types = match extract_parameter_names_types_and_borrows(fn_decl) { + Ok(res) => res.into_iter().map(|v| { + let ty = v.1; + let borrow = v.2; + quote!( #borrow #ty ) + }).collect::>(), + Err(e) => { + self.errors.push(e.to_compile_error()); + Vec::new() + } + }; + let name = generate_method_runtime_api_impl_name(&method.sig.ident); + let block_id = self.block_id; + let crate_ = self.crate_; + + Some( + parse_quote!{ + #[doc(hidden)] + fn #name( + &self, + at: &#block_id, + context: #crate_::runtime_api::ExecutionContext, + params: Option<( #( #param_types ),* )>, + params_encoded: Vec, + ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>>; + } + ) + } + + /// Takes the method declared by the user and creates the declaration we require for the runtime + /// api client side. This method will call by default the `method_runtime_api_impl` for doing + /// the actual call into the runtime. + fn create_method_decl(&mut self, mut method: TraitItemMethod, context: TokenStream) -> TraitItemMethod { + let params = match extract_parameter_names_types_and_borrows(&method.sig.decl) { + Ok(res) => res.into_iter().map(|v| v.0).collect::>(), + Err(e) => { + self.errors.push(e.to_compile_error()); + Vec::new() + } + }; + let params2 = params.clone(); + let ret_type = return_type_extract_type(&method.sig.decl.output); + + method.sig.decl = fold_fn_decl_for_client_side( + method.sig.decl.clone(), &self.block_id, &self.crate_ ); + let name_impl = generate_method_runtime_api_impl_name(&method.sig.ident); + let crate_ = self.crate_; + + let found_attributes = remove_supported_attributes(&mut method.attrs); + // If the method has a `changed_in` attribute, we need to alter the method name to + // `method_before_version_VERSION`. + let (native_handling, param_tuple) = match get_changed_in(&found_attributes) { + Ok(Some(version)) => { + // Make sure that the `changed_in` version is at least the current `api_version`. + if get_api_version(&self.found_attributes).ok() < Some(version) { + self.errors.push( + Error::new( + method.span(), + "`changed_in` version can not be greater than the `api_version`", + ).to_compile_error() + ); + } + + let ident = Ident::new( + &format!("{}_before_version_{}", method.sig.ident, version), + method.sig.ident.span() + ); + method.sig.ident = ident; + method.attrs.push(parse_quote!( #[deprecated] )); + + let panic = format!("Calling `{}` should not return a native value!", method.sig.ident); + (quote!( panic!(#panic) ), quote!( None )) + }, + Ok(None) => (quote!( Ok(n) ), quote!( Some(( #( #params2 ),* )) )), + Err(e) => { + self.errors.push(e.to_compile_error()); + (quote!( unimplemented!() ), quote!( None )) + } + }; - fold::fold_fn_decl(self, input) + let function_name = method.sig.ident.to_string(); + + // Generate the default implementation that calls the `method_runtime_api_impl` method. + method.default = Some( + parse_quote! { + { + let runtime_api_impl_params_encoded = + #crate_::runtime_api::Encode::encode(&( #( &#params ),* )); + + self.#name_impl(at, #context, #param_tuple, runtime_api_impl_params_encoded) + .and_then(|r| + match r { + #crate_::runtime_api::NativeOrEncoded::Native(n) => { + #native_handling + }, + #crate_::runtime_api::NativeOrEncoded::Encoded(r) => { + <#ret_type as #crate_::runtime_api::Decode>::decode(&mut &r[..]) + .ok_or_else(|| + #crate_::error::ErrorKind::CallResultDecode( + #function_name + ).into() + ) + } + } + ) + } + } + ); + + method } +} +impl<'a> Fold for ToClientSideDecl<'a> { fn fold_item_trait(&mut self, mut input: ItemTrait) -> ItemTrait { extend_generics_with_block(&mut input.generics); *self.found_attributes = remove_supported_attributes(&mut input.attrs); // Check if this is the `Core` runtime api trait. let is_core_trait = self.found_attributes.contains_key(CORE_TRAIT_ATTRIBUTE); + let block_ident = Ident::new(BLOCK_GENERIC_IDENT, Span::call_site()); if is_core_trait { // Add all the supertraits we want to have for `Core`. @@ -151,17 +517,17 @@ impl<'a> Fold for ToClientSideDecl<'a> { 'static + Send + Sync - + #crate_::runtime_api::ConstructRuntimeApi - + #crate_::runtime_api::ApiExt + + #crate_::runtime_api::ApiExt<#block_ident> ); } else { // Add the `Core` runtime api as super trait. let crate_ = &self.crate_; - input.supertraits.push(parse_quote!( #crate_::runtime_api::Core )); + input.supertraits.push(parse_quote!( #crate_::runtime_api::Core<#block_ident> )); } // The client side trait is only required when compiling with the feature `std` or `test`. input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] )); + input.items = self.fold_item_trait_items(input.items); fold::fold_item_trait(self, input) } @@ -220,7 +586,7 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { let (impl_generics, ty_generics, where_clause) = trait_.generics.split_for_impl(); quote!( - #[cfg(any(feature = "std", test))] + #[cfg(any(feature = "std", test))] impl #impl_generics #crate_::runtime_api::RuntimeApiInfo for #trait_name #ty_generics #where_clause { @@ -230,30 +596,36 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { ) } +/// Get changed in version from the user given attribute or `Ok(None)`, if no attribute was given. +fn get_changed_in(found_attributes: &HashMap<&'static str, Attribute>) -> Result> { + found_attributes.get(&CHANGED_IN_ATTRIBUTE) + .map(|v| parse_runtime_api_version(v).map(Some)) + .unwrap_or(Ok(None)) +} + /// Get the api version from the user given attribute or `Ok(1)`, if no attribute was given. fn get_api_version(found_attributes: &HashMap<&'static str, Attribute>) -> Result { - match found_attributes.get(&API_VERSION_ATTRIBUTE) { - Some(attr) => parse_runtime_api_version(attr), - None => Ok(1), - } + found_attributes.get(&API_VERSION_ATTRIBUTE).map(parse_runtime_api_version).unwrap_or(Ok(1)) } -/// Generate the decleration of the trait for the client side. +/// Generate the declaration of the trait for the client side. fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { let mut result = Vec::new(); for decl in decls { - let mut decl = decl.clone(); + let decl = decl.clone(); let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let block_id = quote!( #crate_::runtime_api::BlockId ); let mut found_attributes = HashMap::new(); + let mut errors = Vec::new(); let decl = { let mut to_client_side = ToClientSideDecl { crate_: &crate_, block_id: &block_id, - found_attributes: &mut found_attributes + found_attributes: &mut found_attributes, + errors: &mut errors, }; to_client_side.fold_item_trait(decl) }; @@ -264,7 +636,7 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { api_version.map(|v| generate_runtime_info_impl(&decl, v)) ); - result.push(quote!( #decl #runtime_info )); + result.push(quote!( #decl #runtime_info #( #errors )* )); } quote!( #( #result )* ) @@ -291,19 +663,6 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { }, _ => {} } - - match arg.ty { - Type::Reference(ref reference) => { - self.errors.push( - Error::new( - reference.span(), - "Do not use type references as arguments. The client side \ - declaration will take all arguments as reference automatically." - ) - ) - }, - _ => {}, - } }, FnArg::SelfRef(_) | FnArg::SelfValue(_) => { self.errors.push(Error::new(input.span(), "Self values are not supported.")) @@ -323,7 +682,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { fn visit_generic_param(&mut self, input: &'ast GenericParam) { match input { - GenericParam::Type(ty) if &ty.ident == "Block" => { + GenericParam::Type(ty) if &ty.ident == BLOCK_GENERIC_IDENT => { self.errors.push( Error::new( input.span(), @@ -340,7 +699,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { fn visit_trait_bound(&mut self, input: &'ast TraitBound) { if let Some(last_ident) = input.path.segments.last().map(|v| &v.value().ident) { - if last_ident == "BlockT" || last_ident == "Block" { + if last_ident == "BlockT" || last_ident == BLOCK_GENERIC_IDENT { self.errors.push( Error::new( input.span(), diff --git a/core/sr-api-macros/src/impl_runtime_apis.rs b/core/sr-api-macros/src/impl_runtime_apis.rs index a6aa4b82a54ea3958175ef413a28133ce81c7518..5cfb5fcc9321ffaea52a775e5232e47d5756055b 100644 --- a/core/sr-api-macros/src/impl_runtime_apis.rs +++ b/core/sr-api-macros/src/impl_runtime_apis.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,20 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use utils::{ +use crate::utils::{ unwrap_or_error, generate_crate_access, generate_hidden_includes, - generate_runtime_mod_name_for_trait, fold_fn_decl_for_client_side + generate_runtime_mod_name_for_trait, generate_method_runtime_api_impl_name, + extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name, + return_type_extract_type }; -use proc_macro; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{ - spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, FnArg, Path, + spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, Path, ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, - fold::{self, Fold}, FnDecl, parse_quote, Pat + fold::{self, Fold}, parse_quote }; use std::{collections::HashSet, iter}; @@ -60,47 +61,17 @@ fn generate_impl_call( input: &Ident, impl_trait: &Path ) -> Result { - let mut pnames = Vec::new(); - let mut ptypes = Vec::new(); - let mut generated_pattern_counter = 0; - for input in signature.decl.inputs.iter() { - match input { - FnArg::Captured(arg) => { - match &arg.ty { - Type::Reference(_) => { - return Err( - Error::new( - arg.ty.span(), - "No type references are allowed in the api traits!" - ) - ) - }, - _ => {}, - } - - pnames.push( - generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter) - ); - ptypes.push(&arg.ty); - }, - _ => { - return Err( - Error::new( - input.span(), - "Only function arguments with the following \ - pattern are accepted: `name: type`!" - ) - ) - } - } - } + let params = extract_parameter_names_types_and_borrows(&signature.decl)?; let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c_iter = iter::repeat(&c); let fn_name = &signature.ident; let fn_name_str = iter::repeat(fn_name.to_string()); let input = iter::repeat(input); - let pnames2 = pnames.clone(); + let pnames = params.iter().map(|v| &v.0); + let pnames2 = params.iter().map(|v| &v.0); + let ptypes = params.iter().map(|v| &v.1); + let pborrow = params.iter().map(|v| &v.2); Ok( quote!( @@ -111,7 +82,7 @@ fn generate_impl_call( }; )* - let output = <#runtime as #impl_trait>::#fn_name(#( #pnames2 ),*); + let output = <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*); #c::runtime_api::Encode::encode(&output) ).into() ) @@ -294,10 +265,11 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result>, + pub struct RuntimeApiImpl + 'static> { + call: &'static C, commit_on_success: ::std::cell::RefCell, initialised_block: ::std::cell::RefCell>, changes: ::std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, @@ -307,12 +279,14 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result> Send for RuntimeApiImpl {} #[cfg(any(feature = "std", test))] - unsafe impl Sync for RuntimeApi {} + unsafe impl> Sync for RuntimeApiImpl {} #[cfg(any(feature = "std", test))] - impl #crate_::runtime_api::ApiExt<#block> for RuntimeApi { + impl> #crate_::runtime_api::ApiExt<#block> + for RuntimeApiImpl + { fn map_api_result ::std::result::Result, R, E>( &self, map_call: F @@ -326,26 +300,25 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result( + fn runtime_version_at( &self, at: &#block_id - ) -> #crate_::error::Result where Self: Sized { - unsafe { self.call.as_ref().runtime_version_at(at) }.map(|r| r.has_api::()) + ) -> #crate_::error::Result<#crate_::runtime_api::RuntimeVersion> { + self.call.runtime_version_at(at) } } #[cfg(any(feature = "std", test))] - impl #crate_::runtime_api::ConstructRuntimeApi<#block> for RuntimeApi { - fn construct_runtime_api<'a, T: #crate_::runtime_api::CallRuntimeAt<#block>>( - call: &'a T - ) -> #crate_::runtime_api::ApiRef<'a, Self> where Self: Sized { - RuntimeApi { - call: unsafe { - ::std::ptr::NonNull::new_unchecked( - call as - &#crate_::runtime_api::CallRuntimeAt<#block> as *const _ as *mut _ - ) - }, + impl + 'static> + #crate_::runtime_api::ConstructRuntimeApi<#block, C> for RuntimeApi + { + type RuntimeApi = RuntimeApiImpl; + + fn construct_runtime_api<'a>( + call: &'a C, + ) -> #crate_::runtime_api::ApiRef<'a, Self::RuntimeApi> { + RuntimeApiImpl { + call: unsafe { ::std::mem::transmute(call) }, commit_on_success: true.into(), initialised_block: None.into(), changes: Default::default(), @@ -354,25 +327,27 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result( + impl> RuntimeApiImpl { + fn call_api_at< + R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq, + NC: FnOnce() -> ::std::result::Result + ::std::panic::UnwindSafe, + >( &self, at: &#block_id, function: &'static str, - args: &A - ) -> #crate_::error::Result { + args: Vec, + native_call: Option, + context: #crate_::runtime_api::ExecutionContext + ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded> { let res = unsafe { - self.call.as_ref().call_api_at( + self.call.call_api_at( at, function, - args.encode(), + args, &mut *self.changes.borrow_mut(), - &mut *self.initialised_block.borrow_mut() - ).and_then(|r| - R::decode(&mut &r[..]) - .ok_or_else(|| - #crate_::error::ErrorKind::CallResultDecode(function).into() - ) + &mut *self.initialised_block.borrow_mut(), + native_call, + context ) }; @@ -431,23 +406,8 @@ fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { Ok(quote!( #( #impls_prepared )* )) } -/// Generate an unique pattern based on the given counter, if the given pattern is a `_`. -fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat { - match pat { - Pat::Wild(_) => { - let generated_name = Ident::new( - &format!("impl_runtime_api_generated_name_{}", counter), - pat.span() - ); - *counter += 1; - - parse_quote!( #generated_name ) - }, - _ => pat, - } -} -/// Auxilariy data structure that is used to convert `impl Api for Runtime` to +/// Auxiliary data structure that is used to convert `impl Api for Runtime` to /// `impl Api for RuntimeApi`. /// This requires us to replace the runtime `Block` with the node `Block`, /// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations @@ -457,6 +417,9 @@ struct ApiRuntimeImplToApiRuntimeApiImpl<'a> { runtime_block: &'a TypePath, node_block_id: &'a TokenStream, impl_trait_ident: &'a Ident, + runtime_mod_path: &'a Path, + runtime_type: &'a Type, + trait_generic_arguments: &'a [GenericArgument] } impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { @@ -471,41 +434,96 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { fold::fold_type_path(self, new_ty_path) } - fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { - let input = fold_fn_decl_for_client_side( - input, - &self.node_block_id, - &generate_crate_access(HIDDEN_INCLUDES_ID) - ); + fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod { + let block = { + let runtime_mod_path = self.runtime_mod_path; + let runtime = self.runtime_type; + let fn_name = prefix_function_with_trait(self.impl_trait_ident, &input.sig.ident); + let native_call_generator_ident = + generate_native_call_generator_fn_name(&input.sig.ident); + let trait_generic_arguments = self.trait_generic_arguments; + let node_block = self.node_block; + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let block_id = self.node_block_id; + + // Generate the access to the native parameters + let param_tuple_access = if input.sig.decl.inputs.len() == 1 { + vec![ quote!( p ) ] + } else { + input.sig.decl.inputs.iter().enumerate().map(|(i, _)| { + let i = syn::Index::from(i); + quote!( p.#i ) + }).collect::>() + }; + + let (param_types, error) = match extract_parameter_names_types_and_borrows(&input.sig.decl) { + Ok(res) => ( + res.into_iter().map(|v| { + let ty = v.1; + let borrow = v.2; + quote!( #borrow #ty ) + }).collect::>(), + None + ), + Err(e) => (Vec::new(), Some(e.to_compile_error())), + }; + + let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext ); + + // Rewrite the input parameters. + input.sig.decl.inputs = parse_quote! { + &self, at: &#block_id, #context_arg, params: Option<( #( #param_types ),* )>, params_encoded: Vec + }; + + input.sig.ident = generate_method_runtime_api_impl_name(&input.sig.ident); + let ret_type = return_type_extract_type(&input.sig.decl.output); + + // Generate the correct return type. + input.sig.decl.output = parse_quote!( + -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>> + ); - fold::fold_fn_decl(self, input) - } + // Generate the new method implementation that calls into the runtime. + parse_quote!( + { + // Get the error to the user (if we have one). + #( #error )* - fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod { - { - let mut generated_name_counter = 0; - let arg_names = input.sig.decl.inputs.iter_mut().filter_map(|i| match i { - FnArg::Captured(ref mut arg) => Some(&mut arg.pat), - _ => None, - }).map(|p| { - *p = generate_unique_pattern(p.clone(), &mut generated_name_counter); - p - }); - let name = prefix_function_with_trait(self.impl_trait_ident, &input.sig.ident); - - // Generate the new method implementation that calls into the runime. - input.block = parse_quote!( { self.call_api_at(at, #name, &( #( #arg_names ),* )) } ); - } + self.call_api_at( + at, + #fn_name, + params_encoded, + params.map(|p| { + #runtime_mod_path #native_call_generator_ident :: + <#runtime, #node_block #(, #trait_generic_arguments )*> ( + #( #param_tuple_access ),* + ) + }), + context, + ) + } + ) + }; - fold::fold_impl_item_method(self, input) + let mut input = fold::fold_impl_item_method(self, input); + // We need to set the block, after we modified the rest of the ast, otherwise we would + // modify our generated block as well. + input.block = block; + input } fn fold_item_impl(&mut self, mut input: ItemImpl) -> ItemImpl { - // Implement the trait for the `RuntimeApi` - input.self_ty = Box::new(parse_quote!( RuntimeApi )); + // Implement the trait for the `RuntimeApiImpl` + input.self_ty = Box::new(parse_quote!( RuntimeApiImpl )); + + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let block = self.node_block; + input.generics.params.push( + parse_quote!( RuntimeApiImplCall: #crate_::runtime_api::CallRuntimeAt<#block> + 'static ) + ); - // The implementation for the `RuntimeApi` is only required when compiling with the feature - // `std` or `test`. + // The implementation for the `RuntimeApiImpl` is only required when compiling with + // the feature `std` or `test`. input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] )); fold::fold_item_impl(self, input) @@ -517,26 +535,37 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result let mut result = Vec::with_capacity(impls.len()); for impl_ in impls { - let impl_trait = extract_impl_trait(&impl_)?; - let impl_trait_ident = &impl_trait + let impl_trait_path = extract_impl_trait(&impl_)?; + let impl_trait = &impl_trait_path .segments .last() - .ok_or_else(|| Error::new(impl_trait.span(), "Empty trait path not possible!"))? - .value() - .ident; - let runtime_block = extract_runtime_block_ident(impl_trait)?; + .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? + .into_value(); + let impl_trait_ident = &impl_trait.ident; + let runtime_block = extract_runtime_block_ident(impl_trait_path)?; let (node_block, node_block_id) = generate_node_block_and_block_id_ty(&impl_.self_ty); + let runtime_type = &impl_.self_ty; + let mut runtime_mod_path = extend_with_runtime_decl_path(impl_trait_path.clone()); + // remove the trait to get just the module path + runtime_mod_path.segments.pop(); + + let trait_generic_arguments = match impl_trait.arguments { + PathArguments::Parenthesized(_) | PathArguments::None => vec![], + PathArguments::AngleBracketed(ref b) => b.args.iter().cloned().collect(), + }; let mut visitor = ApiRuntimeImplToApiRuntimeApiImpl { runtime_block, node_block: &node_block, node_block_id: &node_block_id, impl_trait_ident: &impl_trait_ident, + runtime_mod_path: &runtime_mod_path, + runtime_type: &*runtime_type, + trait_generic_arguments: &trait_generic_arguments, }; result.push(visitor.fold_item_impl(impl_.clone())); } - Ok(quote!( #( #result )* )) } @@ -586,13 +615,14 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { // Parse all impl blocks let RuntimeApiImpls { impls: api_impls } = parse_macro_input!(input as RuntimeApiImpls); + let dispatch_impl = unwrap_or_error(generate_dispatch_function(&api_impls)); - let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls)); - let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); - let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls)); let api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&api_impls)); - let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls)); + let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls)); + let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); let runtime_api_versions = unwrap_or_error(generate_runtime_api_versions(&api_impls)); + let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls)); + let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls)); quote!( #hidden_includes diff --git a/core/sr-api-macros/src/lib.rs b/core/sr-api-macros/src/lib.rs index 3dfc26c442a14094f8035f908689d740834a4ce3..72e143eb1a0088a2e16dcae9ae955b6c4a3faf43 100644 --- a/core/sr-api-macros/src/lib.rs +++ b/core/sr-api-macros/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,12 +16,8 @@ //! Macros for declaring and implementing runtime apis. -#![recursion_limit = "256"] +#![recursion_limit = "512"] extern crate proc_macro; -extern crate proc_macro2; -extern crate quote; -extern crate syn; -extern crate blake2_rfc; use proc_macro::TokenStream; @@ -50,13 +46,13 @@ mod compile_fail_tests; /// /// ```rust /// #[macro_use] -/// extern crate substrate_client; +/// extern crate client; /// extern crate sr_version as version; /// /// use version::create_runtime_str; -/// # extern crate substrate_test_client as test_client; -/// # extern crate sr_primitives as runtime_primitives; -/// # extern crate substrate_primitives as primitives; +/// # extern crate test_client; +/// # extern crate runtime_primitives; +/// # extern crate substrate_primitives; /// # /// # use runtime_primitives::traits::GetNodeBlockType; /// # use test_client::runtime::Block; @@ -132,7 +128,7 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// /// ```rust /// #[macro_use] -/// extern crate substrate_client; +/// extern crate client; /// /// decl_runtime_apis! { /// /// Declare the api trait. @@ -159,11 +155,15 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// /// To support versioning of the traits, the macro supports the attribute `#[api_version(1)]`. /// The attribute supports any `u32` as version. By default, each trait is at version `1`, if no -/// version is provided. +/// version is provided. We also support changing the signature of a method. This signature +/// change is highlighted with the `#[changed_in(2)]` attribute above a method. A method that is +/// tagged with this attribute is callable by the name `METHOD_before_version_VERSION`. This +/// method will only support calling into wasm, trying to call into native will fail (change the +/// spec version!). Such a method also does not need to be implemented in the runtime. /// /// ```rust /// #[macro_use] -/// extern crate substrate_client; +/// extern crate client; /// /// decl_runtime_apis! { /// /// Declare the api trait. @@ -171,8 +171,13 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// pub trait Balance { /// /// Get the balance. /// fn get_balance() -> u64; -/// /// Set the balance. +/// /// Set balance. /// fn set_balance(val: u64); +/// /// Set balance, old version. +/// /// +/// /// Is callable by `set_balance_before_version_2`. +/// #[changed_in(2)] +/// fn set_balance(val: u8); /// /// In version 2, we added this new function. /// fn increase_balance(val: u64); /// } diff --git a/core/sr-api-macros/src/utils.rs b/core/sr-api-macros/src/utils.rs index 4c80adf16b4d2b9e58a492d84df0009a29835ff8..e593e41ebedd4519f4bc2773d20bcd34df8a914b 100644 --- a/core/sr-api-macros/src/utils.rs +++ b/core/sr-api-macros/src/utils.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,9 +15,10 @@ // along with Substrate. If not, see . use proc_macro2::{TokenStream, Span}; -use syn::{Result, Ident, FnDecl, parse_quote, Type, FnArg}; +use syn::{Result, Ident, FnDecl, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error}; use quote::quote; use std::env; +use proc_macro_crate::crate_name; /// Unwrap the given result, if it is an error, `compile_error!` will be generated. pub fn unwrap_or_error(res: Result) -> TokenStream { @@ -34,16 +35,26 @@ pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { TokenStream::new() } else { let mod_name = generate_hidden_includes_mod_name(unique_id); - quote!( - #[doc(hidden)] - mod #mod_name { - pub extern crate substrate_client as sr_api_client; + match crate_name("substrate-client") { + Ok(client_name) => { + let client_name = Ident::new(&client_name, Span::call_site()); + quote!( + #[doc(hidden)] + mod #mod_name { + pub extern crate #client_name as sr_api_client; + } + ) + }, + Err(e) => { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + quote!( #err ) } - ) + } + }.into() } -/// Generates the access to the `subtrate_client` crate. +/// Generates the access to the `substrate_client` crate. pub fn generate_crate_access(unique_id: &'static str) -> TokenStream { if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { quote!( crate ) @@ -58,40 +69,92 @@ pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident { Ident::new(&format!("runtime_decl_for_{}", trait_.to_string()), Span::call_site()) } +/// Generates a name for a method that needs to be implemented in the runtime for the client side. +pub fn generate_method_runtime_api_impl_name(method: &Ident) -> Ident { + Ident::new(&format!("{}_runtime_api_impl", method.to_string()), Span::call_site()) +} + +/// Get the type of a `syn::ReturnType`. +pub fn return_type_extract_type(rt: &syn::ReturnType) -> Type { + match rt { + syn::ReturnType::Default => parse_quote!( () ), + syn::ReturnType::Type(_, ref ty) => *ty.clone(), + } +} + /// Fold the given `FnDecl` to make it usable on the client side. pub fn fold_fn_decl_for_client_side( mut input: FnDecl, block_id: &TokenStream, crate_: &TokenStream ) -> FnDecl { - // Add `&` to all parameter types. - input.inputs - .iter_mut() - .filter_map(|i| match i { - FnArg::Captured(ref mut arg) => Some(&mut arg.ty), - _ => None, - }) - .filter_map(|i| match i { - Type::Reference(_) => None, - r => Some(r), - }) - .for_each(|i| *i = parse_quote!( &#i )); - // Add `&self, at:& BlockId` as parameters to each function at the beginning. input.inputs.insert(0, parse_quote!( at: &#block_id )); input.inputs.insert(0, parse_quote!( &self )); // Wrap the output in a `Result` input.output = { - let generate_result = |ty: &Type| { - parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> ) - }; - - match &input.output { - syn::ReturnType::Default => generate_result(&parse_quote!( () )), - syn::ReturnType::Type(_, ref ty) => generate_result(&ty), - } + let ty = return_type_extract_type(&input.output); + parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> ) }; input } + +/// Generate an unique pattern based on the given counter, if the given pattern is a `_`. +pub fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat { + match pat { + Pat::Wild(_) => { + let generated_name = Ident::new( + &format!("runtime_api_generated_name_{}", counter), + pat.span() + ); + *counter += 1; + + parse_quote!( #generated_name ) + }, + _ => pat, + } +} + +/// Extracts the name, the type and `&` or ``(if it is a reference or not) +/// for each parameter in the given function declaration. +pub fn extract_parameter_names_types_and_borrows(fn_decl: &FnDecl) + -> Result> +{ + let mut result = Vec::new(); + let mut generated_pattern_counter = 0; + for input in fn_decl.inputs.iter() { + match input { + FnArg::Captured(arg) => { + let (ty, borrow) = match &arg.ty { + Type::Reference(t) => { + let ty = &t.elem; + (parse_quote!( #ty ), quote!( & )) + }, + t => { (t.clone(), quote!()) }, + }; + + let name = + generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter); + result.push((name, ty, borrow)); + }, + _ => { + return Err( + Error::new( + input.span(), + "Only function arguments with the following \ + pattern are accepted: `name: type`!" + ) + ) + } + } + } + + Ok(result) +} + +/// Generates the name for the native call generator function. +pub fn generate_native_call_generator_fn_name(fn_name: &Ident) -> Ident { + Ident::new(&format!("{}_native_call_generator", fn_name.to_string()), Span::call_site()) +} diff --git a/core/sr-api-macros/tests/decl_and_impl.rs b/core/sr-api-macros/tests/decl_and_impl.rs index 47822e538beb3b1b9f325dfcf32b0b74ae7abaf9..c7226065591edc8fef6b41c66bb4497cf2eea6be 100644 --- a/core/sr-api-macros/tests/decl_and_impl.rs +++ b/core/sr-api-macros/tests/decl_and_impl.rs @@ -1,14 +1,23 @@ -#[macro_use] -extern crate substrate_client; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_primitives as primitives; -extern crate substrate_test_client as test_client; +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. -use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT}; +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT, AuthorityIdFor}; use runtime_primitives::generic::BlockId; -use primitives::AuthorityId; -use substrate_client::runtime_api::{self, RuntimeApiInfo}; -use substrate_client::error::Result; +use client::runtime_api::{self, RuntimeApiInfo}; +use client::{error::Result, decl_runtime_apis, impl_runtime_apis}; use test_client::runtime::Block; /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` @@ -29,6 +38,8 @@ decl_runtime_apis! { #[api_version(2)] pub trait ApiWithCustomVersion { fn same_name(); + #[changed_in(2)] + fn same_name() -> String; } } @@ -57,23 +68,32 @@ impl_runtime_apis! { fn version() -> runtime_api::RuntimeVersion { unimplemented!() } - fn authorities() -> Vec { + fn authorities() -> Vec> { unimplemented!() } fn execute_block(_: Block) { unimplemented!() } - fn initialise_block(_: ::Header) { + fn initialise_block(_: &::Header) { unimplemented!() } } } +type TestClient = client::Client; + #[test] fn test_client_side_function_signature() { - let _test: fn(&RuntimeApi, &BlockId, &u64) -> Result<()> = RuntimeApi::test; - let _something_with_block: fn(&RuntimeApi, &BlockId, &Block) -> Result = - RuntimeApi::something_with_block; + let _test: fn(&RuntimeApiImpl, &BlockId, u64) -> Result<()> = + RuntimeApiImpl::::test; + let _something_with_block: + fn(&RuntimeApiImpl, &BlockId, Block) -> Result = + RuntimeApiImpl::::something_with_block; + + #[allow(deprecated)] + let _same_name_before_version_2: + fn(&RuntimeApiImpl, &BlockId) -> Result = + RuntimeApiImpl::::same_name_before_version_2; } #[test] diff --git a/core/sr-api-macros/tests/runtime_calls.rs b/core/sr-api-macros/tests/runtime_calls.rs new file mode 100644 index 0000000000000000000000000000000000000000..92e7a389246a01d1e050daacac06f4285a8d5d8f --- /dev/null +++ b/core/sr-api-macros/tests/runtime_calls.rs @@ -0,0 +1,108 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use test_client::runtime::{TestAPI, DecodeFails}; +use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; +use state_machine::ExecutionStrategy; + +fn calling_function_with_strat(strat: ExecutionStrategy) { + let client = test_client::new_with_execution_strategy(strat); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + assert_eq!(runtime_api.benchmark_add_one(&block_id, &1).unwrap(), 2); +} + +#[test] +fn calling_native_runtime_function() { + calling_function_with_strat(ExecutionStrategy::NativeWhenPossible); +} + +#[test] +fn calling_wasm_runtime_function() { + calling_function_with_strat(ExecutionStrategy::AlwaysWasm); +} + +#[test] +#[should_panic(expected = "Could not convert parameter `param` between node and runtime!")] +fn calling_native_runtime_function_with_non_decodable_parameter() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeWhenPossible); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + runtime_api.fail_convert_parameter(&block_id, DecodeFails::new()).unwrap(); +} + +#[test] +#[should_panic(expected = "Could not convert return value from runtime to node!")] +fn calling_native_runtime_function_with_non_decodable_return_value() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeWhenPossible); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + runtime_api.fail_convert_return_value(&block_id).unwrap(); +} + +#[test] +fn calling_native_runtime_signature_changed_function() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeWhenPossible); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + assert_eq!(runtime_api.function_signature_changed(&block_id).unwrap(), 1); +} + +#[test] +fn calling_wasm_runtime_signature_changed_old_function() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + #[allow(deprecated)] + let res = runtime_api.function_signature_changed_before_version_2(&block_id).unwrap(); + assert_eq!(&res, &[1, 2]); +} + +#[test] +fn calling_with_both_strategy_and_fail_on_wasm_should_return_error() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::Both); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + assert!(runtime_api.fail_on_wasm(&block_id).is_err()); +} + +#[test] +fn calling_with_both_strategy_and_fail_on_native_should_work() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::Both); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1); +} + + +#[test] +fn calling_with_native_else_wasm_and_faild_on_wasm_should_work() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeElseWasm); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + assert_eq!(runtime_api.fail_on_wasm(&block_id).unwrap(), 1); +} + +#[test] +fn calling_with_native_else_wasm_and_fail_on_native_should_work() { + let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeElseWasm); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1); +} diff --git a/core/sr-io/Cargo.toml b/core/sr-io/Cargo.toml index 39e62e7a2035d4e9041849b81b500a81ac4d4293..811c17e0b1477cbe4a5b2efd69620e3ee979596f 100644 --- a/core/sr-io/Cargo.toml +++ b/core/sr-io/Cargo.toml @@ -3,31 +3,36 @@ name = "sr-io" version = "0.1.0" authors = ["Parity Technologies "] build = "build.rs" +edition = "2018" [build-dependencies] rustc_version = "0.2" [dependencies] -sr-std = { path = "../sr-std", default-features = false } -substrate-primitives = { path = "../primitives", default-features = false } -parity-codec = { version = "2.1", default-features = false } -hash-db = { git = "https://github.com/paritytech/trie", default-features = false } - +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false } +hash-db = { version = "0.11", default-features = false } +libsecp256k1 = { version = "0.2.1", optional = true } +tiny-keccak = { version = "1.4.2", optional = true } environmental = { version = "~1.0", optional = true } substrate-state-machine = { path = "../state-machine", optional = true } -substrate-trie = { path = "../trie", optional = true } +trie = { package = "substrate-trie", path = "../trie", optional = true } [features] default = ["std"] std = [ - "substrate-primitives/std", + "primitives/std", "parity-codec/std", - "sr-std/std", + "rstd/std", "hash-db/std", "environmental", "substrate-state-machine", - "substrate-trie" + "trie", + "libsecp256k1", + "tiny-keccak" ] nightly = [] strict = [] +wasm-nice-panic-message = [] \ No newline at end of file diff --git a/core/sr-io/build.rs b/core/sr-io/build.rs index 35eb154f3a69ac3fd6e7ae7fc8c02342be7c0a60..62ddacbbf4f993f3d58b036391e0ae0e94dc1b5a 100644 --- a/core/sr-io/build.rs +++ b/core/sr-io/build.rs @@ -1,6 +1,5 @@ //! Set a nightly feature -extern crate rustc_version; use rustc_version::{version, version_meta, Channel}; fn main() { diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs index 3394265a847b55f8f6cd3fab0889f54b859197b0..6a00e6ca2734d1b73fe7ec6e7063b9bf2e03b3f2 100644 --- a/core/sr-io/src/lib.rs +++ b/core/sr-io/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,6 +25,12 @@ #![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] +pub enum EcdsaVerifyError { + BadRS, + BadV, + BadSignature, +} + #[cfg(feature = "std")] include!("../with_std.rs"); diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index a608a632fe136aeb2520d2361628d548bfcb9462..d67d4ec53c50f826d9031bb6993a7df484cd8be6 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,33 +14,33 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -#[macro_use] -extern crate environmental; - -#[cfg_attr(test, macro_use)] -extern crate substrate_primitives as primitives; - -extern crate substrate_state_machine; -extern crate substrate_trie as trie; -extern crate hash_db; - #[doc(hidden)] -pub extern crate parity_codec as codec; +pub use parity_codec as codec; // re-export hashing functions. -pub use primitives::{blake2_256, twox_128, twox_256, ed25519}; - -pub use primitives::{Blake2Hasher}; +pub use primitives::{ + blake2_256, twox_128, twox_256, ed25519, Blake2Hasher, sr25519, + Pair +}; +pub use tiny_keccak::keccak256 as keccak_256; // Switch to this after PoC-3 // pub use primitives::BlakeHasher; -pub use substrate_state_machine::{Externalities, TestExternalities}; -use primitives::hexdisplay::HexDisplay; -use primitives::H256; +pub use substrate_state_machine::{Externalities, BasicExternalities, TestExternalities}; + +use environmental::{environmental, thread_local_impl}; +use primitives::{hexdisplay::HexDisplay, H256}; use hash_db::Hasher; -// TODO: use the real error, not NoError. +#[cfg(feature = "std")] +use std::collections::HashMap; environmental!(ext: trait Externalities); +/// A set of key value pairs for storage. +pub type StorageOverlay = HashMap, Vec>; + +/// A set of key value pairs for children storage; +pub type ChildrenStorageOverlay = HashMap, StorageOverlay>; + /// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Option> { ext::with(|ext| ext.storage(key).map(|s| s.to_vec())) @@ -164,6 +164,7 @@ pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option

(input: &[&[u8]]) -> H::Out where H: Hasher, @@ -197,7 +198,24 @@ where /// Verify a ed25519 signature. pub fn ed25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { - ed25519::verify(sig, msg, pubkey) + ed25519::Pair::verify_weak(sig, msg, pubkey) +} + +/// Verify an sr25519 signature. +pub fn sr25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { + sr25519::Pair::verify_weak(sig, msg, pubkey) +} + +/// Verify and recover a SECP256k1 ECDSA signature. +/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. +/// - returns `Err` if the signature is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix). +pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { + let rs = secp256k1::Signature::parse_slice(&sig[0..64]).map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8).map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v).map_err(|_| EcdsaVerifyError::BadSignature)?; + let mut res = [0u8; 64]; + res.copy_from_slice(&pubkey.serialize()[1..65]); + Ok(res) } /// Execute the given closure with global function available whose functionality routes into the @@ -207,6 +225,17 @@ pub fn with_externalities R>(ext: &mut Externalities R>(storage: &mut StorageOverlay, f: F) -> R { + let mut alt_storage = Default::default(); + rstd::mem::swap(&mut alt_storage, storage); + let mut ext: BasicExternalities = alt_storage.into(); + let r = ext::using(&mut ext, f); + *storage = ext.into(); + r +} + /// Trait for things which can be printed. pub trait Printable { fn print(self); @@ -238,10 +267,11 @@ pub fn print(value: T) { #[cfg(test)] mod std_tests { use super::*; + use primitives::map; #[test] fn storage_works() { - let mut t = TestExternalities::::default(); + let mut t = BasicExternalities::default(); assert!(with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); set_storage(b"hello", b"world"); @@ -251,7 +281,7 @@ mod std_tests { true })); - t = TestExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()]); + t = BasicExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()]); assert!(!with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); @@ -262,7 +292,7 @@ mod std_tests { #[test] fn read_storage_works() { - let mut t = TestExternalities::::new(map![ + let mut t = BasicExternalities::new(map![ b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() ]); @@ -278,7 +308,7 @@ mod std_tests { #[test] fn clear_prefix_works() { - let mut t = TestExternalities::::new(map![ + let mut t = BasicExternalities::new(map![ b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index d0f112b76e8bf98df87bba1082eeaf565d6a05cb..e3cf8318a68913ab45d0c01838dddd4d334dea13 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,30 +14,33 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . - -extern crate substrate_primitives as primitives; -extern crate hash_db; - #[doc(hidden)] -pub extern crate sr_std as rstd; - +pub use parity_codec as codec; #[doc(hidden)] -pub extern crate parity_codec as codec; +pub use rstd; +pub use rstd::{mem, slice}; -use core::intrinsics; -use rstd::vec::Vec; +use core::{intrinsics, panic::PanicInfo}; +use rstd::{vec::Vec, cell::Cell}; use hash_db::Hasher; use primitives::Blake2Hasher; -pub use rstd::{mem, slice}; #[panic_handler] #[no_mangle] -pub fn panic(info: &::core::panic::PanicInfo) -> ! { +pub fn panic(info: &PanicInfo) -> ! { unsafe { - if let Some(loc) = info.location() { - ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); - ext_print_num(loc.line() as u64); - ext_print_num(loc.column() as u64); + #[cfg(feature = "wasm-nice-panic-message")] + { + let message = rstd::alloc::format!("{}", info); + extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); + } + #[cfg(not(feature = "wasm-nice-panic-message"))] + { + if let Some(loc) = info.location() { + extern_functions_host_impl::ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); + extern_functions_host_impl::ext_print_num(loc.line() as u64); + extern_functions_host_impl::ext_print_num(loc.column() as u64); + } } intrinsics::abort() } @@ -48,37 +51,238 @@ pub extern fn oom(_: ::core::alloc::Layout) -> ! { static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; unsafe { - ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); + extern_functions_host_impl::ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); intrinsics::abort(); } } -extern "C" { - fn ext_free(addr: *mut u8); +/// The state of an exchangeable function. +#[derive(Clone, Copy)] +enum ExchangeableFunctionState { + Original, + Replaced, +} + +/// A function which implementation can be exchanged. +/// +/// Internally this works by swapping function pointers. +pub struct ExchangeableFunction(Cell<(T, ExchangeableFunctionState)>); + +impl ExchangeableFunction { + /// Create a new instance of `ExchangeableFunction`. + pub const fn new(impl_: T) -> Self { + Self(Cell::new((impl_, ExchangeableFunctionState::Original))) + } +} + +impl ExchangeableFunction { + /// Replace the implementation with `new_impl`. + /// + /// # Panics + /// + /// Panics when trying to replace an already replaced implementation. + /// + /// # Returns + /// + /// Returns the original implementation wrapped in [`RestoreImplementation`]. + pub fn replace_implementation(&'static self, new_impl: T) -> RestoreImplementation { + if let ExchangeableFunctionState::Replaced = self.0.get().1 { + panic!("Trying to replace an already replaced implementation!") + } + + let old = self.0.replace((new_impl, ExchangeableFunctionState::Replaced)); + + RestoreImplementation(self, Some(old.0)) + } + + /// Restore the original implementation. + fn restore_orig_implementation(&self, orig: T) { + self.0.set((orig, ExchangeableFunctionState::Original)); + } + + /// Returns the internal function pointer. + pub fn get(&self) -> T { + self.0.get().0 + } +} + +// WASM does not support threads, so this is safe; qed. +unsafe impl Sync for ExchangeableFunction {} + +/// Restores a function implementation on drop. +/// +/// Stores a static reference to the function object and the original implementation. +pub struct RestoreImplementation(&'static ExchangeableFunction, Option); + +impl Drop for RestoreImplementation { + fn drop(&mut self) { + self.0.restore_orig_implementation(self.1.take().expect("Value is only taken on drop; qed")); + } +} + +/// Declare extern functions +macro_rules! extern_functions { + ( + $( + $( #[$attr:meta] )* + fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* ) $( -> $ret:ty )?; + )* + ) => { + $( + $( #[$attr] )* + #[allow(non_upper_case_globals)] + pub static $name: ExchangeableFunction $ret )?> = + ExchangeableFunction::new(extern_functions_host_impl::$name); + )* + + /// The exchangeable extern functions host implementations. + mod extern_functions_host_impl { + $( + pub unsafe fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )? { + implementation::$name ( $( $arg ),* ) + } + )* + + mod implementation { + extern "C" { + $( + pub fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )?; + )* + } + } + } + }; +} + +/// Host functions, provided by the executor. +/// A WebAssembly runtime module would "import" these to access the execution environment +/// (most importantly, storage) or perform heavy hash calculations. +/// See also "ext_" functions in sr-sandbox and sr-std +extern_functions! { + /// Host functions for printing, useful for debugging. fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32); fn ext_print_hex(data: *const u8, len: u32); fn ext_print_num(value: u64); + + /// Set value for key in storage. fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); - fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + /// Remove key and value from storage. fn ext_clear_storage(key_data: *const u8, key_len: u32); - fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32); + /// Checks if the given key exists in the storage. + /// + /// # Returns + /// + /// - `1` if the value exists. + /// - `0` if the value does not exists. fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32; - fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32; + /// Remove storage entries which key starts with given prefix. fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32); - fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32); + /// Gets the value of the given key from storage. + /// + /// The host allocates the memory for storing the value. + /// + /// # Returns + /// + /// - `0` if no value exists to the given key. `written_out` is set to `u32::max_value()`. + /// + /// - Otherwise, pointer to the value in memory. `written_out` contains the length of the value. fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; - fn ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; + /// Gets the value of the given key from storage. + /// + /// The value is written into `value` starting at `value_offset`. + /// + /// If the value length is greater than `value_len - value_offset`, the value is written partially. + /// + /// # Returns + /// + /// - `u32::max_value()` if the value does not exists. + /// + /// - Otherwise, the number of bytes written for value. fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; - fn ext_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; + /// Gets the trie root of the storage. fn ext_storage_root(result: *mut u8); - fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8; + /// Get the change trie root of the current storage overlay at a block with given parent. + /// + /// # Returns + /// + /// - `1` if the change trie root was found. + /// - `0` if the change trie root was not found. fn ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, parent_num: u64, result: *mut u8) -> u32; - fn ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8); + + /// A child storage function. + /// + /// See [`ext_set_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + /// A child storage function. + /// + /// See [`ext_clear_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32); + /// A child storage function. + /// + /// See [`ext_exists_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32; + /// A child storage function. + /// + /// See [`ext_kill_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32); + /// A child storage function. + /// + /// See [`ext_get_allocated_storage`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_get_allocated_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + written_out: *mut u32 + ) -> *mut u8; + /// A child storage function. + /// + /// See [`ext_get_storage_into`] for details. + /// + /// A child storage is used e.g. by a contract. + fn ext_get_child_storage_into( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + value_data: *mut u8, + value_len: u32, + value_offset: u32 + ) -> u32; + /// Commits all changes and calculates the child-storage root. + /// + /// A child storage is used e.g. by a contract. + /// + /// # Returns + /// + /// - The pointer to the result vector and `written_out` contains its length. + fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8; + + /// The current relay chain identifier. fn ext_chain_id() -> u64; + + /// Hash calculation and verification + fn ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8); fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); fn ext_twox_128(data: *const u8, len: u32, out: *mut u8); fn ext_twox_256(data: *const u8, len: u32, out: *mut u8); + fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); + /// Note: ext_ed25519_verify returns 0 if the signature is correct, nonzero otherwise. fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; + /// Note: ext_sr25519_verify returns 0 if the signature is correct, nonzero otherwise. + fn ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; + /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. + fn ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32; } /// Ensures we use the right crypto when calling into native @@ -93,7 +297,7 @@ impl ExternTrieCrypto for Blake2Hasher { let values = values.iter().fold(Vec::new(), |mut acc, sl| { acc.extend_from_slice(sl); acc }); let mut result: [u8; 32] = Default::default(); unsafe { - ext_blake2_256_enumerated_trie_root( + ext_blake2_256_enumerated_trie_root.get()( values.as_ptr(), lengths.as_ptr(), lengths.len() as u32, @@ -108,13 +312,14 @@ impl ExternTrieCrypto for Blake2Hasher { pub fn storage(key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length); + let ptr = ext_get_allocated_storage.get()(key.as_ptr(), key.len() as u32, &mut length); if length == u32::max_value() { None } else { - let ret = slice::from_raw_parts(ptr, length as usize).to_vec(); - ext_free(ptr); - Some(ret) + // Invariants required by Vec::from_raw_parts are not formally fulfilled. + // We don't allocate via String/Vec, but use a custom allocator instead. + // See #300 for more details. + Some(>::from_raw_parts(ptr, length as usize, length as usize)) } } } @@ -123,13 +328,20 @@ pub fn storage(key: &[u8]) -> Option> { pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_child_storage(storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, &mut length); + let ptr = ext_get_allocated_child_storage.get()( + storage_key.as_ptr(), + storage_key.len() as u32, + key.as_ptr(), + key.len() as u32, + &mut length + ); if length == u32::max_value() { None } else { - let ret = slice::from_raw_parts(ptr, length as usize).to_vec(); - ext_free(ptr); - Some(ret) + // Invariants required by Vec::from_raw_parts are not formally fulfilled. + // We don't allocate via String/Vec, but use a custom allocator instead. + // See #300 for more details. + Some(>::from_raw_parts(ptr, length as usize, length as usize)) } } } @@ -137,7 +349,7 @@ pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { /// Set the storage of some particular key to Some value. pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { - ext_set_storage( + ext_set_storage.get()( key.as_ptr(), key.len() as u32, value.as_ptr(), value.len() as u32 ); @@ -147,7 +359,7 @@ pub fn set_storage(key: &[u8], value: &[u8]) { /// Set the child storage of some particular key to Some value. pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { unsafe { - ext_set_child_storage( + ext_set_child_storage.get()( storage_key.as_ptr(), key.len() as u32, key.as_ptr(), key.len() as u32, value.as_ptr(), value.len() as u32 @@ -158,7 +370,7 @@ pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { /// Clear the storage of some particular key. pub fn clear_storage(key: &[u8]) { unsafe { - ext_clear_storage( + ext_clear_storage.get()( key.as_ptr(), key.len() as u32 ); } @@ -167,7 +379,7 @@ pub fn clear_storage(key: &[u8]) { /// Clear the storage of some particular key. pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) { unsafe { - ext_clear_child_storage( + ext_clear_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32 ); @@ -177,7 +389,7 @@ pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) { /// Determine whether a particular key exists in storage. pub fn exists_storage(key: &[u8]) -> bool { unsafe { - ext_exists_storage( + ext_exists_storage.get()( key.as_ptr(), key.len() as u32 ) != 0 } @@ -186,7 +398,7 @@ pub fn exists_storage(key: &[u8]) -> bool { /// Determine whether a particular key exists in storage. pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { unsafe { - ext_exists_child_storage( + ext_exists_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32 ) != 0 @@ -196,7 +408,7 @@ pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { /// Clear the storage entries key of which starts with the given prefix. pub fn clear_prefix(prefix: &[u8]) { unsafe { - ext_clear_prefix( + ext_clear_prefix.get()( prefix.as_ptr(), prefix.len() as u32 ); @@ -206,7 +418,7 @@ pub fn clear_prefix(prefix: &[u8]) { /// Clear an entire child storage. pub fn kill_child_storage(storage_key: &[u8]) { unsafe { - ext_kill_child_storage( + ext_kill_child_storage.get()( storage_key.as_ptr(), storage_key.len() as u32 ); @@ -217,10 +429,12 @@ pub fn kill_child_storage(storage_key: &[u8]) { /// the number of bytes that the key in storage was beyond the offset. pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { unsafe { - match ext_get_storage_into( - key.as_ptr(), key.len() as u32, - value_out.as_mut_ptr(), value_out.len() as u32, - value_offset as u32 + match ext_get_storage_into.get()( + key.as_ptr(), + key.len() as u32, + value_out.as_mut_ptr(), + value_out.len() as u32, + value_offset as u32, ) { none if none == u32::max_value() => None, length => Some(length as usize), @@ -232,7 +446,7 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Op /// the number of bytes that the key in storage was beyond the offset. pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { unsafe { - match ext_get_child_storage_into( + match ext_get_child_storage_into.get()( storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, value_out.as_mut_ptr(), value_out.len() as u32, @@ -248,7 +462,7 @@ pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], pub fn storage_root() -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_storage_root(result.as_mut_ptr()); + ext_storage_root.get()(result.as_mut_ptr()); } result } @@ -257,13 +471,14 @@ pub fn storage_root() -> [u8; 32] { pub fn child_storage_root(storage_key: &[u8]) -> Option> { let mut length: u32 = 0; unsafe { - let ptr = ext_child_storage_root(storage_key.as_ptr(), storage_key.len() as u32, &mut length); + let ptr = ext_child_storage_root.get()(storage_key.as_ptr(), storage_key.len() as u32, &mut length); if length == u32::max_value() { None } else { - let ret = slice::from_raw_parts(ptr, length as usize).to_vec(); - ext_free(ptr); - Some(ret) + // Invariants required by Vec::from_raw_parts are not formally fulfilled. + // We don't allocate via String/Vec, but use a custom allocator instead. + // See #300 for more details. + Some(>::from_raw_parts(ptr, length as usize, length as usize)) } } } @@ -272,7 +487,7 @@ pub fn child_storage_root(storage_key: &[u8]) -> Option> { pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option<[u8; 32]> { let mut result: [u8; 32] = Default::default(); let is_set = unsafe { - ext_storage_changes_root(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr()) + ext_storage_changes_root.get()(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr()) }; if is_set != 0 { @@ -295,8 +510,6 @@ pub fn trie_root< B: AsRef<[u8]>, >(_input: I) -> [u8; 32] { unimplemented!() - // TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing - // implemneted natively and compile the trie logic as wasm). } /// A trie root formed from the enumerated items. @@ -306,14 +519,12 @@ pub fn ordered_trie_root< A: AsRef<[u8]> >(_input: I) -> [u8; 32] { unimplemented!() - // TODO Maybe implement (though probably easier/cleaner to have blake2 be the only thing - // implemneted natively and compile the trie logic as wasm). } /// The current relay chain identifier. pub fn chain_id() -> u64 { unsafe { - ext_chain_id() + ext_chain_id.get()() } } @@ -321,7 +532,16 @@ pub fn chain_id() -> u64 { pub fn blake2_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_blake2_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + } + result +} + +/// Conduct a 256-bit Keccak hash. +pub fn keccak_256(data: &[u8]) -> [u8; 32] { + let mut result: [u8; 32] = Default::default(); + unsafe { + ext_keccak_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -330,7 +550,7 @@ pub fn blake2_256(data: &[u8]) -> [u8; 32] { pub fn twox_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); unsafe { - ext_twox_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_twox_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -339,7 +559,7 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { pub fn twox_128(data: &[u8]) -> [u8; 16] { let mut result: [u8; 16] = Default::default(); unsafe { - ext_twox_128(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + ext_twox_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } result } @@ -347,7 +567,30 @@ pub fn twox_128(data: &[u8]) -> [u8; 16] { /// Verify a ed25519 signature. pub fn ed25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { unsafe { - ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 + ext_ed25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 + } +} + +/// Verify a sr25519 signature. +pub fn sr25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { + unsafe { + ext_sr25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0 + } +} + +/// Verify and recover a SECP256k1 ECDSA signature. +/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. +/// - returns `None` if the signature is bad, the 64-byte pubkey (doesn't include the 0x04 prefix). +pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { + let mut pubkey = [0u8; 64]; + match unsafe { + ext_secp256k1_ecdsa_recover.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) + } { + 0 => Ok(pubkey), + 1 => Err(EcdsaVerifyError::BadRS), + 2 => Err(EcdsaVerifyError::BadV), + 3 => Err(EcdsaVerifyError::BadSignature), + _ => unreachable!("`ext_secp256k1_ecdsa_recover` only returns 0, 1, 2 or 3; qed"), } } @@ -359,7 +602,7 @@ pub trait Printable { impl<'a> Printable for &'a [u8] { fn print(self) { unsafe { - ext_print_hex(self.as_ptr(), self.len() as u32); + ext_print_hex.get()(self.as_ptr(), self.len() as u32); } } } @@ -367,14 +610,14 @@ impl<'a> Printable for &'a [u8] { impl<'a> Printable for &'a str { fn print(self) { unsafe { - ext_print_utf8(self.as_ptr() as *const u8, self.len() as u32); + ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32); } } } impl Printable for u64 { fn print(self) { - unsafe { ext_print_num(self); } + unsafe { ext_print_num.get()(self); } } } diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index 9dc3988681af32ed781f9b4c231136d5a743118e..565b9fb1e400aa1c533a2175e1bfe87a5fbd4ac7 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -2,18 +2,18 @@ name = "sr-primitives" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] num-traits = { version = "0.2", default-features = false } integer-sqrt = { version = "0.1.2" } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../primitives", default-features = false } -sr-std = { path = "../sr-std", default-features = false } -sr-io = { path = "../sr-io", default-features = false } -log = {version = "0.4", optional = true } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } +log = { version = "0.4", optional = true } [dev-dependencies] serde_json = "1.0" @@ -25,10 +25,8 @@ std = [ "serde", "serde_derive", "log", - "sr-std/std", - "sr-io/std", + "rstd/std", + "runtime_io/std", "parity-codec/std", "substrate-primitives/std", ] -api-for-runtime = [] - diff --git a/core/sr-primitives/src/generic/block.rs b/core/sr-primitives/src/generic/block.rs index df9f656513edb5bf67b6040ca62af5dfec47d1fc..5fb83a2a4f766251ca7908196148e89ade4a075e 100644 --- a/core/sr-primitives/src/generic/block.rs +++ b/core/sr-primitives/src/generic/block.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,13 +20,12 @@ use std::fmt; #[cfg(feature = "std")] -use serde::{Deserialize, Deserializer}; -#[cfg(feature = "std")] -use codec::Decode; +use serde_derive::Serialize; + use rstd::prelude::*; -use codec::Codec; -use traits::{self, Member, Block as BlockT, Header as HeaderT, MaybeSerialize}; -use ::Justification; +use crate::codec::{Codec, Encode, Decode}; +use crate::traits::{self, Member, Block as BlockT, Header as HeaderT, MaybeSerialize}; +use crate::Justification; /// Something to identify a block. #[derive(PartialEq, Eq, Clone)] @@ -73,17 +72,6 @@ pub struct Block { pub extrinsics: Vec, } -// TODO: Remove Deserialize for Block once RPC no longer needs it #1098 -#[cfg(feature = "std")] -impl<'a, Header: 'a, Extrinsic: 'a + MaybeSerialize> Deserialize<'a> for Block where - Block: Decode, -{ - fn deserialize>(de: D) -> Result { - let r = >::deserialize(de)?; - Decode::decode(&mut &r[..]).ok_or(::serde::de::Error::custom("Invalid value passed into decode")) - } -} - impl traits::Block for Block where Header: HeaderT, @@ -118,16 +106,3 @@ pub struct SignedBlock { /// Block justification. pub justification: Option, } - -// TODO: Remove Deserialize for SignedBlock once RPC no longer needs it #1098 -#[cfg(feature = "std")] -impl<'a, Block: BlockT,> Deserialize<'a> for SignedBlock where - Block::Header: 'a, - Block::Extrinsic: 'a + Codec + MaybeSerialize, - SignedBlock: Decode, -{ - fn deserialize>(de: D) -> Result { - let r = >::deserialize(de)?; - Decode::decode(&mut &r[..]).ok_or(::serde::de::Error::custom("Invalid value passed into decode")) - } -} diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 749577cdd6c3b91110447a5872dd81a5cd4fdd71..c0548c26e598ea51ce692fe4402e2fdb74cb86da 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ //! Generic implementation of an extrinsic that has passed the verification //! stage. -use traits::{self, Member, SimpleArithmetic, MaybeDisplay}; +use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay}; /// Definition of something that the external world might want to say; its /// existence implies that it has been checked and is good, particularly with diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs index ea2dafb758411edc7188df95cd745aa5dcf69632..710bcc77457ce3ac86262f7e3753f184874ad913 100644 --- a/core/sr-primitives/src/generic/digest.rs +++ b/core/sr-primitives/src/generic/digest.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,16 +16,19 @@ //! Generic implementation of a digest. -use rstd::prelude::*; +#[cfg(feature = "std")] +use serde_derive::Serialize; -use codec::{Decode, Encode, Codec, Input}; -use traits::{self, Member, DigestItem as DigestItemT, MaybeSerializeDebug}; +use rstd::prelude::*; -use substrate_primitives::hash::H512 as Signature; +use crate::codec::{Decode, Encode, Codec, Input}; +use crate::traits::{self, Member, DigestItem as DigestItemT, MaybeHash}; +/// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] pub struct Digest { + /// A list of logs in the digest. pub logs: Vec, } @@ -57,8 +60,8 @@ impl traits::Digest for Digest where /// Digest item that is able to encode/decode 'system' digest items and /// provide opaque access to other items. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -pub enum DigestItem { +#[cfg_attr(feature = "std", derive(Debug))] +pub enum DigestItem { /// System digest item announcing that authorities set has been changed /// in the block. Contains the new set of authorities. AuthoritiesChange(Vec), @@ -67,23 +70,32 @@ pub enum DigestItem { /// trie creation. ChangesTrieRoot(Hash), /// Put a Seal on it - Seal(u64, Signature), + Seal(u64, SealSignature), /// Any 'non-system' digest item, opaque to the native code. Other(Vec), } +#[cfg(feature = "std")] +impl ::serde::Serialize for DigestItem { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + self.using_encoded(|bytes| { + ::substrate_primitives::bytes::serialize(bytes, seq) + }) + } +} + /// A 'referencing view' for digest item. Does not own its contents. Used by /// final runtime implementations for encoding/decoding its log items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a> { +pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// Reference to `DigestItem::AuthoritiesChange`. AuthoritiesChange(&'a [AuthorityId]), /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), /// A sealed signature for testing - Seal(&'a u64, &'a Signature), + Seal(&'a u64, &'a SealSignature), /// Any 'non-system' digest item, opaque to the native code. /// Reference to `DigestItem::Other`. Other(&'a Vec), @@ -102,7 +114,7 @@ enum DigestItemType { Seal, } -impl DigestItem { +impl DigestItem { /// Returns Some if `self` is a `DigestItem::Other`. pub fn as_other(&self) -> Option<&Vec> { match *self { @@ -112,7 +124,7 @@ impl DigestItem { } /// Returns a 'referencing view' for this digest item. - fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId> { + fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { match *self { DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), @@ -123,9 +135,10 @@ impl DigestItem { } impl< - Hash: Codec + Member + MaybeSerializeDebug, - AuthorityId: Codec + Member + MaybeSerializeDebug -> traits::DigestItem for DigestItem { + Hash: Codec + Member, + AuthorityId: Codec + Member + MaybeHash, + SealSignature: Codec + Member, +> traits::DigestItem for DigestItem { type Hash = Hash; type AuthorityId = AuthorityId; @@ -133,18 +146,18 @@ impl< self.dref().as_authorities_change() } - fn as_changes_trie_root(&self) -> Option<&Hash> { + fn as_changes_trie_root(&self) -> Option<&Self::Hash> { self.dref().as_changes_trie_root() } } -impl Encode for DigestItem { +impl Encode for DigestItem { fn encode(&self) -> Vec { self.dref().encode() } } -impl Decode for DigestItem { +impl Decode for DigestItem { fn decode(input: &mut I) -> Option { let item_type: DigestItemType = Decode::decode(input)?; match item_type { @@ -155,7 +168,7 @@ impl Decode for DigestItem Decode::decode(input)?, )), DigestItemType::Seal => { - let vals: (u64, Signature) = Decode::decode(input)?; + let vals: (u64, SealSignature) = Decode::decode(input)?; Some(DigestItem::Seal(vals.0, vals.1)) }, DigestItemType::Other => Some(DigestItem::Other( @@ -165,7 +178,8 @@ impl Decode for DigestItem } } -impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Hash, AuthorityId> { +impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec + Member> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { + /// Cast this digest item into `AuthoritiesChange`. pub fn as_authorities_change(&self) -> Option<&'a [AuthorityId]> { match *self { DigestItemRef::AuthoritiesChange(ref authorities) => Some(authorities), @@ -173,6 +187,7 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Ha } } + /// Cast this digest item into `ChangesTrieRoot`. pub fn as_changes_trie_root(&self) -> Option<&'a Hash> { match *self { DigestItemRef::ChangesTrieRoot(ref changes_trie_root) => Some(changes_trie_root), @@ -181,7 +196,7 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Ha } } -impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId> { +impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> { fn encode(&self) -> Vec { let mut v = Vec::new(); @@ -207,3 +222,26 @@ impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, A v } } + +#[cfg(test)] +mod tests { + use super::*; + use substrate_primitives::hash::H512 as Signature; + + #[test] + fn should_serialize_digest() { + let digest = Digest { + logs: vec![ + DigestItem::AuthoritiesChange(vec![1]), + DigestItem::ChangesTrieRoot(4), + DigestItem::Seal(1, Signature::from_low_u64_be(15)), + DigestItem::Other(vec![1, 2, 3]), + ], + }; + + assert_eq!( + ::serde_json::to_string(&digest).unwrap(), + r#"{"logs":["0x010401000000","0x0204000000","0x0301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","0x000c010203"]}"# + ); + } +} diff --git a/core/sr-primitives/src/generic/era.rs b/core/sr-primitives/src/generic/era.rs index bccee778be203986d9072125b0a860e837380572..037013b4feaa951512eaec7fceb185c3f7d77d75 100644 --- a/core/sr-primitives/src/generic/era.rs +++ b/core/sr-primitives/src/generic/era.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,10 @@ //! Generic implementation of an unchecked (pre-verification) extrinsic. -use codec::{Decode, Encode, Input, Output}; +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; + +use crate::codec::{Decode, Encode, Input, Output}; pub type Period = u64; pub type Phase = u64; diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index ec70d5d66ba5f26bd2b5e0ed635fd428b03ac778..60ccd93b3ded8ccebeb7f8770d1ca649c4ff5354 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,22 +17,22 @@ //! Generic implementation of a block header. #[cfg(feature = "std")] -use serde::{Deserialize, Deserializer}; - -use codec::{Decode, Encode, Codec, Input, Output, HasCompact}; -use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, +use serde_derive::Serialize; +use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef}; +use crate::traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, DigestItem as DigestItemT, MaybeSerializeDebug, MaybeSerializeDebugButNotDeserialize}; -use generic::Digest; +use crate::generic::Digest; /// Abstraction over a block header for a substrate chain. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header { +pub struct Header, Hash: HashT, DigestItem> { /// The parent hash. pub parent_hash: ::Output, /// The block number. + #[cfg_attr(feature = "std", serde(serialize_with = "serialize_number"))] pub number: Number, /// The state trie merkle root pub state_root: ::Output, @@ -42,19 +42,17 @@ pub struct Header { pub digest: Digest, } -// TODO: Remove Deserialize for Header once RPC no longer needs it #1098 #[cfg(feature = "std")] -impl<'a, Number: 'a, Hash: 'a + HashT, DigestItem: 'a> Deserialize<'a> for Header where - Header: Decode, -{ - fn deserialize>(de: D) -> Result { - let r = >::deserialize(de)?; - Decode::decode(&mut &r[..]).ok_or(::serde::de::Error::custom("Invalid value passed into decode")) - } +pub fn serialize_number>(val: &T, s: S) -> Result where S: ::serde::Serializer { + use substrate_primitives::uint::U256; + let v: u128 = (*val).into(); + let lower = U256::from(v as u64); + let upper = U256::from(v.rotate_left(64) as u64) << 64; + ::serde::Serialize::serialize(&(upper + lower), s) } impl Decode for Header where - Number: HasCompact, + Number: HasCompact + Copy + Into, Hash: HashT, Hash::Output: Decode, DigestItem: DigestItemT + Decode, @@ -71,14 +69,14 @@ impl Decode for Header where } impl Encode for Header where - Number: HasCompact + Copy, + Number: HasCompact + Copy + Into, Hash: HashT, Hash::Output: Encode, DigestItem: DigestItemT + Encode, { fn encode_to(&self, dest: &mut T) { dest.push(&self.parent_hash); - dest.push(&<::Type>::from(self.number)); + dest.push(&<<::Type as EncodeAsRef<_>>::RefType>::from(&self.number)); dest.push(&self.state_root); dest.push(&self.extrinsics_root); dest.push(&self.digest); @@ -86,7 +84,7 @@ impl Encode for Header where } impl traits::Header for Header where - Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec, + Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into, Hash: HashT, DigestItem: DigestItemT + Codec, Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec, @@ -130,7 +128,7 @@ impl traits::Header for Header Header where - Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec, + Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into, Hash: HashT, DigestItem: DigestItemT + Codec, Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, @@ -141,3 +139,26 @@ impl Header where Hash::hash_of(self) } } + +#[cfg(all(test, feature = "std"))] +mod tests { + use super::*; + + #[test] + fn should_serialize_numbers() { + fn serialize(num: u128) -> String { + let mut v = vec![]; + { + let mut ser = ::serde_json::Serializer::new(::std::io::Cursor::new(&mut v)); + serialize_number(&num, &mut ser).unwrap(); + } + String::from_utf8(v).unwrap() + } + + assert_eq!(serialize(0), "\"0x0\"".to_owned()); + assert_eq!(serialize(1), "\"0x1\"".to_owned()); + assert_eq!(serialize(u64::max_value() as u128), "\"0xffffffffffffffff\"".to_owned()); + assert_eq!(serialize(u64::max_value() as u128 + 1), "\"0x10000000000000000\"".to_owned()); + } + +} diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs index 69b317f6eeade4a83ea682b85773b80f0eef8d31..47ce3cb25184f7b2c44d4cb1d4837247d981027f 100644 --- a/core/sr-primitives/src/generic/mod.rs +++ b/core/sr-primitives/src/generic/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ mod unchecked_extrinsic; mod unchecked_mortal_extrinsic; +mod unchecked_mortal_compact_extrinsic; mod era; mod checked_extrinsic; mod header; @@ -30,13 +31,14 @@ mod tests; pub use self::unchecked_extrinsic::UncheckedExtrinsic; pub use self::unchecked_mortal_extrinsic::UncheckedMortalExtrinsic; +pub use self::unchecked_mortal_compact_extrinsic::UncheckedMortalCompactExtrinsic; pub use self::era::Era; pub use self::checked_extrinsic::CheckedExtrinsic; pub use self::header::Header; pub use self::block::{Block, SignedBlock, BlockId}; pub use self::digest::{Digest, DigestItem, DigestItemRef}; -use codec::Encode; +use crate::codec::Encode; use rstd::prelude::*; fn encode_with_vec_prefix)>(encoder: F) -> Vec { diff --git a/core/sr-primitives/src/generic/tests.rs b/core/sr-primitives/src/generic/tests.rs index 76896106170ea5eb5a88f65a22473f00778023ed..91fc8f3faf90486b67174463e2993a73caa10ac9 100644 --- a/core/sr-primitives/src/generic/tests.rs +++ b/core/sr-primitives/src/generic/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,13 +16,13 @@ //! Tests for the generic implementations of Extrinsic/Header/Block. -use codec::{Decode, Encode}; -use substrate_primitives::H256; +use crate::codec::{Decode, Encode}; +use substrate_primitives::{H256, H512}; use super::DigestItem; #[test] fn system_digest_item_encoding() { - let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); + let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::AuthoritiesChange @@ -35,13 +35,13 @@ fn system_digest_item_encoding() { 30, 0, 0, 0, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } #[test] fn non_system_digest_item_encoding() { - let item = DigestItem::Other::(vec![10, 20, 30]); + let item = DigestItem::Other::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::Other @@ -52,6 +52,6 @@ fn non_system_digest_item_encoding() { 10, 20, 30, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); -} \ No newline at end of file +} diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index d6442cbc0b38760a1fa3efdf7ffa96a41e6c49e5..d6e0d60e2c218c255e5da9af987ce08e46b0d1e3 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,8 +20,8 @@ use std::fmt; use rstd::prelude::*; -use codec::{Decode, Encode, Codec, Input, HasCompact}; -use traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup, Extrinsic}; +use crate::codec::{Decode, Encode, Codec, Input, HasCompact}; +use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup, Extrinsic}; use super::CheckedExtrinsic; #[derive(PartialEq, Eq, Clone, Encode, Decode)] @@ -92,8 +92,8 @@ where Some(SignatureContent{signed, signature, index}) => { let payload = (index, self.function); let signed = context.lookup(signed)?; - if !::verify_encoded_lazy(&signature, &payload, &signed) { - return Err("bad signature in extrinsic") + if !crate::verify_encoded_lazy(&signature, &payload, &signed) { + return Err(crate::BAD_SIGNATURE) } CheckedExtrinsic { signed: Some((signed, payload.0)), @@ -152,11 +152,10 @@ impl for UncheckedExtrinsic { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + self.using_encoded(|bytes| ::substrate_primitives::bytes::serialize(bytes, seq)) } } -/// TODO: use derive when possible. #[cfg(feature = "std")] impl fmt::Debug for UncheckedExtrinsic @@ -173,7 +172,7 @@ where #[cfg(test)] mod test { - use codec::{Decode, Encode}; + use crate::codec::{Decode, Encode}; use super::UncheckedExtrinsic; #[test] @@ -186,4 +185,14 @@ mod test { let as_vec: Vec = Decode::decode(&mut encoded.as_slice()).unwrap(); assert_eq!(as_vec.encode(), encoded); } + + + #[test] + #[cfg(feature = "std")] + fn serialization_of_unchecked_extrinsics() { + type Extrinsic = UncheckedExtrinsic; + let ex = Extrinsic::new_unsigned(42); + + assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x14002a000000\""); + } } diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs new file mode 100644 index 0000000000000000000000000000000000000000..243747092c49ca8100b6aa9a8490cb72c3cf775d --- /dev/null +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -0,0 +1,305 @@ +// 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 . + +//! Generic implementation of an unchecked (pre-verification) extrinsic. + +#[cfg(feature = "std")] +use std::fmt; + +use rstd::prelude::*; +use runtime_io::blake2_256; +use crate::codec::{Decode, Encode, Input, Compact}; +use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, + Checkable, Extrinsic}; +use super::{CheckedExtrinsic, Era}; + +const TRANSACTION_VERSION: u8 = 1; + +/// A extrinsic right from the external world. This is unchecked and so +/// can contain a signature. +#[derive(PartialEq, Eq, Clone)] +pub struct UncheckedMortalCompactExtrinsic { + /// The signature, address, number of extrinsics have come before from + /// the same signer and an era describing the longevity of this transaction, + /// if this is a signed extrinsic. + pub signature: Option<(Address, Signature, Compact, Era)>, + /// The function that should be called. + pub function: Call, +} + +impl UncheckedMortalCompactExtrinsic { + /// New instance of a signed extrinsic aka "transaction". + pub fn new_signed(index: Index, function: Call, signed: Address, signature: Signature, era: Era) -> Self { + UncheckedMortalCompactExtrinsic { + signature: Some((signed, signature, index.into(), era)), + function, + } + } + + /// New instance of an unsigned extrinsic aka "inherent". + pub fn new_unsigned(function: Call) -> Self { + UncheckedMortalCompactExtrinsic { + signature: None, + function, + } + } +} + +impl Extrinsic for UncheckedMortalCompactExtrinsic { + fn is_signed(&self) -> Option { + Some(self.signature.is_some()) + } +} + +impl Checkable + for UncheckedMortalCompactExtrinsic +where + Address: Member + MaybeDisplay, + Index: Member + MaybeDisplay + SimpleArithmetic, + Compact: Encode, + Call: Encode + Member, + Signature: Member + traits::Verify, + AccountId: Member + MaybeDisplay, + BlockNumber: SimpleArithmetic, + Hash: Encode, + Context: Lookup + + CurrentHeight + + BlockNumberToHash, +{ + type Checked = CheckedExtrinsic; + + fn check(self, context: &Context) -> Result { + Ok(match self.signature { + Some((signed, signature, index, era)) => { + let h = context.block_number_to_hash(BlockNumber::sa(era.birth(context.current_height().as_()))) + .ok_or("transaction birth block ancient")?; + let signed = context.lookup(signed)?; + let raw_payload = (index, self.function, era, h); + if !raw_payload.using_encoded(|payload| { + if payload.len() > 256 { + signature.verify(&blake2_256(payload)[..], &signed) + } else { + signature.verify(payload, &signed) + } + }) { + return Err(crate::BAD_SIGNATURE) + } + CheckedExtrinsic { + signed: Some((signed, (raw_payload.0).0)), + function: raw_payload.1, + } + } + None => CheckedExtrinsic { + signed: None, + function: self.function, + }, + }) + } +} + +impl Decode + for UncheckedMortalCompactExtrinsic +where + Address: Decode, + Signature: Decode, + Compact: Decode, + Call: Decode, +{ + fn decode(input: &mut I) -> Option { + // This is a little more complicated than usual since the binary format must be compatible + // with substrate's generic `Vec` type. Basically this just means accepting that there + // will be a prefix of vector length (we don't need + // to use this). + let _length_do_not_remove_me_see_above: Vec<()> = Decode::decode(input)?; + + let version = input.read_byte()?; + + let is_signed = version & 0b1000_0000 != 0; + let version = version & 0b0111_1111; + if version != TRANSACTION_VERSION { + return None + } + + Some(UncheckedMortalCompactExtrinsic { + signature: if is_signed { Some(Decode::decode(input)?) } else { None }, + function: Decode::decode(input)?, + }) + } +} + +impl Encode + for UncheckedMortalCompactExtrinsic +where + Address: Encode, + Signature: Encode, + Compact: Encode, + Call: Encode, +{ + fn encode(&self) -> Vec { + super::encode_with_vec_prefix::(|v| { + // 1 byte version id. + match self.signature.as_ref() { + Some(s) => { + v.push(TRANSACTION_VERSION | 0b1000_0000); + s.encode_to(v); + } + None => { + v.push(TRANSACTION_VERSION & 0b0111_1111); + } + } + self.function.encode_to(v); + }) + } +} + +#[cfg(feature = "std")] +impl serde::Serialize + for UncheckedMortalCompactExtrinsic + where Compact: Encode +{ + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +#[cfg(feature = "std")] +impl fmt::Debug for UncheckedMortalCompactExtrinsic where + Address: fmt::Debug, + Index: fmt::Debug, + Call: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedMortalCompactExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use runtime_io::blake2_256; + use crate::codec::{Encode, Decode}; + use serde_derive::{Serialize, Deserialize}; + + struct TestContext; + impl Lookup for TestContext { + type Source = u64; + type Target = u64; + fn lookup(&self, s: u64) -> Result { Ok(s) } + } + impl CurrentHeight for TestContext { + type BlockNumber = u64; + fn current_height(&self) -> u64 { 42 } + } + impl BlockNumberToHash for TestContext { + type BlockNumber = u64; + type Hash = u64; + fn block_number_to_hash(&self, n: u64) -> Option { Some(n) } + } + + #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)] + struct TestSig(u64, Vec); + impl traits::Verify for TestSig { + type Signer = u64; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + *signer == self.0 && msg.get() == &self.1[..] + } + } + + const DUMMY_ACCOUNTID: u64 = 0; + + type Ex = UncheckedMortalCompactExtrinsic, TestSig>; + type CEx = CheckedExtrinsic>; + + #[test] + fn unsigned_codec_should_work() { + let ux = Ex::new_unsigned(vec![0u8;0]); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn signed_codec_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal()); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn large_signed_codec_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8; 257], Era::immortal(), 0u64).using_encoded(blake2_256)[..].to_owned()), Era::immortal()); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn unsigned_check_should_work() { + let ux = Ex::new_unsigned(vec![0u8;0]); + assert!(!ux.is_signed().unwrap_or(false)); + assert!(>::check(ux, &TestContext).is_ok()); + } + + #[test] + fn badly_signed_check_should_fail() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + } + + #[test] + fn immortal_signed_check_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal()); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); + } + + #[test] + fn mortal_signed_check_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42)); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); + } + + #[test] + fn later_mortal_signed_check_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (Compact::from(DUMMY_ACCOUNTID), vec![0u8;0], Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11)); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); + } + + #[test] + fn too_late_mortal_signed_check_should_fail() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + } + + #[test] + fn too_early_mortal_signed_check_should_fail() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); + assert!(ux.is_signed().unwrap_or(false)); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + } + + #[test] + fn encoding_matches_vec() { + let ex = Ex::new_unsigned(vec![0u8;0]); + let encoded = ex.encode(); + let decoded = Ex::decode(&mut encoded.as_slice()).unwrap(); + assert_eq!(decoded, ex); + let as_vec: Vec = Decode::decode(&mut encoded.as_slice()).unwrap(); + assert_eq!(as_vec.encode(), encoded); + } +} diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index e15a37c3bf01d852ad363908677d1d1cc4199bfd..93eeb55884479281a77071953602553e576e012f 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,8 +20,9 @@ use std::fmt; use rstd::prelude::*; -use codec::{Decode, Encode, Input}; -use traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, +use runtime_io::blake2_256; +use crate::codec::{Decode, Encode, Input}; +use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, Checkable, Extrinsic}; use super::{CheckedExtrinsic, Era}; @@ -84,14 +85,21 @@ where Some((signed, signature, index, era)) => { let h = context.block_number_to_hash(BlockNumber::sa(era.birth(context.current_height().as_()))) .ok_or("transaction birth block ancient")?; - let payload = (index, self.function, era, h); let signed = context.lookup(signed)?; - if !::verify_encoded_lazy(&signature, &payload, &signed) { - return Err("bad signature in extrinsic") + let raw_payload = (index, self.function, era, h); + + if !raw_payload.using_encoded(|payload| { + if payload.len() > 256 { + signature.verify(&blake2_256(payload)[..], &signed) + } else { + signature.verify(payload, &signed) + } + }) { + return Err(crate::BAD_SIGNATURE) } CheckedExtrinsic { - signed: Some((signed, payload.0)), - function: payload.1, + signed: Some((signed, raw_payload.0)), + function: raw_payload.1, } } None => CheckedExtrinsic { @@ -166,7 +174,6 @@ impl serde::Ser } } -/// TODO: use derive when possible. #[cfg(feature = "std")] impl fmt::Debug for UncheckedMortalExtrinsic where Address: fmt::Debug, @@ -181,6 +188,9 @@ impl fmt::Debug for UncheckedMortalExtrinsic; - type CEx = CheckedExtrinsic; + type Ex = UncheckedMortalExtrinsic, TestSig>; + type CEx = CheckedExtrinsic>; #[test] fn unsigned_codec_should_work() { - let ux = Ex::new_unsigned(DUMMY_FUNCTION); + let ux = Ex::new_unsigned(vec![0u8;0]); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); } #[test] fn signed_codec_should_work() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal()); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal()); + let encoded = ux.encode(); + assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); + } + + #[test] + fn large_signed_codec_should_work() { + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8; 257], Era::immortal(), 0u64).using_encoded(blake2_256)[..].to_owned()), Era::immortal()); let encoded = ux.encode(); assert_eq!(Ex::decode(&mut &encoded[..]), Some(ux)); } #[test] fn unsigned_check_should_work() { - let ux = Ex::new_unsigned(DUMMY_FUNCTION); + let ux = Ex::new_unsigned(vec![0u8;0]); assert!(!ux.is_signed().unwrap_or(false)); assert!(>::check(ux, &TestContext).is_ok()); } #[test] fn badly_signed_check_should_fail() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); } #[test] fn immortal_signed_check_should_work() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal()); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::immortal(), 0u64).encode()), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); } #[test] fn mortal_signed_check_should_work() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42)); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); } #[test] fn later_mortal_signed_check_should_work() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11)); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); + assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: vec![0u8;0] })); } #[test] fn too_late_mortal_signed_check_should_fail() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); } #[test] fn too_early_mortal_signed_check_should_fail() { - let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); + let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); + assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); } #[test] fn encoding_matches_vec() { - let ex = Ex::new_unsigned(DUMMY_FUNCTION); + let ex = Ex::new_unsigned(vec![0u8;0]); let encoded = ex.encode(); let decoded = Ex::decode(&mut encoded.as_slice()).unwrap(); assert_eq!(decoded, ex); diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index dfd34ed01f3bd26e14bfeb3141194ffe21d79dd1..6df4bdeb787e38a330da29db79f394c138b9601e 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,41 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code -//! and depositing logs. +//! Runtime Modules shared primitive types. -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -extern crate serde; +#![warn(missing_docs)] -#[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; +#![cfg_attr(not(feature = "std"), no_std)] +#[doc(hidden)] +pub use parity_codec as codec; #[cfg(feature = "std")] -#[macro_use] -extern crate log; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate num_traits; -extern crate integer_sqrt; -extern crate sr_std as rstd; -extern crate sr_io as runtime_io; #[doc(hidden)] -pub extern crate parity_codec as codec; -extern crate substrate_primitives; - -#[cfg(test)] -extern crate serde_json; +pub use serde_derive; #[cfg(feature = "std")] -use std::collections::HashMap; +pub use runtime_io::{StorageOverlay, ChildrenStorageOverlay}; use rstd::prelude::*; -use substrate_primitives::hash::{H256, H512}; +use substrate_primitives::{ed25519, sr25519, hash::{H256, H512}}; +use codec::{Encode, Decode}; #[cfg(feature = "std")] use substrate_primitives::hexdisplay::ascii_format; @@ -60,6 +43,20 @@ pub mod traits; pub mod generic; pub mod transaction_validity; +/// A message indicating an invalid signature in extrinsic. +pub const BAD_SIGNATURE: &str = "bad signature in extrinsic"; + +/// Full block error message. +/// +/// This allows modules to indicate that given transaction is potentially valid +/// in the future, but can't be executed in the current state. +/// Note this error should be returned early in the execution to prevent DoS, +/// cause the fees are not being paid if this error is returned. +/// +/// Example: block gas limit is reached (the transaction can be retried in the next block though). +pub const BLOCK_FULL: &str = "block size limit is reached"; + +/// Justification type. pub type Justification = Vec; use traits::{Verify, Lazy}; @@ -67,6 +64,7 @@ use traits::{Verify, Lazy}; /// A String that is a `&'static str` on `no_std` and a `Cow<'static, str>` on `std`. #[cfg(feature = "std")] pub type RuntimeString = ::std::borrow::Cow<'static, str>; +/// A String that is a `&'static str` on `no_std` and a `Cow<'static, str>` on `std`. #[cfg(not(feature = "std"))] pub type RuntimeString = &'static str; @@ -76,6 +74,8 @@ pub type RuntimeString = &'static str; macro_rules! create_runtime_str { ( $y:expr ) => {{ ::std::borrow::Cow::Borrowed($y) }} } + +/// Create a const [RuntimeString]. #[cfg(not(feature = "std"))] #[macro_export] macro_rules! create_runtime_str { @@ -84,31 +84,40 @@ macro_rules! create_runtime_str { #[cfg(feature = "std")] pub use serde::{Serialize, de::DeserializeOwned}; - -/// A set of key value pairs for storage. -#[cfg(feature = "std")] -pub type StorageMap = HashMap, Vec>; - -/// A set of key value pairs for children storage; #[cfg(feature = "std")] -pub type ChildrenStorageMap = HashMap, StorageMap>; +pub use serde_derive::{Serialize, Deserialize}; /// Complex storage builder stuff. #[cfg(feature = "std")] -pub trait BuildStorage { +pub trait BuildStorage: Sized { + /// Hash given slice. + /// + /// Default to xx128 hashing. fn hash(data: &[u8]) -> [u8; 16] { let r = runtime_io::twox_128(data); - trace!(target: "build_storage", "{} <= {}", substrate_primitives::hexdisplay::HexDisplay::from(&r), ascii_format(data)); + log::trace!(target: "build_storage", "{} <= {}", substrate_primitives::hexdisplay::HexDisplay::from(&r), ascii_format(data)); r } - fn build_storage(self) -> Result<(StorageMap, ChildrenStorageMap), String>; + /// Build the storage out of this builder. + fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { + let mut storage = Default::default(); + let mut child_storage = Default::default(); + self.assimilate_storage(&mut storage, &mut child_storage)?; + Ok((storage, child_storage)) + } + /// Assimilate the storage for this module into pre-existing overlays. + fn assimilate_storage(self, storage: &mut StorageOverlay, child_storage: &mut ChildrenStorageOverlay) -> Result<(), String>; } #[cfg(feature = "std")] -impl BuildStorage for StorageMap { - fn build_storage(self) -> Result<(StorageMap, ChildrenStorageMap), String> { +impl BuildStorage for StorageOverlay { + fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { Ok((self, Default::default())) } + fn assimilate_storage(self, storage: &mut StorageOverlay, _child_storage: &mut ChildrenStorageOverlay) -> Result<(), String> { + storage.extend(self); + Ok(()) + } } /// Permill is parts-per-million (i.e. after multiplying by this, divide by 1000000). @@ -116,21 +125,28 @@ impl BuildStorage for StorageMap { #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] pub struct Permill(u32); -// TODO: impl Mul for N where N: As impl Permill { - pub fn times + ::rstd::ops::Mul + ::rstd::ops::Div>(self, b: N) -> N { - // TODO: handle overflows - b * >::sa(self.0 as u64) / >::sa(1000000) - } - + /// Wraps the argument into `Permill` type. pub fn from_millionths(x: u32) -> Permill { Permill(x) } + /// Converts percents into `Permill`. pub fn from_percent(x: u32) -> Permill { Permill(x * 10_000) } + /// Converts a fraction into `Permill`. #[cfg(feature = "std")] pub fn from_fraction(x: f64) -> Permill { Permill((x * 1_000_000.0) as u32) } } +impl ::rstd::ops::Mul for Permill +where + N: traits::As +{ + type Output = N; + fn mul(self, b: N) -> Self::Output { + >::sa(b.as_().saturating_mul(self.0 as u64) / 1_000_000) + } +} + #[cfg(feature = "std")] impl From for Permill { fn from(x: f64) -> Permill { @@ -145,20 +161,29 @@ impl From for Permill { } } +impl codec::CompactAs for Permill { + type As = u32; + fn encode_as(&self) -> &u32 { + &self.0 + } + fn decode_from(x: u32) -> Permill { + Permill(x) + } +} + +impl From> for Permill { + fn from(x: codec::Compact) -> Permill { + x.0 + } +} + /// Perbill is parts-per-billion. It stores a value between 0 and 1 in fixed point and /// provides a means to multiply some other value by that. #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] pub struct Perbill(u32); -// TODO: impl Mul for N where N: As impl Perbill { - /// Attenuate `b` by self. - pub fn times + ::rstd::ops::Mul + ::rstd::ops::Div>(self, b: N) -> N { - // TODO: handle overflows - b * >::sa(self.0 as u64) / >::sa(1_000_000_000) - } - /// Nothing. pub fn zero() -> Perbill { Perbill(0) } @@ -186,6 +211,16 @@ impl Perbill { pub fn from_rational(n: f64, d: f64) -> Perbill { Perbill(((n / d).max(0.0).min(1.0) * 1_000_000_000.0) as u32) } } +impl ::rstd::ops::Mul for Perbill +where + N: traits::As +{ + type Output = N; + fn mul(self, b: N) -> Self::Output { + >::sa(b.as_().saturating_mul(self.0 as u64) / 1_000_000_000) + } +} + #[cfg(feature = "std")] impl From for Perbill { fn from(x: f64) -> Perbill { @@ -200,24 +235,178 @@ impl From for Perbill { } } -/// Ed25519 signature verify. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] +impl codec::CompactAs for Perbill { + type As = u32; + fn encode_as(&self) -> &u32 { + &self.0 + } + fn decode_from(x: u32) -> Perbill { + Perbill(x) + } +} + +impl From> for Perbill { + fn from(x: codec::Compact) -> Perbill { + x.0 + } +} + +/// Perquintill is parts-per-quintillion. It stores a value between 0 and 1 in fixed point and +/// provides a means to multiply some other value by that. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] +pub struct Perquintill(u64); + +const QUINTILLION: u64 = 1_000_000_000_000_000_000; + +impl Perquintill { + /// Nothing. + pub fn zero() -> Self { Self(0) } + + /// Everything. + pub fn one() -> Self { Self(QUINTILLION) } + + /// Construct new instance where `x` is in quintillionths. Value equivalent to `x / 1,000,000,000,000,000,000`. + pub fn from_quintillionths(x: u64) -> Self { Self(x.min(QUINTILLION)) } + + /// Construct new instance where `x` is in billionths. Value equivalent to `x / 1,000,000,000`. + pub fn from_billionths(x: u64) -> Self { Self(x.min(1_000_000_000) * 1_000_000_000 ) } + + /// Construct new instance where `x` is in millionths. Value equivalent to `x / 1,000,000`. + pub fn from_millionths(x: u64) -> Self { Self(x.min(1_000_000) * 1000_000_000_000) } + + /// Construct new instance where `x` is denominator and the nominator is 1. + pub fn from_xth(x: u64) -> Self { Self(QUINTILLION / x.min(QUINTILLION)) } + + #[cfg(feature = "std")] + /// Construct new instance whose value is equal to `x` (between 0 and 1). + pub fn from_fraction(x: f64) -> Self { Self((x.max(0.0).min(1.0) * QUINTILLION as f64) as u64) } +} + +impl ::rstd::ops::Deref for Perquintill { + type Target = u64; + + fn deref(&self) -> &u64 { + &self.0 + } +} + +impl ::rstd::ops::Mul for Perquintill +where + N: traits::As +{ + type Output = N; + fn mul(self, b: N) -> Self::Output { + >::sa(b.as_().saturating_mul(self.0) / QUINTILLION) + } +} + +#[cfg(feature = "std")] +impl From for Perquintill { + fn from(x: f64) -> Perquintill { + Perquintill::from_fraction(x) + } +} + +#[cfg(feature = "std")] +impl From for Perquintill { + fn from(x: f32) -> Perquintill { + Perquintill::from_fraction(x as f64) + } +} + +impl codec::CompactAs for Perquintill { + type As = u64; + fn encode_as(&self) -> &u64 { + &self.0 + } + fn decode_from(x: u64) -> Perquintill { + Perquintill(x) + } +} + +impl From> for Perquintill { + fn from(x: codec::Compact) -> Perquintill { + x.0 + } +} + +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum MultiSignature { + /// An Ed25519 signature. + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + Sr25519(sr25519::Signature), +} + +impl Default for MultiSignature { + fn default() -> Self { + MultiSignature::Ed25519(Default::default()) + } +} + +/// Public key for any known crypto algorithm. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Ed25519Signature(pub H512); +pub enum MultiSigner { + /// An Ed25519 identity. + Ed25519(ed25519::Public), + /// An Sr25519 identity. + Sr25519(sr25519::Public), +} -impl Verify for Ed25519Signature { - type Signer = H256; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - runtime_io::ed25519_verify((self.0).as_fixed_bytes(), msg.get(), &signer.as_bytes()) +impl Default for MultiSigner { + fn default() -> Self { + MultiSigner::Ed25519(Default::default()) } } -impl From for Ed25519Signature { - fn from(h: H512) -> Ed25519Signature { - Ed25519Signature(h) +impl Verify for MultiSignature { + type Signer = MultiSigner; + fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { + match (self, signer) { + (MultiSignature::Ed25519(ref sig), &MultiSigner::Ed25519(ref who)) => sig.verify(msg, who), + (MultiSignature::Sr25519(ref sig), &MultiSigner::Sr25519(ref who)) => sig.verify(msg, who), + _ => false, + } } } +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct AnySignature(H512); + +/// Public key for any known crypto algorithm. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Default, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct AnySigner(H256); + +impl Verify for AnySignature { + type Signer = AnySigner; + fn verify>(&self, mut msg: L, signer: &AnySigner) -> bool { + runtime_io::sr25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0.as_bytes()) || + runtime_io::ed25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0.as_bytes()) + } +} + +/// Context for executing a call into the runtime. +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[repr(u8)] +pub enum ExecutionContext { + /// Context for general importing (including own blocks). + Importing, + /// Context used when syncing the blockchain. + Syncing, + /// Context used for block construction. + BlockConstruction, + /// Context used for other calls. + Other, +} + #[derive(Eq, PartialEq, Clone, Copy, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[repr(u8)] @@ -248,6 +437,8 @@ pub enum ApplyError { Future = 2, /// Sending account had too low a balance. CantPay = 3, + /// Block is full, no more extrinsics can be applied. + FullBlock = 255, } impl codec::Encode for ApplyError { @@ -283,14 +474,22 @@ pub fn verify_encoded_lazy(sig: &V, item: &T, signe ) } +/// Helper macro for `impl_outer_config` #[macro_export] macro_rules! __impl_outer_config_types { + ( + $concrete:ident $config:ident $snake:ident < $ignore:ident, $instance:path > $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig<$concrete, $instance>; + $crate::__impl_outer_config_types! {$concrete $($rest)*} + }; ( $concrete:ident $config:ident $snake:ident < $ignore:ident > $( $rest:tt )* ) => { #[cfg(any(feature = "std", test))] pub type $config = $snake::GenesisConfig<$concrete>; - __impl_outer_config_types! {$concrete $($rest)*} + $crate::__impl_outer_config_types! {$concrete $($rest)*} }; ( $concrete:ident $config:ident $snake:ident $( $rest:tt )* @@ -302,17 +501,22 @@ macro_rules! __impl_outer_config_types { ($concrete:ident) => () } +/// Implement the output "meta" module configuration struct, +/// which is basically: +/// pub struct GenesisConfig { +/// rust_module_one: Option, +/// ... +/// } #[macro_export] -/// Implement the output "meta" module configuration struct. macro_rules! impl_outer_config { ( pub struct $main:ident for $concrete:ident { - $( $config:ident => $snake:ident $( < $generic:ident > )*, )* + $( $config:ident => $snake:ident $( < $generic:ident $(, $instance:path)? > )*, )* } ) => { - __impl_outer_config_types! { $concrete $( $config $snake $( < $generic > )* )* } + $crate::__impl_outer_config_types! { $concrete $( $config $snake $( < $generic $(, $instance)? > )* )* } #[cfg(any(feature = "std", test))] - #[derive(Serialize, Deserialize)] + #[derive($crate::serde_derive::Serialize, $crate::serde_derive::Deserialize)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct $main { @@ -322,19 +526,13 @@ macro_rules! impl_outer_config { } #[cfg(any(feature = "std", test))] impl $crate::BuildStorage for $main { - fn build_storage(self) -> ::std::result::Result<($crate::StorageMap, $crate::ChildrenStorageMap), String> { - let mut top = $crate::StorageMap::new(); - let mut children = $crate::ChildrenStorageMap::new(); + fn assimilate_storage(self, top: &mut $crate::StorageOverlay, children: &mut $crate::ChildrenStorageOverlay) -> ::std::result::Result<(), String> { $( if let Some(extra) = self.$snake { - let (other_top, other_children) = extra.build_storage()?; - top.extend(other_top); - for (other_child_key, other_child_map) in other_children { - children.entry(other_child_key).or_default().extend(other_child_map); - } + extra.assimilate_storage(top, children)?; } )* - Ok((top, children)) + Ok(()) } } } @@ -360,26 +558,26 @@ macro_rules! impl_outer_log { ( $(#[$attr:meta])* pub enum $name:ident ($internal:ident: DigestItem<$( $genarg:ty ),*>) for $trait:ident { - $( $module:ident( $( $sitem:ident ),* ) ),* + $( $module:ident $(<$instance:path>)? ( $( $sitem:ident ),* ) ),* } ) => { /// Wrapper for all possible log entries for the `$trait` runtime. Provides binary-compatible /// `Encode`/`Decode` implementations with the corresponding `generic::DigestItem`. #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, Serialize))] + #[cfg_attr(feature = "std", derive(Debug, $crate::serde_derive::Serialize))] $(#[$attr])* #[allow(non_camel_case_types)] pub struct $name($internal); /// All possible log entries for the `$trait` runtime. `Encode`/`Decode` implementations /// are auto-generated => it is not binary-compatible with `generic::DigestItem`. - #[derive(Clone, PartialEq, Eq, Encode, Decode)] - #[cfg_attr(feature = "std", derive(Debug, Serialize))] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] + #[cfg_attr(feature = "std", derive(Debug, $crate::serde_derive::Serialize))] $(#[$attr])* #[allow(non_camel_case_types)] pub enum InternalLog { $( - $module($module::Log<$trait>), + $module($module::Log<$trait $(, $instance)? >), )* } @@ -434,7 +632,7 @@ macro_rules! impl_outer_log { } impl $crate::codec::Decode for $name { - /// `generic::DigestItem` binray compatible decode. + /// `generic::DigestItem` binary compatible decode. fn decode(input: &mut I) -> Option { let gen: $crate::generic::DigestItem<$($genarg),*> = $crate::codec::Decode::decode(input)?; @@ -443,7 +641,7 @@ macro_rules! impl_outer_log { } impl $crate::codec::Encode for $name { - /// `generic::DigestItem` binray compatible encode. + /// `generic::DigestItem` binary compatible encode. fn encode(&self) -> Vec { match self.dref() { Some(dref) => dref.encode(), @@ -457,16 +655,16 @@ macro_rules! impl_outer_log { } $( - impl From<$module::Log<$trait>> for $name { + impl From<$module::Log<$trait $(, $instance)? >> for $name { /// Converts single module log item into `$name`. - fn from(x: $module::Log<$trait>) -> Self { + fn from(x: $module::Log<$trait $(, $instance)? >) -> Self { $name(x.into()) } } - impl From<$module::Log<$trait>> for InternalLog { + impl From<$module::Log<$trait $(, $instance)? >> for InternalLog { /// Converts single module log item into `$internal`. - fn from(x: $module::Log<$trait>) -> Self { + fn from(x: $module::Log<$trait $(, $instance)? >) -> Self { InternalLog::$module(x) } } @@ -474,62 +672,30 @@ macro_rules! impl_outer_log { }; } -//TODO: https://github.com/paritytech/substrate/issues/1022 -/// Basic Inherent data to include in a block; used by simple runtimes. -#[derive(Encode, Decode)] -pub struct BasicInherentData { - /// Current timestamp. - pub timestamp: u64, - /// Blank report. - pub consensus: (), - /// Aura expected slot. Can take any value during block construction. - pub aura_expected_slot: u64, -} - -impl BasicInherentData { - /// Create a new `BasicInherentData` instance. - pub fn new(timestamp: u64, expected_slot: u64) -> Self { - Self { - timestamp, - consensus: (), - aura_expected_slot: expected_slot, - } +/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized +/// correctly. +#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct OpaqueExtrinsic(pub Vec); + +#[cfg(feature = "std")] +impl ::serde::Serialize for OpaqueExtrinsic { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + codec::Encode::using_encoded(&self.0, |bytes| ::substrate_primitives::bytes::serialize(bytes, seq)) } } -//TODO: https://github.com/paritytech/substrate/issues/1022 -/// Error type used while checking inherents. -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Decode))] -pub enum CheckInherentError { - /// The inherents are generally valid but a delay until the given timestamp - /// is required. - ValidAtTimestamp(u64), - /// Some other error has occurred. - Other(RuntimeString), -} - -impl CheckInherentError { - /// Combine two results, taking the "worse" of the two. - pub fn combine_results Result<(), Self>>(this: Result<(), Self>, other: F) -> Result<(), Self> { - match this { - Ok(()) => other(), - Err(CheckInherentError::Other(s)) => Err(CheckInherentError::Other(s)), - Err(CheckInherentError::ValidAtTimestamp(x)) => match other() { - Ok(()) => Err(CheckInherentError::ValidAtTimestamp(x)), - Err(CheckInherentError::ValidAtTimestamp(y)) - => Err(CheckInherentError::ValidAtTimestamp(rstd::cmp::max(x, y))), - Err(CheckInherentError::Other(s)) => Err(CheckInherentError::Other(s)), - } - } +impl traits::Extrinsic for OpaqueExtrinsic { + fn is_signed(&self) -> Option { + None } } #[cfg(test)] mod tests { - use substrate_primitives::hash::H256; - use codec::{Encode as EncodeHidden, Decode as DecodeHidden}; - use traits::DigestItem; + use substrate_primitives::hash::{H256, H512}; + use crate::codec::{Encode, Decode}; + use crate::traits::DigestItem; pub trait RuntimeT { type AuthorityId; @@ -543,6 +709,8 @@ mod tests { mod a { use super::RuntimeT; + use crate::codec::{Encode, Decode}; + use serde_derive::Serialize; pub type Log = RawLog<::AuthorityId>; #[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)] @@ -551,15 +719,16 @@ mod tests { mod b { use super::RuntimeT; + use crate::codec::{Encode, Decode}; + use serde_derive::Serialize; pub type Log = RawLog<::AuthorityId>; #[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)] pub enum RawLog { B1(AuthorityId), B2(AuthorityId) } } - // TODO try to avoid redundant brackets: a(AuthoritiesChange), b impl_outer_log! { - pub enum Log(InternalLog: DigestItem) for Runtime { + pub enum Log(InternalLog: DigestItem) for Runtime { a(AuthoritiesChange), b() } } @@ -569,26 +738,26 @@ mod tests { // encode/decode regular item let b1: Log = b::RawLog::B1::(777).into(); let encoded_b1 = b1.encode(); - let decoded_b1: Log = DecodeHidden::decode(&mut &encoded_b1[..]).unwrap(); + let decoded_b1: Log = Decode::decode(&mut &encoded_b1[..]).unwrap(); assert_eq!(b1, decoded_b1); // encode/decode system item let auth_change: Log = a::RawLog::AuthoritiesChange::(vec![100, 200, 300]).into(); let encoded_auth_change = auth_change.encode(); - let decoded_auth_change: Log = DecodeHidden::decode(&mut &encoded_auth_change[..]).unwrap(); + let decoded_auth_change: Log = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); assert_eq!(auth_change, decoded_auth_change); // interpret regular item using `generic::DigestItem` - let generic_b1: super::generic::DigestItem = DecodeHidden::decode(&mut &encoded_b1[..]).unwrap(); + let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); match generic_b1 { super::generic::DigestItem::Other(_) => (), _ => panic!("unexpected generic_b1: {:?}", generic_b1), } // interpret system item using `generic::DigestItem` - let generic_auth_change: super::generic::DigestItem = DecodeHidden::decode(&mut &encoded_auth_change[..]).unwrap(); + let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); match generic_auth_change { - super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), + super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), _ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change), } @@ -598,4 +767,55 @@ mod tests { // check that as-style methods are not working with regular items assert!(b1.as_authorities_change().is_none()); } + + #[test] + fn opaque_extrinsic_serialization() { + let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]); + assert_eq!(serde_json::to_string(&ex).unwrap(), "\"0x1001020304\"".to_owned()); + } + + #[test] + fn compact_permill_perbill_encoding() { + let tests = [(0u32, 1usize), (63, 1), (64, 2), (16383, 2), (16384, 4), (1073741823, 4), (1073741824, 5), (u32::max_value(), 5)]; + for &(n, l) in &tests { + let compact: crate::codec::Compact = super::Permill(n).into(); + let encoded = compact.encode(); + assert_eq!(encoded.len(), l); + let decoded = >::decode(&mut & encoded[..]).unwrap(); + let permill: super::Permill = decoded.into(); + assert_eq!(permill, super::Permill(n)); + + let compact: crate::codec::Compact = super::Perbill(n).into(); + let encoded = compact.encode(); + assert_eq!(encoded.len(), l); + let decoded = >::decode(&mut & encoded[..]).unwrap(); + let perbill: super::Perbill = decoded.into(); + assert_eq!(perbill, super::Perbill(n)); + } + } + + #[derive(Encode, Decode, PartialEq, Eq, Debug)] + struct WithCompact { + data: T, + } + + #[test] + fn test_has_compact_permill() { + let data = WithCompact { data: super::Permill(1) }; + let encoded = data.encode(); + assert_eq!(data, WithCompact::::decode(&mut &encoded[..]).unwrap()); + } + + #[test] + fn test_has_compact_perbill() { + let data = WithCompact { data: super::Perbill(1) }; + let encoded = data.encode(); + assert_eq!(data, WithCompact::::decode(&mut &encoded[..]).unwrap()); + } + + #[test] + fn saturating_mul() { + assert_eq!(super::Perbill::one() * std::u64::MAX, std::u64::MAX/1_000_000_000); + assert_eq!(super::Permill::from_percent(100) * std::u64::MAX, std::u64::MAX/1_000_000); + } } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index acbcd9241dc4f336f908511544b9673e57b6868e..2711c0e623d62a171f249ab8adbe9bb998a77e07 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,17 +17,42 @@ //! Testing utilities. use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer}; +use serde_derive::Serialize; +#[cfg(feature = "std")] +use serde_derive::Deserialize; use std::{fmt::Debug, ops::Deref, fmt}; -use codec::{Codec, Encode, Decode}; -use traits::{self, Checkable, Applyable, BlakeTwo256}; -use generic::DigestItem as GenDigestItem; +use crate::codec::{Codec, Encode, Decode}; +use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert}; +use crate::generic::DigestItem as GenDigestItem; +pub use substrate_primitives::H256; +use substrate_primitives::U256; +use substrate_primitives::ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; -pub use substrate_primitives::{H256, AuthorityId}; +/// Authority Id +#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct UintAuthorityId(pub u64); +impl Into for UintAuthorityId { + fn into(self) -> AuthorityId { + let bytes: [u8; 32] = U256::from(self.0).into(); + AuthorityId(bytes) + } +} -pub type DigestItem = GenDigestItem; +/// Converter between u64 and the AuthorityId wrapper type. +pub struct ConvertUintAuthorityId; +impl Convert> for ConvertUintAuthorityId { + fn convert(a: u64) -> Option { + Some(UintAuthorityId(a)) + } +} +/// Digest item +pub type DigestItem = GenDigestItem; +/// Header Digest #[derive(Default, PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] pub struct Digest { + /// Generated logs pub logs: Vec, } @@ -48,14 +73,20 @@ impl traits::Digest for Digest { } } +/// Block Header #[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct Header { + /// Parent hash pub parent_hash: H256, + /// Block Number pub number: u64, + /// Post-execution state trie root pub state_root: H256, + /// Merkle root of block's extrinsics pub extrinsics_root: H256, + /// Digest items pub digest: Digest, } @@ -105,6 +136,7 @@ impl<'a> Deserialize<'a> for Header { } } +/// An opaque extrinsic wrapper type. #[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] pub struct ExtrinsicWrapper(Xt); @@ -135,9 +167,12 @@ impl Deref for ExtrinsicWrapper { } } +/// Testing block #[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] pub struct Block { + /// Block header pub header: Header, + /// List of extrinsics pub extrinsics: Vec, } @@ -167,6 +202,7 @@ impl<'a, Xt> Deserialize<'a> for Block where Block: Decode { } } +/// Test transaction #[derive(PartialEq, Eq, Clone, Encode, Decode)] pub struct TestXt(pub Option, pub u64, pub Call); diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 8bdfd7eda6e1073662b8fc21f68575cff3f71822..e5a58850e747c6979abda9e523d8b34150bfaa49 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,17 +17,18 @@ //! Primitives for the runtime modules. use rstd::prelude::*; -use rstd::{self, result}; +use rstd::{self, result, marker::PhantomData}; use runtime_io; #[cfg(feature = "std")] use std::fmt::{Debug, Display}; #[cfg(feature = "std")] use serde::{Serialize, de::DeserializeOwned}; -use substrate_primitives; -use substrate_primitives::Blake2Hasher; -use codec::{Codec, Encode, HasCompact}; +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; +use substrate_primitives::{self, Hasher, Blake2Hasher}; +use crate::codec::{Codec, Encode, HasCompact}; pub use integer_sqrt::IntegerSquareRoot; -pub use num_traits::{Zero, One, Bounded}; -pub use num_traits::ops::checked::{ - CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr, +pub use num_traits::{ + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr, Saturating }; use rstd::ops::{ Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, @@ -36,6 +37,9 @@ use rstd::ops::{ /// A lazy value. pub trait Lazy { + /// Get a reference to the underlying value. + /// + /// This will compute the value if the function is invoked for the first time. fn get(&mut self) -> &T; } @@ -51,10 +55,26 @@ pub trait Verify { fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; } +impl Verify for substrate_primitives::ed25519::Signature { + type Signer = substrate_primitives::ed25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::ed25519_verify(self.as_ref(), msg.get(), signer) + } +} + +impl Verify for substrate_primitives::sr25519::Signature { + type Signer = substrate_primitives::sr25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::sr25519_verify(self.as_ref(), msg.get(), signer) + } +} + /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { + /// A return type. type Success; - fn ensure_origin(o: OuterOrigin) -> Result; + /// Perform the origin check. + fn ensure_origin(o: OuterOrigin) -> result::Result; } /// Means of changing one type into another in a manner dependent on the source type. @@ -67,6 +87,35 @@ pub trait Lookup { fn lookup(&self, s: Self::Source) -> result::Result; } +/// Means of changing one type into another in a manner dependent on the source type. +/// This variant is different to `Lookup` in that it doesn't (can cannot) require any +/// context. +pub trait StaticLookup { + /// Type to lookup from. + type Source: Codec + Clone + PartialEq + MaybeDebug; + /// Type to lookup into. + type Target; + /// Attempt a lookup. + fn lookup(s: Self::Source) -> result::Result; + /// Convert from Target back to Source. + fn unlookup(t: Self::Target) -> Self::Source; +} + +/// A lookup implementation returning the input value. +#[derive(Default)] +pub struct IdentityLookup(PhantomData); +impl StaticLookup for IdentityLookup { + type Source = T; + type Target = T; + fn lookup(x: T) -> result::Result { Ok(x) } + fn unlookup(x: T) -> T { x } +} +impl Lookup for IdentityLookup { + type Source = T; + type Target = T; + fn lookup(&self, x: T) -> result::Result { Ok(x) } +} + /// Get the "current" block number. pub trait CurrentHeight { /// The type of the block number. @@ -93,30 +142,29 @@ pub trait BlockNumberToHash { } } -/// Simple payment making trait, operating on a single generic `AccountId` type. -pub trait MakePayment { - /// Make some sort of payment concerning `who` for an extrinsic (transaction) of encoded length - /// `encoded_len` bytes. Return true iff the payment was successful. - fn make_payment(who: &AccountId, encoded_len: usize) -> Result<(), &'static str>; -} - -impl MakePayment for () { - fn make_payment(_: &T, _: usize) -> Result<(), &'static str> { Ok(()) } -} - /// Extensible conversion trait. Generic over both source and destination types. pub trait Convert { /// Make conversion. fn convert(a: A) -> B; } +impl Convert for () { + fn convert(_: A) -> B { Default::default() } +} + +/// A structure that performs identity conversion. +pub struct Identity; +impl Convert for Identity { + fn convert(a: T) -> T { a } +} + /// Simple trait similar to `Into`, except that it can be used to convert numerics between each /// other. pub trait As { /// Convert forward (ala `Into::into`). fn as_(self) -> T; /// Convert backward (ala `From::from`). - fn sa(T) -> Self; + fn sa(_: T) -> Self; } macro_rules! impl_numerics { @@ -137,21 +185,7 @@ macro_rules! impl_numerics { impl_numerics!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -pub struct Identity; -impl Convert for Identity { - fn convert(a: T) -> T { a } -} -impl Convert for () { - fn convert(_: T) -> () { () } -} - -pub trait RefInto { - fn ref_into(&self) -> &T; -} -impl RefInto for T { - fn ref_into(&self) -> &T { &self } -} - +/// A meta trait for arithmetic. pub trait SimpleArithmetic: Zero + One + IntegerSquareRoot + As + Add + AddAssign + @@ -166,7 +200,8 @@ pub trait SimpleArithmetic: CheckedSub + CheckedMul + CheckedDiv + - PartialOrd + Ord + + Saturating + + PartialOrd + Ord + Bounded + HasCompact {} impl + Ord + + Saturating + + PartialOrd + Ord + Bounded + HasCompact > SimpleArithmetic for T {} @@ -202,6 +238,7 @@ impl Clear for T { fn clear() -> Self { Default::default() } } +/// A meta trait for all bit ops. pub trait SimpleBitOps: Sized + Clear + rstd::ops::BitOr + @@ -224,6 +261,15 @@ pub trait OnFinalise { impl OnFinalise for () {} +/// The block initialisation trait. Implementing this lets you express what should happen +/// for your module when the block is beginning (right before the first extrinsic is executed). +pub trait OnInitialise { + /// The block is being initialised. Implement to have something happen. + fn on_initialise(_n: BlockNumber) {} +} + +impl OnInitialise for () {} + macro_rules! tuple_impl { ($one:ident,) => { impl> OnFinalise for ($one,) { @@ -231,6 +277,11 @@ macro_rules! tuple_impl { $one::on_finalise(n); } } + impl> OnInitialise for ($one,) { + fn on_initialise(n: Number) { + $one::on_initialise(n); + } + } }; ($first:ident, $($rest:ident,)+) => { impl< @@ -243,6 +294,16 @@ macro_rules! tuple_impl { $($rest::on_finalise(n);)+ } } + impl< + Number: Copy, + $first: OnInitialise, + $($rest: OnInitialise),+ + > OnInitialise for ($first, $($rest),+) { + fn on_initialise(n: Number) { + $first::on_initialise(n); + $($rest::on_initialise(n);)+ + } + } tuple_impl!($($rest,)+); } } @@ -254,7 +315,10 @@ tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived // traits must be fulfilled by all type parameters. /// The hash type produced. - type Output: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]>; + type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default; + + /// The associated hash_db Hasher type. + type Hasher: Hasher; /// Produce the hash of some byte-slice. fn hash(s: &[u8]) -> Self::Output; @@ -294,6 +358,7 @@ pub struct BlakeTwo256; impl Hash for BlakeTwo256 { type Output = substrate_primitives::H256; + type Hasher = Blake2Hasher; fn hash(s: &[u8]) -> Self::Output { runtime_io::blake2_256(s).into() } @@ -323,6 +388,7 @@ impl Hash for BlakeTwo256 { /// Something that can be checked for equality and printed out to a debug channel if bad. pub trait CheckEqual { + /// Perform the equality check. fn check_equal(&self, other: &Self); } @@ -363,66 +429,80 @@ impl CheckEqual for I where I: DigestItem { } } +/// A type that implements Serialize and Debug when in std environment. #[cfg(feature = "std")] pub trait MaybeSerializeDebugButNotDeserialize: Serialize + Debug {} #[cfg(feature = "std")] impl MaybeSerializeDebugButNotDeserialize for T {} +/// A type that implements Serialize and Debug when in std environment. #[cfg(not(feature = "std"))] pub trait MaybeSerializeDebugButNotDeserialize {} #[cfg(not(feature = "std"))] impl MaybeSerializeDebugButNotDeserialize for T {} +/// A type that implements Serialize when in std environment. #[cfg(feature = "std")] pub trait MaybeSerialize: Serialize {} #[cfg(feature = "std")] impl MaybeSerialize for T {} +/// A type that implements Serialize when in std environment. #[cfg(not(feature = "std"))] pub trait MaybeSerialize {} #[cfg(not(feature = "std"))] impl MaybeSerialize for T {} +/// A type that implements Serialize, DeserializeOwned and Debug when in std environment. #[cfg(feature = "std")] pub trait MaybeSerializeDebug: Serialize + DeserializeOwned + Debug {} #[cfg(feature = "std")] impl MaybeSerializeDebug for T {} +/// A type that implements Serialize, DeserializeOwned and Debug when in std environment. #[cfg(not(feature = "std"))] pub trait MaybeSerializeDebug {} #[cfg(not(feature = "std"))] impl MaybeSerializeDebug for T {} +/// A type that implements Debug when in std environment. #[cfg(feature = "std")] pub trait MaybeDebug: Debug {} #[cfg(feature = "std")] impl MaybeDebug for T {} +/// A type that implements Debug when in std environment. #[cfg(not(feature = "std"))] pub trait MaybeDebug {} #[cfg(not(feature = "std"))] impl MaybeDebug for T {} +/// A type that implements Display when in std environment. #[cfg(feature = "std")] pub trait MaybeDisplay: Display {} #[cfg(feature = "std")] impl MaybeDisplay for T {} +/// A type that implements Display when in std environment. #[cfg(not(feature = "std"))] pub trait MaybeDisplay {} #[cfg(not(feature = "std"))] impl MaybeDisplay for T {} +/// A type that implements Hash when in std environment. #[cfg(feature = "std")] -pub trait MaybeDecode: ::codec::Decode {} +pub trait MaybeHash: ::rstd::hash::Hash {} #[cfg(feature = "std")] -impl MaybeDecode for T {} +impl MaybeHash for T {} +/// A type that implements Hash when in std environment. #[cfg(not(feature = "std"))] -pub trait MaybeDecode {} +pub trait MaybeHash {} #[cfg(not(feature = "std"))] -impl MaybeDecode for T {} +impl MaybeHash for T {} + +/// A type that can be used in runtime structures. pub trait Member: Send + Sync + Sized + MaybeDebug + Eq + PartialEq + Clone + 'static {} impl Member for T {} @@ -431,12 +511,17 @@ impl Mem /// `parent_hash`, as well as a `digest` and a block `number`. /// /// You can also create a `new` one from those fields. -pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'static { +pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDeserialize + 'static { + /// Header number. type Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec; + /// Header hash type type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; + /// Hashing algorithm type Hashing: Hash; - type Digest: Digest; + /// Digest type + type Digest: Digest + Codec; + /// Creates new header. fn new( number: Self::Number, extrinsics_root: Self::Hash, @@ -445,23 +530,34 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'stat digest: Self::Digest ) -> Self; + /// Returns a reference to the header number. fn number(&self) -> &Self::Number; - fn set_number(&mut self, Self::Number); + /// Sets the header number. + fn set_number(&mut self, number: Self::Number); + /// Returns a reference to the extrinsics root. fn extrinsics_root(&self) -> &Self::Hash; - fn set_extrinsics_root(&mut self, Self::Hash); + /// Sets the extrinsic root. + fn set_extrinsics_root(&mut self, root: Self::Hash); + /// Returns a reference to the state root. fn state_root(&self) -> &Self::Hash; - fn set_state_root(&mut self, Self::Hash); + /// Sets the state root. + fn set_state_root(&mut self, root: Self::Hash); + /// Returns a reference to the parent hash. fn parent_hash(&self) -> &Self::Hash; - fn set_parent_hash(&mut self, Self::Hash); + /// Sets the parent hash. + fn set_parent_hash(&mut self, hash: Self::Hash); + /// Returns a reference to the digest. fn digest(&self) -> &Self::Digest; /// Get a mutable reference to the digest. fn digest_mut(&mut self) -> &mut Self::Digest; - fn set_digest(&mut self, Self::Digest); + /// Sets the digest. + fn set_digest(&mut self, digest: Self::Digest); + /// Returns the hash of the header. fn hash(&self) -> Self::Hash { ::hash_of(self) } @@ -471,15 +567,23 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'stat /// `Extrinsic` piece of information as well as a `Header`. /// /// You can get an iterator over each of the `extrinsics` and retrieve the `header`. -pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'static { +pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDeserialize + 'static { + /// Type of extrinsics. type Extrinsic: Member + Codec + Extrinsic + MaybeSerialize; + /// Header type. type Header: Header; + /// Block hash type. type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; + /// Returns a reference to the header. fn header(&self) -> &Self::Header; + /// Returns a reference to the list of extrinsics. fn extrinsics(&self) -> &[Self::Extrinsic]; + /// Split the block into header and list of extrinsics. fn deconstruct(self) -> (Self::Header, Vec); + /// Creates new block from header and extrinsics. fn new(header: Self::Header, extrinsics: Vec) -> Self; + /// Returns the hash of the block. fn hash(&self) -> Self::Hash { <::Hashing as Hash>::hash_of(self.header()) } @@ -500,6 +604,8 @@ pub type NumberFor = <::Header as Header>::Number; pub type DigestFor = <::Header as Header>::Digest; /// Extract the digest item type for a block. pub type DigestItemFor = as Digest>::Item; +/// Extract the authority ID type for a block. +pub type AuthorityIdFor = as DigestItem>::AuthorityId; /// A "checkable" piece of information, used by the standard Substrate Executive in order to /// check the validity of a piece of extrinsic information, usually by verifying the signature. @@ -534,24 +640,32 @@ impl Checkable for T { } /// An "executable" piece of information, used by the standard Substrate Executive in order to -/// enact a piece of extrinsic information by marshalling and dispatching to a named functioon +/// enact a piece of extrinsic information by marshalling and dispatching to a named function /// call. /// /// Also provides information on to whom this information is attributable and an index that allows /// each piece of attributable information to be disambiguated. pub trait Applyable: Sized + Send + Sync { + /// Id of the account that is responsible for this piece of information (sender). type AccountId: Member + MaybeDisplay; + /// Index allowing to disambiguate other `Applyable`s from the same `AccountId`. type Index: Member + MaybeDisplay + SimpleArithmetic; + /// Function call. type Call: Member; + /// Returns a reference to the index if any. fn index(&self) -> Option<&Self::Index>; + /// Returns a reference to the sender if any. fn sender(&self) -> Option<&Self::AccountId>; + /// Deconstructs into function call and sender. fn deconstruct(self) -> (Self::Call, Option); } /// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are /// each `Codec`. pub trait Digest: Member + MaybeSerializeDebugButNotDeserialize + Default { - type Hash: Member + MaybeSerializeDebugButNotDeserialize; + /// Hash of the items. + type Hash: Member; + /// Digest item type. type Item: DigestItem; /// Get reference to all digest items. @@ -562,7 +676,7 @@ pub trait Digest: Member + MaybeSerializeDebugButNotDeserialize + Default { fn pop(&mut self) -> Option; /// Get reference to the first digest item that matches the passed predicate. - fn log Option<&T>>(&self, predicate: F) -> Option<&T> { + fn log Option<&T>>(&self, predicate: F) -> Option<&T> { self.logs().iter() .filter_map(predicate) .next() @@ -574,8 +688,10 @@ pub trait Digest: Member + MaybeSerializeDebugButNotDeserialize + Default { /// /// If the runtime does not supports some 'system' items, use `()` as a stub. pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize { - type Hash: Member + MaybeSerializeDebugButNotDeserialize; - type AuthorityId: Member + MaybeSerializeDebugButNotDeserialize; + /// `ChangesTrieRoot` payload. + type Hash: Member; + /// `AuthorityChange` payload. + type AuthorityId: Member + MaybeHash + crate::codec::Encode + crate::codec::Decode; /// Returns Some if the entry is the `AuthoritiesChange` entry. fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]>; @@ -584,26 +700,6 @@ pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize { fn as_changes_trie_root(&self) -> Option<&Self::Hash>; } -/// Something that provides an inherent for a runtime. -pub trait ProvideInherent { - /// The inherent that is provided. - type Inherent: Encode + MaybeDecode; - /// The call for setting the inherent. - type Call: Encode + MaybeDecode; - - /// Create the inherent extrinsics. - /// - /// # Return - /// - /// Returns a vector with tuples containing the index for the extrinsic and the extrinsic itself. - fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)>; - - /// Check that the given inherent is valid. - fn check_inherent Option<&Self::Call>>( - block: &Block, data: Self::Inherent, extract_function: &F - ) -> Result<(), super::CheckInherentError>; -} - /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. pub struct ApiRef<'a, T>(T, rstd::marker::PhantomData<&'a ()>); diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 3e185fea99673436ccd63c86ab2ae8646c1c2220..7cf3aa1d6d6a1bb62f1f94a90ff523c48bdb4a28 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,6 +17,7 @@ //! Transaction validity interface. use rstd::prelude::*; +use crate::codec::{Encode, Decode}; /// Priority for a transaction. Additive. Higher is better. pub type TransactionPriority = u64; @@ -32,12 +33,33 @@ pub type TransactionTag = Vec; #[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum TransactionValidity { - Invalid, + /// Transaction is invalid. Details are described by the error code. + Invalid(i8), + /// Transaction is valid. Valid { + /// Priority of the transaction. + /// + /// Priority determines the ordering of two transactions that have all + /// their dependencies (required tags) satisfied. priority: TransactionPriority, + /// Transaction dependencies + /// + /// A non-empty list signifies that some other transactions which provide + /// given tags are required to be included before that one. requires: Vec, + /// Provided tags + /// + /// A list of tags this transaction provides. Successfuly importing the transaction + /// will enable other transactions that depend on (require) those tags to be included as well. + /// Provided and requried tags allow Substrate to build a dependency graph of transactions + /// and import them in the right (linear) order. provides: Vec, - longevity: TransactionLongevity + /// Transaction longevity + /// + /// Longevity describes minimum number of blocks the validity is correct. + /// After this period transaction should be removed from the pool or revalidated. + longevity: TransactionLongevity, }, - Unknown, + /// Transaction validity can't be determined. + Unknown(i8), } diff --git a/core/sr-sandbox/Cargo.toml b/core/sr-sandbox/Cargo.toml index 2dc384f0fbec3040402b381dddd6518b6c16481e..599e66d6638b1b899619c3b9a175d2343544a5b9 100755 --- a/core/sr-sandbox/Cargo.toml +++ b/core/sr-sandbox/Cargo.toml @@ -3,27 +3,28 @@ name = "sr-sandbox" version = "0.1.0" authors = ["Parity Technologies "] build = "build.rs" +edition = "2018" [build-dependencies] rustc_version = "0.2" [dependencies] -wasmi = { version = "0.4.2", optional = true } -substrate-primitives = { path = "../primitives", default-features = false } -sr-std = { path = "../sr-std", default-features = false } -parity-codec = { version = "2.1", default-features = false } +wasmi = { version = "0.4.3", optional = true } +primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +codec = { package = "parity-codec", version = "3.2", default-features = false } [dev-dependencies] -wabt = "0.7" +wabt = "~0.7.4" assert_matches = "1.1" [features] default = ["std"] std = [ "wasmi", - "substrate-primitives/std", - "sr-std/std", - "parity-codec/std", + "primitives/std", + "rstd/std", + "codec/std", ] nightly = [] strict = [] diff --git a/core/sr-sandbox/build.rs b/core/sr-sandbox/build.rs index 35eb154f3a69ac3fd6e7ae7fc8c02342be7c0a60..62ddacbbf4f993f3d58b036391e0ae0e94dc1b5a 100755 --- a/core/sr-sandbox/build.rs +++ b/core/sr-sandbox/build.rs @@ -1,6 +1,5 @@ //! Set a nightly feature -extern crate rustc_version; use rustc_version::{version, version_meta, Channel}; fn main() { diff --git a/core/sr-sandbox/src/lib.rs b/core/sr-sandbox/src/lib.rs index 09af04747df40e52e441ef0b18da7a3abda4ba92..e8bdd5727ea8795ea16efeae71426aecc014e73f 100755 --- a/core/sr-sandbox/src/lib.rs +++ b/core/sr-sandbox/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -39,19 +39,6 @@ #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; -extern crate substrate_primitives as primitives; -#[cfg(not(feature = "std"))] -extern crate parity_codec as codec; - -#[cfg(test)] -extern crate wabt; - -#[cfg(test)] -#[macro_use] -extern crate assert_matches; - use rstd::prelude::*; pub use primitives::sandbox::{TypedValue, ReturnValue, HostError}; @@ -153,7 +140,7 @@ impl EnvironmentDefinitionBuilder { } } - /// Register a host function in this environment defintion. + /// Register a host function in this environment definition. /// /// NOTE that there is no constraints on type of this function. An instance /// can import function passed here with any signature it wants. It can even import diff --git a/core/sr-sandbox/with_std.rs b/core/sr-sandbox/with_std.rs index d6a60694894098a0782609eae3398bd7229397ab..ea7ce818350d082030c3660ef8408a73cfa1db2c 100755 --- a/core/sr-sandbox/with_std.rs +++ b/core/sr-sandbox/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,17 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -extern crate wasmi; - use rstd::collections::btree_map::BTreeMap; use rstd::fmt; -use self::wasmi::{ +use wasmi::{ Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind }; -use self::wasmi::memory_units::Pages; +use wasmi::memory_units::Pages; use super::{Error, TypedValue, ReturnValue, HostFuncType, HostError}; #[derive(Clone)] @@ -90,7 +88,7 @@ impl fmt::Display for DummyHostError { } } -impl self::wasmi::HostError for DummyHostError { +impl wasmi::HostError for DummyHostError { } fn from_runtime_value(v: RuntimeValue) -> TypedValue { @@ -103,7 +101,7 @@ fn from_runtime_value(v: RuntimeValue) -> TypedValue { } fn to_runtime_value(v: TypedValue) -> RuntimeValue { - use self::wasmi::nan_preserving_float::{F32, F64}; + use wasmi::nan_preserving_float::{F32, F64}; match v { TypedValue::I32(v) => RuntimeValue::I32(v as i32), TypedValue::I64(v) => RuntimeValue::I64(v as i64), @@ -309,7 +307,8 @@ impl Instance { #[cfg(test)] mod tests { use wabt; - use ::{Error, TypedValue, ReturnValue, HostError, EnvironmentDefinitionBuilder, Instance}; + use crate::{Error, TypedValue, ReturnValue, HostError, EnvironmentDefinitionBuilder, Instance}; + use assert_matches::assert_matches; fn execute_sandboxed(code: &[u8], args: &[TypedValue]) -> Result { struct State { diff --git a/core/sr-sandbox/without_std.rs b/core/sr-sandbox/without_std.rs index d75168f1b06e3496af1f51ad2be2c714e359fc7e..070ca1ddf15cfd9f08e9275f57cea6567c8b3e11 100755 --- a/core/sr-sandbox/without_std.rs +++ b/core/sr-sandbox/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-std/Cargo.toml b/core/sr-std/Cargo.toml index 8f4774ec5d1e62b416128adde8a9f8eb68850fbf..da1c799159e51249ada3f9058e0718b4325a6675 100644 --- a/core/sr-std/Cargo.toml +++ b/core/sr-std/Cargo.toml @@ -3,6 +3,7 @@ name = "sr-std" version = "0.1.0" authors = ["Parity Technologies "] build = "build.rs" +edition = "2018" [build-dependencies] rustc_version = "0.2" diff --git a/core/sr-std/build.rs b/core/sr-std/build.rs index 55688bad9cc5193389437bc35eed06668f848f6e..3cac76831607babfcdf6ccc7bea25b92c25daf98 100644 --- a/core/sr-std/build.rs +++ b/core/sr-std/build.rs @@ -1,6 +1,5 @@ //! Set a nightly feature -extern crate rustc_version; use rustc_version::{version, version_meta, Channel}; fn main() { diff --git a/core/sr-std/src/lib.rs b/core/sr-std/src/lib.rs index 416c91bc7f49b9832a87d4ff5d0d34040fdbe6cd..45857b33eda784a3107bc162a3c12c1b610d0342 100644 --- a/core/sr-std/src/lib.rs +++ b/core/sr-std/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -41,8 +41,13 @@ include!("../without_std.rs"); /// /// This should include only things which are in the normal std prelude. pub mod prelude { - pub use ::vec::Vec; - pub use ::boxed::Box; - pub use ::cmp::{Eq, PartialEq}; - pub use ::clone::Clone; + pub use crate::vec::Vec; + pub use crate::boxed::Box; + pub use crate::cmp::{Eq, PartialEq}; + pub use crate::clone::Clone; + + // Re-export `vec!` macro here, but not in `std` mode, since + // std's prelude already brings `vec!` into the scope. + #[cfg(not(feature = "std"))] + pub use crate::vec; } diff --git a/core/sr-std/with_std.rs b/core/sr-std/with_std.rs index 7a718dfd2718308757834ec375258f93ed1123bd..27df71c4092f570cfb63fae62d27de0960c4ec3c 100644 --- a/core/sr-std/with_std.rs +++ b/core/sr-std/with_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-std/without_std.rs b/core/sr-std/without_std.rs index d5065648e9c7780ae1299f709762da00730afe53..c5178854848d6a09eef4bacfe1bc3f1ce51da02f 100644 --- a/core/sr-std/without_std.rs +++ b/core/sr-std/without_std.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/core/sr-version/Cargo.toml b/core/sr-version/Cargo.toml index 785eecdfa7c32c735e1f41e8d073e9e3ce411017..cf3062faac01b7ffd0316e81324b1f39c926b1c3 100644 --- a/core/sr-version/Cargo.toml +++ b/core/sr-version/Cargo.toml @@ -2,21 +2,23 @@ name = "sr-version" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +impl-serde = { version = "0.1", optional = true } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -sr-std = { path = "../sr-std", default-features = false } -sr-primitives = { path = "../sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } [features] default = ["std"] std = [ - "serde/std", + "impl-serde", + "serde", "serde_derive", "parity-codec/std", - "sr-std/std", - "sr-primitives/std", + "rstd/std", + "runtime_primitives/std", ] diff --git a/core/sr-version/src/lib.rs b/core/sr-version/src/lib.rs index b24347baa89d3775fc25581b8de756740987682e..71a4c5149d393faac9b139aee3fa23e89f756b91 100644 --- a/core/sr-version/src/lib.rs +++ b/core/sr-version/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,18 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; - -#[allow(unused_imports)] -#[macro_use] -extern crate sr_std as rstd; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate sr_primitives as runtime_primitives; - +use serde_derive::Serialize; #[cfg(feature = "std")] use std::fmt; #[cfg(feature = "std")] @@ -38,6 +27,9 @@ use std::collections::HashSet; #[cfg(feature = "std")] use runtime_primitives::traits::RuntimeApiInfo; +use parity_codec::Encode; +#[cfg(feature = "std")] +use parity_codec::Decode; use runtime_primitives::RuntimeString; pub use runtime_primitives::create_runtime_str; @@ -71,7 +63,8 @@ macro_rules! create_apis_vec { /// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, /// absolutely not `impl_version` since they change the semantics of the runtime. #[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Decode))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and node. /// A different on-chain spec_name to that of the native runtime would normally result @@ -103,6 +96,7 @@ pub struct RuntimeVersion { pub impl_version: u32, /// List of supported API "features" along with their versions. + #[cfg_attr(feature = "std", serde(serialize_with = "apis_serialize::serialize"))] pub apis: ApisVec, } @@ -134,6 +128,16 @@ impl RuntimeVersion { s == &A::ID && *v == A::VERSION }) } + + /// Check if the given api is implemented and the version passes a predicate. + pub fn has_api_with bool>( + &self, + pred: P, + ) -> bool { + self.apis.iter().any(|(s, v)| { + s == &A::ID && pred(*v) + }) + } } #[cfg(feature = "std")] @@ -154,3 +158,33 @@ impl NativeVersion { self.can_author_with.contains(&other.authoring_version)) } } + +#[cfg(feature = "std")] +mod apis_serialize { + use super::*; + use impl_serde::serialize as bytes; + use serde::{Serializer, ser::SerializeTuple}; + + #[derive(Serialize)] + struct ApiId<'a>( + #[serde(serialize_with="serialize_bytesref")] &'a super::ApiId, + &'a u32, + ); + + pub fn serialize(apis: &ApisVec, ser: S) -> Result where + S: Serializer, + { + let len = apis.len(); + let mut seq = ser.serialize_tuple(len)?; + for (api, ver) in &**apis { + seq.serialize_element(&ApiId(api, ver))?; + } + seq.end() + } + + pub fn serialize_bytesref(apis: &&super::ApiId, ser: S) -> Result where + S: Serializer, + { + bytes::serialize(*apis, ser) + } +} diff --git a/core/state-db/Cargo.toml b/core/state-db/Cargo.toml index bef12d1ae6a61a539a9d1435fbe9ec3d41854eaf..28d5696928ef5bf99bc353e86111b0221a1ac2c8 100644 --- a/core/state-db/Cargo.toml +++ b/core/state-db/Cargo.toml @@ -2,13 +2,13 @@ name = "substrate-state-db" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -parking_lot = "0.5" +parking_lot = "0.7.1" log = "0.4" -substrate-primitives = { path = "../../core/primitives" } -parity-codec = "2.1" -parity-codec-derive = "2.1" +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +parity-codec = { version = "3.2", features = ["derive"] } [dev-dependencies] -env_logger = "0.4" +env_logger = "0.6" diff --git a/core/state-db/src/lib.rs b/core/state-db/src/lib.rs index 51fffa1f2dce4ee72702142bf8bdf9524f2e039e..4cb10e768db2be5a2ad42e278d92c3c483ace5e4 100644 --- a/core/state-db/src/lib.rs +++ b/core/state-db/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -29,23 +29,18 @@ //! See `RefWindow` for pruning algorithm details. `StateDb` prunes on each canonicalization until pruning //! constraints are satisfied. -#[macro_use] extern crate log; -#[macro_use] extern crate parity_codec_derive; -extern crate parking_lot; -extern crate parity_codec as codec; -#[cfg(test)] -extern crate substrate_primitives as primitives; - mod noncanonical; mod pruning; #[cfg(test)] mod test; use std::fmt; use parking_lot::RwLock; +use parity_codec as codec; use codec::Codec; use std::collections::HashSet; use noncanonical::NonCanonicalOverlay; use pruning::RefWindow; +use log::trace; /// Database value type. pub type DBValue = Vec; @@ -62,7 +57,6 @@ pub trait MetaDb { fn get_meta(&self, key: &[u8]) -> Result, Self::Error>; } - /// Backend database trait. Read-only. pub trait HashDb { type Hash: Hash; @@ -78,8 +72,12 @@ pub enum Error { Db(E), /// `Codec` decoding error. Decoding, - /// NonCanonical error. - NonCanonical, + /// Trying to canonicalize invalid block. + InvalidBlock, + /// Trying to insert block with invalid number. + InvalidBlockNumber, + /// Trying to insert block with unknown parent. + InvalidParent, } impl fmt::Debug for Error { @@ -87,7 +85,9 @@ impl fmt::Debug for Error { match self { Error::Db(e) => e.fmt(f), Error::Decoding => write!(f, "Error decoding slicable value"), - Error::NonCanonical => write!(f, "Error processing non-canonical data"), + Error::InvalidBlock => write!(f, "Trying to canonicalize invalid block"), + Error::InvalidBlockNumber => write!(f, "Trying to insert block with invalid number"), + Error::InvalidParent => write!(f, "Trying to insert block with unknown parent"), } } } @@ -190,12 +190,6 @@ impl StateDbSync { } pub fn insert_block(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, mut changeset: ChangeSet) -> Result, Error> { - if number == 0 { - return Ok(CommitSet { - data: changeset, - meta: Default::default(), - }) - } match self.mode { PruningMode::ArchiveAll => { changeset.deleted.clear(); @@ -211,35 +205,42 @@ impl StateDbSync { } } - pub fn canonicalize_block(&mut self, hash: &BlockHash) -> CommitSet { - // clear the temporary overlay from the previous canonicalization. - self.non_canonical.clear_overlay(); + pub fn canonicalize_block(&mut self, hash: &BlockHash) -> Result, Error> { let mut commit = match self.mode { PruningMode::ArchiveAll => { CommitSet::default() }, PruningMode::ArchiveCanonical => { - let mut commit = self.non_canonical.canonicalize(hash); + let mut commit = self.non_canonical.canonicalize(hash)?; commit.data.deleted.clear(); commit }, PruningMode::Constrained(_) => { - self.non_canonical.canonicalize(hash) + self.non_canonical.canonicalize(hash)? }, }; if let Some(ref mut pruning) = self.pruning { pruning.note_canonical(hash, &mut commit); } self.prune(&mut commit); - commit + Ok(commit) } - pub fn best_canonical(&self) -> u64 { + pub fn best_canonical(&self) -> Option { return self.non_canonical.last_canonicalized_block_number() } - pub fn is_pruned(&self, number: u64) -> bool { - self.pruning.as_ref().map_or(false, |pruning| number < pruning.pending()) + pub fn is_pruned(&self, hash: &BlockHash, number: u64) -> bool { + match self.mode { + PruningMode::ArchiveAll => false, + PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { + if self.best_canonical().map(|c| number > c).unwrap_or(true) { + !self.non_canonical.have_block(hash) + } else { + self.pruning.as_ref().map_or(false, |pruning| number < pruning.pending() || !pruning.have_block(hash)) + } + } + } } fn prune(&mut self, commit: &mut CommitSet) { @@ -290,6 +291,27 @@ impl StateDbSync { } db.get(key).map_err(|e| Error::Db(e)) } + + pub fn apply_pending(&mut self) { + self.non_canonical.apply_pending(); + if let Some(pruning) = &mut self.pruning { + pruning.apply_pending(); + } + trace!(target: "forks", "First available: {:?} ({}), Last canon: {:?} ({}), Best forks: {:?}", + self.pruning.as_ref().and_then(|p| p.next_hash()), + self.pruning.as_ref().map(|p| p.pending()).unwrap_or(0), + self.non_canonical.last_canonicalized_hash(), + self.non_canonical.last_canonicalized_block_number().unwrap_or(0), + self.non_canonical.top_level(), + ); + } + + pub fn revert_pending(&mut self) { + if let Some(pruning) = &mut self.pruning { + pruning.revert_pending(); + } + self.non_canonical.revert_pending(); + } } /// State DB maintenance. See module description. @@ -312,7 +334,7 @@ impl StateDb { } /// Finalize a previously inserted block. - pub fn canonicalize_block(&self, hash: &BlockHash) -> CommitSet { + pub fn canonicalize_block(&self, hash: &BlockHash) -> Result, Error> { self.db.write().canonicalize_block(hash) } @@ -339,13 +361,23 @@ impl StateDb { } /// Returns last finalized block number. - pub fn best_canonical(&self) -> u64 { + pub fn best_canonical(&self) -> Option { return self.db.read().best_canonical() } /// Check if block is pruned away. - pub fn is_pruned(&self, number: u64) -> bool { - return self.db.read().is_pruned(number) + pub fn is_pruned(&self, hash: &BlockHash, number: u64) -> bool { + return self.db.read().is_pruned(hash, number) + } + + /// Apply all pending changes + pub fn apply_pending(&self) { + self.db.write().apply_pending(); + } + + /// Revert all pending changes + pub fn revert_pending(&self) { + self.db.write().revert_pending(); } } @@ -353,8 +385,8 @@ impl StateDb { mod tests { use std::io; use primitives::H256; - use {StateDb, PruningMode, Constraints}; - use test::{make_db, make_changeset, TestDb}; + use crate::{StateDb, PruningMode, Constraints}; + use crate::test::{make_db, make_changeset, TestDb}; fn make_test_db(settings: PruningMode) -> (TestDb, StateDb) { let mut db = make_db(&[91, 921, 922, 93, 94]); @@ -400,7 +432,9 @@ mod tests { ) .unwrap(), ); - db.commit(&state_db.canonicalize_block(&H256::from_low_u64_be(1))); + state_db.apply_pending(); + db.commit(&state_db.canonicalize_block::(&H256::from_low_u64_be(1)).unwrap()); + state_db.apply_pending(); db.commit( &state_db .insert_block::( @@ -411,16 +445,20 @@ mod tests { ) .unwrap(), ); - db.commit(&state_db.canonicalize_block(&H256::from_low_u64_be(21))); - db.commit(&state_db.canonicalize_block(&H256::from_low_u64_be(3))); + state_db.apply_pending(); + db.commit(&state_db.canonicalize_block::(&H256::from_low_u64_be(21)).unwrap()); + state_db.apply_pending(); + db.commit(&state_db.canonicalize_block::(&H256::from_low_u64_be(3)).unwrap()); + state_db.apply_pending(); (db, state_db) } #[test] fn full_archive_keeps_everything() { - let (db, _) = make_test_db(PruningMode::ArchiveAll); + let (db, sdb) = make_test_db(PruningMode::ArchiveAll); assert!(db.data_eq(&make_db(&[1, 21, 22, 3, 4, 91, 921, 922, 93, 94]))); + assert!(!sdb.is_pruned(&H256::from_low_u64_be(0), 0)); } #[test] @@ -444,9 +482,10 @@ mod tests { max_blocks: Some(1), max_mem: None, })); - assert!(sdb.is_pruned(0)); - assert!(sdb.is_pruned(1)); - assert!(!sdb.is_pruned(2)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(0), 0)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(1), 1)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(21), 2)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(22), 2)); assert!(db.data_eq(&make_db(&[21, 3, 922, 93, 94]))); } @@ -456,8 +495,10 @@ mod tests { max_blocks: Some(2), max_mem: None, })); - assert!(sdb.is_pruned(0)); - assert!(!sdb.is_pruned(1)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(0), 0)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(1), 1)); + assert!(!sdb.is_pruned(&H256::from_low_u64_be(21), 2)); + assert!(sdb.is_pruned(&H256::from_low_u64_be(22), 2)); assert!(db.data_eq(&make_db(&[1, 21, 3, 921, 922, 93, 94]))); } } diff --git a/core/state-db/src/noncanonical.rs b/core/state-db/src/noncanonical.rs index b1d34c09ad3ab0d422e661382a43e1a6c013c449..da957335ba30f4e7d59e5fe7f5eda6613b9943d7 100644 --- a/core/state-db/src/noncanonical.rs +++ b/core/state-db/src/noncanonical.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,13 +17,14 @@ //! Canonicalization window. //! Maintains trees of block overlays and allows discarding trees/roots //! The overlays are added in `insert` and removed in `canonicalize`. -//! Last canonicalized overlay is kept in memory until next call to `canonicalize` or -//! `clear_overlay` +//! All pending changes are kept in memory until next call to `apply_pending` or +//! `revert_pending` use std::fmt; -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, VecDeque, hash_map::Entry}; use super::{Error, DBValue, ChangeSet, CommitSet, MetaDb, Hash, to_meta_key}; -use codec::{Decode, Encode}; +use crate::codec::{Encode, Decode}; +use log::trace; const NON_CANONICAL_JOURNAL: &[u8] = b"noncanonical_journal"; const LAST_CANONICAL: &[u8] = b"last_canonical"; @@ -33,7 +34,9 @@ pub struct NonCanonicalOverlay { last_canonicalized: Option<(BlockHash, u64)>, levels: VecDeque>>, parents: HashMap, - last_canonicalized_overlay: HashMap, + pending_canonicalizations: Vec, + pending_insertions: Vec, + values: HashMap, //ref counted } #[derive(Encode, Decode)] @@ -52,10 +55,61 @@ fn to_journal_key(block: u64, index: u64) -> Vec { struct BlockOverlay { hash: BlockHash, journal_key: Vec, - values: HashMap, + inserted: Vec, deleted: Vec, } +fn insert_values(values: &mut HashMap, inserted: Vec<(Key, DBValue)>) { + for (k, v) in inserted { + debug_assert!(values.get(&k).map_or(true, |(_, value)| *value == v)); + let (ref mut counter, _) = values.entry(k).or_insert_with(|| (0, v)); + *counter += 1; + } +} + +fn discard_values(values: &mut HashMap, inserted: Vec) { + for k in inserted { + match values.entry(k) { + Entry::Occupied(mut e) => { + let (ref mut counter, _) = e.get_mut(); + *counter -= 1; + if *counter == 0 { + e.remove(); + } + }, + Entry::Vacant(_) => { + debug_assert!(false, "Trying to discard missing value"); + } + } + } +} + +fn discard_descendants( + levels: &mut VecDeque>>, + mut values: &mut HashMap, + index: usize, + parents: &mut HashMap, + hash: &BlockHash, + ) { + let mut discarded = Vec::new(); + if let Some(level) = levels.get_mut(index) { + *level = level.drain(..).filter_map(|overlay| { + let parent = parents.get(&overlay.hash).expect("there is a parent entry for each entry in levels; qed").clone(); + if parent == *hash { + parents.remove(&overlay.hash); + discarded.push(overlay.hash); + discard_values(&mut values, overlay.inserted); + None + } else { + Some(overlay) + } + }).collect(); + } + for hash in discarded { + discard_descendants(levels, values, index + 1, parents, &hash); + } +} + impl NonCanonicalOverlay { /// Creates a new instance. Does not expect any metadata to be present in the DB. pub fn new(db: &D) -> Result, Error> { @@ -67,6 +121,7 @@ impl NonCanonicalOverlay { }; let mut levels = VecDeque::new(); let mut parents = HashMap::new(); + let mut values = HashMap::new(); if let Some((ref hash, mut block)) = last_canonicalized { // read the journal trace!(target: "state-db", "Reading uncanonicalized journal. Last canonicalized #{} ({:?})", block, hash); @@ -80,13 +135,15 @@ impl NonCanonicalOverlay { match db.get_meta(&journal_key).map_err(|e| Error::Db(e))? { Some(record) => { let record: JournalRecord = Decode::decode(&mut record.as_slice()).ok_or(Error::Decoding)?; + let inserted = record.inserted.iter().map(|(k, _)| k.clone()).collect(); let overlay = BlockOverlay { hash: record.hash.clone(), journal_key, - values: record.inserted.into_iter().collect(), + inserted: inserted, deleted: record.deleted, }; - trace!(target: "state-db", "Uncanonicalized journal entry {}.{} ({} inserted, {} deleted)", block, index, overlay.values.len(), overlay.deleted.len()); + insert_values(&mut values, record.inserted); + trace!(target: "state-db", "Uncanonicalized journal entry {}.{} ({} inserted, {} deleted)", block, index, overlay.inserted.len(), overlay.deleted.len()); level.push(overlay); parents.insert(record.hash, record.parent_hash); index += 1; @@ -107,39 +164,43 @@ impl NonCanonicalOverlay { last_canonicalized, levels, parents, - last_canonicalized_overlay: Default::default(), + pending_canonicalizations: Default::default(), + pending_insertions: Default::default(), + values: values, }) } /// Insert a new block into the overlay. If inserted on the second level or lover expects parent to be present in the window. pub fn insert(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, changeset: ChangeSet) -> Result, Error> { let mut commit = CommitSet::default(); - if self.levels.is_empty() && self.last_canonicalized.is_none() { - if number < 1 { - return Err(Error::NonCanonical); - } + let front_block_number = self.front_block_number(); + if self.levels.is_empty() && self.last_canonicalized.is_none() && number > 0 { // assume that parent was canonicalized let last_canonicalized = (parent_hash.clone(), number - 1); commit.meta.inserted.push((to_meta_key(LAST_CANONICAL, &()), last_canonicalized.encode())); self.last_canonicalized = Some(last_canonicalized); } else if self.last_canonicalized.is_some() { - if number < self.front_block_number() || number >= self.front_block_number() + self.levels.len() as u64 + 1 { - return Err(Error::NonCanonical); + if number < front_block_number || number >= front_block_number + self.levels.len() as u64 + 1 { + trace!(target: "state-db", "Failed to insert block {}, current is {} .. {})", + number, + front_block_number, + front_block_number + self.levels.len() as u64, + ); + return Err(Error::InvalidBlockNumber); } // check for valid parent if inserting on second level or higher - if number == self.front_block_number() { + if number == front_block_number { if !self.last_canonicalized.as_ref().map_or(false, |&(ref h, n)| h == parent_hash && n == number - 1) { - return Err(Error::NonCanonical); + return Err(Error::InvalidParent); } } else if !self.parents.contains_key(&parent_hash) { - return Err(Error::NonCanonical); + return Err(Error::InvalidParent); } } - let level = if self.levels.is_empty() || number == self.front_block_number() + self.levels.len() as u64 { + let level = if self.levels.is_empty() || number == front_block_number + self.levels.len() as u64 { self.levels.push_back(Vec::new()); self.levels.back_mut().expect("can't be empty after insertion; qed") } else { - let front_block_number = self.front_block_number(); self.levels.get_mut((number - front_block_number) as usize) .expect("number is [front_block_number .. front_block_number + levels.len()) is asserted in precondition; qed") }; @@ -147,10 +208,11 @@ impl NonCanonicalOverlay { let index = level.len() as u64; let journal_key = to_journal_key(number, index); + let inserted = changeset.inserted.iter().map(|(k, _)| k.clone()).collect(); let overlay = BlockOverlay { hash: hash.clone(), journal_key: journal_key.clone(), - values: changeset.inserted.iter().cloned().collect(), + inserted: inserted, deleted: changeset.deleted.clone(), }; level.push(overlay); @@ -161,29 +223,20 @@ impl NonCanonicalOverlay { inserted: changeset.inserted, deleted: changeset.deleted, }; + commit.meta.inserted.push((journal_key, journal_record.encode())); trace!(target: "state-db", "Inserted uncanonicalized changeset {}.{} ({} inserted, {} deleted)", number, index, journal_record.inserted.len(), journal_record.deleted.len()); - let journal_record = journal_record.encode(); - commit.meta.inserted.push((journal_key, journal_record)); + insert_values(&mut self.values, journal_record.inserted); + self.pending_insertions.push(hash.clone()); Ok(commit) } - fn discard( - levels: &mut [Vec>], - parents: &mut HashMap, - discarded_journals: &mut Vec>, - number: u64, - hash: &BlockHash, - ) { - if let Some((level, sublevels)) = levels.split_first_mut() { - level.retain(|ref overlay| { - let parent = parents.get(&overlay.hash).expect("there is a parent entry for each entry in levels; qed").clone(); + fn discard_journals(&self, level_index: usize, discarded_journals: &mut Vec>, hash: &BlockHash) { + if let Some(level) = self.levels.get(level_index) { + level.iter().for_each(|overlay| { + let parent = self.parents.get(&overlay.hash).expect("there is a parent entry for each entry in levels; qed").clone(); if parent == *hash { - parents.remove(&overlay.hash); discarded_journals.push(overlay.journal_key.clone()); - Self::discard(sublevels, parents, discarded_journals, number + 1, &overlay.hash); - false - } else { - true + self.discard_journals(level_index + 1, discarded_journals, &overlay.hash); } }); } @@ -193,66 +246,98 @@ impl NonCanonicalOverlay { self.last_canonicalized.as_ref().map(|&(_, n)| n + 1).unwrap_or(0) } - pub fn last_canonicalized_block_number(&self) -> u64 { - self.last_canonicalized.as_ref().map(|&(_, n)| n).unwrap_or(0) + pub fn last_canonicalized_block_number(&self) -> Option { + match self.last_canonicalized.as_ref().map(|&(_, n)| n) { + Some(n) => Some(n + self.pending_canonicalizations.len() as u64), + None if !self.pending_canonicalizations.is_empty() => Some(self.pending_canonicalizations.len() as u64), + _ => None, + } + } + + pub fn last_canonicalized_hash(&self) -> Option { + self.last_canonicalized.as_ref().map(|&(ref h, _)| h.clone()) } - /// This may be called when the last finalization commit was applied to the database. - pub fn clear_overlay(&mut self) { - self.last_canonicalized_overlay.clear(); + pub fn top_level(&self) -> Vec<(BlockHash, u64)> { + let start = self.last_canonicalized_block_number().unwrap_or(0); + self.levels + .get(self.pending_canonicalizations.len()) + .map(|level| level.iter().map(|r| (r.hash.clone(), start)).collect()) + .unwrap_or_default() } /// Select a top-level root and canonicalized it. Discards all sibling subtrees and the root. /// Returns a set of changes that need to be added to the DB. - pub fn canonicalize(&mut self, hash: &BlockHash) -> CommitSet { + pub fn canonicalize(&mut self, hash: &BlockHash) -> Result, Error> { trace!(target: "state-db", "Canonicalizing {:?}", hash); - let level = self.levels.pop_front().expect("no blocks to canonicalize"); - let index = level.iter().position(|overlay| overlay.hash == *hash) - .expect("attempting to canonicalize unknown block"); + let level = self.levels.get(self.pending_canonicalizations.len()).ok_or_else(|| Error::InvalidBlock)?; + let index = level + .iter() + .position(|overlay| overlay.hash == *hash) + .ok_or_else(|| Error::InvalidBlock)?; let mut commit = CommitSet::default(); let mut discarded_journals = Vec::new(); for (i, overlay) in level.into_iter().enumerate() { - self.parents.remove(&overlay.hash); if i == index { - self.last_canonicalized_overlay = overlay.values; // that's the one we need to canonicalize - commit.data.inserted = self.last_canonicalized_overlay.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); - commit.data.deleted = overlay.deleted; + commit.data.inserted = overlay.inserted.iter() + .map(|k| (k.clone(), self.values.get(k).expect("For each key in verlays there's a value in values").1.clone())) + .collect(); + commit.data.deleted = overlay.deleted.clone(); } else { - // TODO: borrow checker won't allow us to split out mutable references - // required for recursive processing. A more efficient implementation - // that does not require converting to vector is possible - let mut vec: Vec<_> = self.levels.drain(..).collect(); - Self::discard(&mut vec, &mut self.parents, &mut discarded_journals, 0, &overlay.hash); - self.levels.extend(vec.into_iter()); + self.discard_journals(self.pending_canonicalizations.len() + 1, &mut discarded_journals, &overlay.hash); } - // cleanup journal entry - discarded_journals.push(overlay.journal_key); + discarded_journals.push(overlay.journal_key.clone()); } commit.meta.deleted.append(&mut discarded_journals); - let last_canonicalized = (hash.clone(), self.front_block_number()); - commit.meta.inserted.push((to_meta_key(LAST_CANONICAL, &()), last_canonicalized.encode())); - self.last_canonicalized = Some(last_canonicalized); - trace!(target: "state-db", "Discarded {} records", commit.meta.deleted.len()); - commit + let canonicalized = (hash.clone(), self.front_block_number() + self.pending_canonicalizations.len() as u64); + commit.meta.inserted.push((to_meta_key(LAST_CANONICAL, &()), canonicalized.encode())); + trace!(target: "state-db", "Discarding {} records", commit.meta.deleted.len()); + self.pending_canonicalizations.push(hash.clone()); + Ok(commit) + } + + fn apply_canonicalizations(&mut self) { + let last = self.pending_canonicalizations.last().cloned(); + let count = self.pending_canonicalizations.len() as u64; + for hash in self.pending_canonicalizations.drain(..) { + trace!(target: "state-db", "Post canonicalizing {:?}", hash); + let level = self.levels.pop_front().expect("Hash validity is checked in `canonicalize`"); + let index = level + .iter() + .position(|overlay| overlay.hash == hash) + .expect("Hash validity is checked in `canonicalize`"); + + // discard unfinalized overlays and values + for (i, overlay) in level.into_iter().enumerate() { + self.parents.remove(&overlay.hash); + if i != index { + discard_descendants(&mut self.levels, &mut self.values, 0, &mut self.parents, &overlay.hash); + } + discard_values(&mut self.values, overlay.inserted); + } + } + if let Some(hash) = last { + let last_canonicalized = (hash, self.last_canonicalized.as_ref().map(|(_, n)| n + count).unwrap_or(count - 1)); + self.last_canonicalized = Some(last_canonicalized); + } } /// Get a value from the node overlay. This searches in every existing changeset. pub fn get(&self, key: &Key) -> Option { - if let Some(value) = self.last_canonicalized_overlay.get(&key) { + if let Some((_, value)) = self.values.get(&key) { return Some(value.clone()); } - for level in self.levels.iter() { - for overlay in level.iter() { - if let Some(value) = overlay.values.get(&key) { - return Some(value.clone()); - } - } - } None } + /// Check if the block is in the canonicalization queue. + pub fn have_block(&self, hash: &BlockHash) -> bool { + (self.parents.contains_key(hash) || self.pending_insertions.contains(hash)) + && !self.pending_canonicalizations.contains(hash) + } + /// Revert a single level. Returns commit set that deletes the journal or `None` if not possible. pub fn revert_one(&mut self) -> Option> { self.levels.pop_back().map(|level| { @@ -260,19 +345,51 @@ impl NonCanonicalOverlay { for overlay in level.into_iter() { commit.meta.deleted.push(overlay.journal_key); self.parents.remove(&overlay.hash); + discard_values(&mut self.values, overlay.inserted); } commit }) } + + fn revert_insertions(&mut self) { + self.pending_insertions.reverse(); + for hash in self.pending_insertions.drain(..) { + self.parents.remove(&hash); + // find a level. When iterating insertions backwards the hash is always last in the level. + let level_index = + self.levels.iter().position(|level| + level.last().expect("Hash is added in `insert` in reverse order").hash == hash) + .expect("Hash is added in insert"); + + let overlay = self.levels[level_index].pop().expect("Empty levels are not allowed in self.levels"); + discard_values(&mut self.values, overlay.inserted); + if self.levels[level_index].is_empty() { + debug_assert_eq!(level_index, self.levels.len() - 1); + self.levels.pop_back(); + } + } + } + + /// Apply all pending changes + pub fn apply_pending(&mut self) { + self.apply_canonicalizations(); + self.pending_insertions.clear(); + } + + /// Revert all pending changes + pub fn revert_pending(&mut self) { + self.pending_canonicalizations.clear(); + self.revert_insertions(); + } } #[cfg(test)] mod tests { use std::io; - use super::NonCanonicalOverlay; - use {ChangeSet}; use primitives::H256; - use test::{make_db, make_changeset}; + use super::{NonCanonicalOverlay, to_journal_key}; + use crate::ChangeSet; + use crate::test::{make_db, make_changeset}; fn contains(overlay: &NonCanonicalOverlay, key: u64) -> bool { overlay.get(&H256::from_low_u64_be(key)) == Some(H256::from_low_u64_be(key).as_bytes().to_vec()) @@ -292,7 +409,7 @@ mod tests { fn canonicalize_empty_panics() { let db = make_db(&[]); let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); - overlay.canonicalize(&H256::default()); + overlay.canonicalize::(&H256::default()).unwrap(); } #[test] @@ -336,7 +453,7 @@ mod tests { let db = make_db(&[]); let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); overlay.insert::(&h1, 1, &H256::default(), ChangeSet::default()).unwrap(); - overlay.canonicalize(&h2); + overlay.canonicalize::(&h2).unwrap(); } #[test] @@ -351,7 +468,7 @@ mod tests { assert_eq!(insertion.meta.inserted.len(), 2); assert_eq!(insertion.meta.deleted.len(), 0); db.commit(&insertion); - let finalization = overlay.canonicalize(&h1); + let finalization = overlay.canonicalize::(&h1).unwrap(); assert_eq!(finalization.data.inserted.len(), changeset.inserted.len()); assert_eq!(finalization.data.deleted.len(), changeset.deleted.len()); assert_eq!(finalization.meta.inserted.len(), 1); @@ -384,7 +501,8 @@ mod tests { let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); db.commit(&overlay.insert::(&h1, 10, &H256::default(), make_changeset(&[3, 4], &[2])).unwrap()); db.commit(&overlay.insert::(&h2, 11, &h1, make_changeset(&[5], &[3])).unwrap()); - db.commit(&overlay.canonicalize(&h1)); + db.commit(&overlay.canonicalize::(&h1).unwrap()); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 1); let overlay2 = NonCanonicalOverlay::::new(&db).unwrap(); @@ -408,23 +526,59 @@ mod tests { assert!(contains(&overlay, 5)); assert_eq!(overlay.levels.len(), 2); assert_eq!(overlay.parents.len(), 2); - db.commit(&overlay.canonicalize(&h1)); + db.commit(&overlay.canonicalize::(&h1).unwrap()); + assert!(contains(&overlay, 5)); + assert_eq!(overlay.levels.len(), 2); + assert_eq!(overlay.parents.len(), 2); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 1); assert_eq!(overlay.parents.len(), 1); - assert!(contains(&overlay, 5)); - overlay.clear_overlay(); assert!(!contains(&overlay, 5)); assert!(contains(&overlay, 7)); - db.commit(&overlay.canonicalize(&h2)); - overlay.clear_overlay(); + db.commit(&overlay.canonicalize::(&h2).unwrap()); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 0); assert_eq!(overlay.parents.len(), 0); assert!(db.data_eq(&make_db(&[1, 4, 6, 7, 8]))); } + #[test] + fn insert_same_key() { + let mut db = make_db(&[]); + let (h_1, c_1) = (H256::random(), make_changeset(&[1], &[])); + let (h_2, c_2) = (H256::random(), make_changeset(&[1], &[])); + + let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); + db.commit(&overlay.insert::(&h_1, 1, &H256::default(), c_1).unwrap()); + db.commit(&overlay.insert::(&h_2, 1, &H256::default(), c_2).unwrap()); + assert!(contains(&overlay, 1)); + db.commit(&overlay.canonicalize::(&h_1).unwrap()); + assert!(contains(&overlay, 1)); + overlay.apply_pending(); + assert!(!contains(&overlay, 1)); + } + + #[test] + fn insert_with_pending_canonicalization() { + let h1 = H256::random(); + let h2 = H256::random(); + let h3 = H256::random(); + let mut db = make_db(&[]); + let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); + let changeset = make_changeset(&[], &[]); + db.commit(&overlay.insert::(&h1, 1, &H256::default(), changeset.clone()).unwrap()); + db.commit(&overlay.insert::(&h2, 2, &h1, changeset.clone()).unwrap()); + overlay.apply_pending(); + db.commit(&overlay.canonicalize::(&h1).unwrap()); + db.commit(&overlay.canonicalize::(&h2).unwrap()); + db.commit(&overlay.insert::(&h3, 3, &h2, changeset.clone()).unwrap()); + overlay.apply_pending(); + assert_eq!(overlay.levels.len(), 1); + } #[test] fn complex_tree() { + use crate::MetaDb; let mut db = make_db(&[]); // - 1 - 1_1 - 1_1_1 @@ -485,8 +639,8 @@ mod tests { assert_eq!(overlay.last_canonicalized, overlay2.last_canonicalized); // canonicalize 1. 2 and all its children should be discarded - db.commit(&overlay.canonicalize(&h_1)); - overlay.clear_overlay(); + db.commit(&overlay.canonicalize::(&h_1).unwrap()); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 2); assert_eq!(overlay.parents.len(), 6); assert!(!contains(&overlay, 1)); @@ -495,10 +649,17 @@ mod tests { assert!(!contains(&overlay, 22)); assert!(!contains(&overlay, 211)); assert!(contains(&overlay, 111)); + assert!(!contains(&overlay, 211)); + // check that journals are deleted + assert!(db.get_meta(&to_journal_key(1, 0)).unwrap().is_none()); + assert!(db.get_meta(&to_journal_key(1, 1)).unwrap().is_none()); + assert!(db.get_meta(&to_journal_key(2, 1)).unwrap().is_some()); + assert!(db.get_meta(&to_journal_key(2, 2)).unwrap().is_none()); + assert!(db.get_meta(&to_journal_key(2, 3)).unwrap().is_none()); // canonicalize 1_2. 1_1 and all its children should be discarded - db.commit(&overlay.canonicalize(&h_1_2)); - overlay.clear_overlay(); + db.commit(&overlay.canonicalize::(&h_1_2).unwrap()); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 1); assert_eq!(overlay.parents.len(), 3); assert!(!contains(&overlay, 11)); @@ -506,10 +667,14 @@ mod tests { assert!(contains(&overlay, 121)); assert!(contains(&overlay, 122)); assert!(contains(&overlay, 123)); + assert!(overlay.have_block(&h_1_2_1)); + assert!(!overlay.have_block(&h_1_2)); + assert!(!overlay.have_block(&h_1_1)); + assert!(!overlay.have_block(&h_1_1_1)); // canonicalize 1_2_2 - db.commit(&overlay.canonicalize(&h_1_2_2)); - overlay.clear_overlay(); + db.commit(&overlay.canonicalize::(&h_1_2_2).unwrap()); + overlay.apply_pending(); assert_eq!(overlay.levels.len(), 0); assert_eq!(overlay.parents.len(), 0); assert!(db.data_eq(&make_db(&[1, 12, 122]))); @@ -538,5 +703,29 @@ mod tests { assert!(overlay.revert_one().is_none()); } + #[test] + fn revert_pending_insertion() { + let h1 = H256::random(); + let h2_1 = H256::random(); + let h2_2 = H256::random(); + let db = make_db(&[]); + let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); + let changeset1 = make_changeset(&[5, 6], &[2]); + let changeset2 = make_changeset(&[7, 8], &[5, 3]); + let changeset3 = make_changeset(&[9], &[]); + overlay.insert::(&h1, 1, &H256::default(), changeset1).unwrap(); + assert!(contains(&overlay, 5)); + overlay.insert::(&h2_1, 2, &h1, changeset2).unwrap(); + overlay.insert::(&h2_2, 2, &h1, changeset3).unwrap(); + assert!(contains(&overlay, 7)); + assert!(contains(&overlay, 5)); + assert!(contains(&overlay, 9)); + assert_eq!(overlay.levels.len(), 2); + assert_eq!(overlay.parents.len(), 3); + overlay.revert_pending(); + assert!(!contains(&overlay, 5)); + assert_eq!(overlay.levels.len(), 0); + assert_eq!(overlay.parents.len(), 0); + } } diff --git a/core/state-db/src/pruning.rs b/core/state-db/src/pruning.rs index 91f2b9db91311a124101d9b64b79d2b7edea5d4b..c2e40abe413be0c379983939212d49dad40a7b6b 100644 --- a/core/state-db/src/pruning.rs +++ b/core/state-db/src/pruning.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,8 +23,10 @@ //! The changes are journaled in the DB. use std::collections::{HashMap, HashSet, VecDeque}; -use codec::{Encode, Decode}; -use {CommitSet, Error, MetaDb, to_meta_key, Hash}; +use std::mem; +use crate::codec::{Encode, Decode}; +use crate::{CommitSet, Error, MetaDb, to_meta_key, Hash}; +use log::{trace, warn}; const LAST_PRUNED: &[u8] = b"last_pruned"; const PRUNING_JOURNAL: &[u8] = b"pruning_journal"; @@ -34,6 +36,8 @@ pub struct RefWindow { death_rows: VecDeque>, death_index: HashMap, pending_number: u64, + pending_records: Vec<(u64, JournalRecord)>, + pending_prunings: usize, } #[derive(Debug, PartialEq, Eq)] @@ -67,6 +71,8 @@ impl RefWindow { death_rows: Default::default(), death_index: Default::default(), pending_number: pending_number, + pending_records: Default::default(), + pending_prunings: 0, }; // read the journal trace!(target: "state-db", "Reading pruning journal. Pending #{}", pending_number); @@ -108,11 +114,11 @@ impl RefWindow { } pub fn window_size(&self) -> u64 { - self.death_rows.len() as u64 + (self.death_rows.len() + self.pending_records.len() - self.pending_prunings) as u64 } pub fn next_hash(&self) -> Option { - self.death_rows.front().map(|r| r.hash.clone()) + self.death_rows.get(self.pending_prunings).map(|r| r.hash.clone()) } pub fn mem_used(&self) -> usize { @@ -120,20 +126,33 @@ impl RefWindow { } pub fn pending(&self) -> u64 { - self.pending_number + self.pending_number + self.pending_prunings as u64 + } + + pub fn have_block(&self, hash: &BlockHash) -> bool { + self.death_rows.iter().skip(self.pending_prunings).any(|r| r.hash == *hash) || + self.pending_records.iter().any(|(_, record)| record.hash == *hash) } /// Prune next block. Expects at least one block in the window. Adds changes to `commit`. pub fn prune_one(&mut self, commit: &mut CommitSet) { - let pruned = self.death_rows.pop_front().expect("prune_one is only called with a non-empty window"); - trace!(target: "state-db", "Pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); - for k in pruned.deleted.iter() { - self.death_index.remove(&k); + if let Some(pruned) = self.death_rows.get(self.pending_prunings) { + trace!(target: "state-db", "Pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); + let index = self.pending_number + self.pending_prunings as u64; + commit.data.deleted.extend(pruned.deleted.iter().cloned()); + commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), index.encode())); + commit.meta.deleted.push(pruned.journal_key.clone()); + self.pending_prunings += 1; + } else if let Some((block, pruned)) = self.pending_records.get(self.pending_prunings - self.death_rows.len()) { + trace!(target: "state-db", "Pruning pending{:?} ({} deleted)", pruned.hash, pruned.deleted.len()); + commit.data.deleted.extend(pruned.deleted.iter().cloned()); + commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), block.encode())); + let journal_key = to_journal_key(*block); + commit.meta.deleted.push(journal_key); + self.pending_prunings += 1; + } else { + warn!(target: "state-db", "Trying to prune when there's nothing to prune"); } - commit.data.deleted.extend(pruned.deleted.into_iter()); - commit.meta.inserted.push((to_meta_key(LAST_PRUNED, &()), self.pending_number.encode())); - commit.meta.deleted.push(pruned.journal_key); - self.pending_number += 1; } /// Add a change set to the window. Creates a journal record and pushes it to `commit` @@ -146,11 +165,36 @@ impl RefWindow { inserted, deleted, }; - let block = self.pending_number + self.window_size(); + // Calculate pending block number taking pending canonicalizations into account, but not pending prunings + // as these are always applied last. + let block = self.pending_number + (self.death_rows.len() + self.pending_records.len()) as u64; let journal_key = to_journal_key(block); commit.meta.inserted.push((journal_key.clone(), journal_record.encode())); + self.pending_records.push((block, journal_record)); + } + + /// Apply all pending changes + pub fn apply_pending(&mut self) { + for (block, journal_record) in mem::replace(&mut self.pending_records, Default::default()).into_iter() { + trace!(target: "state-db", "Applying pruning window record: {}: {:?}", block, journal_record.hash); + let journal_key = to_journal_key(block); + self.import(&journal_record.hash, journal_key, journal_record.inserted.into_iter(), journal_record.deleted); + } + for _ in 0 .. self.pending_prunings { + let pruned = self.death_rows.pop_front().expect("pending_prunings is always < death_rows.len()"); + trace!(target: "state-db", "Applying pruning {:?} ({} deleted)", pruned.hash, pruned.deleted.len()); + for k in pruned.deleted.iter() { + self.death_index.remove(&k); + } + self.pending_number += 1; + } + self.pending_prunings = 0; + } - self.import(hash, journal_key, journal_record.inserted.into_iter(), journal_record.deleted); + /// Revert all pending changes + pub fn revert_pending(&mut self) { + self.pending_records.clear(); + self.pending_prunings = 0; } } @@ -158,8 +202,8 @@ impl RefWindow { mod tests { use super::RefWindow; use primitives::H256; - use {CommitSet}; - use test::{make_db, make_commit, TestDb}; + use crate::CommitSet; + use crate::test::{make_db, make_commit, TestDb}; fn check_journal(pruning: &RefWindow, db: &TestDb) { let restored: RefWindow = RefWindow::new(db).unwrap(); @@ -178,12 +222,16 @@ mod tests { } #[test] - #[should_panic] - fn prune_empty_panics() { + fn prune_empty() { let db = make_db(&[]); let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); let mut commit = CommitSet::default(); pruning.prune_one(&mut commit); + assert_eq!(pruning.pending_number, 0); + assert!(pruning.death_rows.is_empty()); + assert!(pruning.death_index.is_empty()); + assert!(pruning.pending_prunings == 0); + assert!(pruning.pending_records.is_empty()); } #[test] @@ -194,6 +242,9 @@ mod tests { let h = H256::random(); pruning.note_canonical(&h, &mut commit); db.commit(&commit); + assert!(pruning.have_block(&h)); + pruning.apply_pending(); + assert!(pruning.have_block(&h)); assert!(commit.data.deleted.is_empty()); assert_eq!(pruning.death_rows.len(), 1); assert_eq!(pruning.death_index.len(), 2); @@ -202,7 +253,10 @@ mod tests { let mut commit = CommitSet::default(); pruning.prune_one(&mut commit); + assert!(!pruning.have_block(&h)); db.commit(&commit); + pruning.apply_pending(); + assert!(!pruning.have_block(&h)); assert!(db.data_eq(&make_db(&[2, 4, 5]))); assert!(pruning.death_rows.is_empty()); assert!(pruning.death_index.is_empty()); @@ -219,10 +273,35 @@ mod tests { let mut commit = make_commit(&[5], &[2]); pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); + pruning.apply_pending(); assert!(db.data_eq(&make_db(&[1, 2, 3, 4, 5]))); check_journal(&pruning, &db); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + pruning.apply_pending(); + assert!(db.data_eq(&make_db(&[2, 3, 4, 5]))); + let mut commit = CommitSet::default(); + pruning.prune_one(&mut commit); + db.commit(&commit); + pruning.apply_pending(); + assert!(db.data_eq(&make_db(&[3, 4, 5]))); + assert_eq!(pruning.pending_number, 2); + } + + #[test] + fn prune_two_pending() { + let mut db = make_db(&[1, 2, 3]); + let mut pruning: RefWindow = RefWindow::new(&db).unwrap(); + let mut commit = make_commit(&[4], &[1]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + let mut commit = make_commit(&[5], &[2]); + pruning.note_canonical(&H256::random(), &mut commit); + db.commit(&commit); + assert!(db.data_eq(&make_db(&[1, 2, 3, 4, 5]))); let mut commit = CommitSet::default(); pruning.prune_one(&mut commit); db.commit(&commit); @@ -230,6 +309,7 @@ mod tests { let mut commit = CommitSet::default(); pruning.prune_one(&mut commit); db.commit(&commit); + pruning.apply_pending(); assert!(db.data_eq(&make_db(&[3, 4, 5]))); assert_eq!(pruning.pending_number, 2); } @@ -248,6 +328,7 @@ mod tests { pruning.note_canonical(&H256::random(), &mut commit); db.commit(&commit); assert!(db.data_eq(&make_db(&[1, 2, 3]))); + pruning.apply_pending(); check_journal(&pruning, &db); @@ -262,6 +343,7 @@ mod tests { pruning.prune_one(&mut commit); db.commit(&commit); assert!(db.data_eq(&make_db(&[1, 3]))); + pruning.apply_pending(); assert_eq!(pruning.pending_number, 3); } } diff --git a/core/state-db/src/test.rs b/core/state-db/src/test.rs index 487a5c641d1fe1a67e1bf5578d47e2c7d7ccc92c..cec5935142e7486299599dcaa6cd79577e4025f4 100644 --- a/core/state-db/src/test.rs +++ b/core/state-db/src/test.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ use std::collections::HashMap; use primitives::H256; -use {DBValue, ChangeSet, CommitSet, MetaDb, HashDb}; +use crate::{DBValue, ChangeSet, CommitSet, MetaDb, HashDb}; #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct TestDb { @@ -46,6 +46,7 @@ impl HashDb for TestDb { impl TestDb { pub fn commit(&mut self, commit: &CommitSet) { self.data.extend(commit.data.inserted.iter().cloned()); + self.meta.extend(commit.meta.inserted.iter().cloned()); for k in commit.data.deleted.iter() { self.data.remove(k); } diff --git a/core/state-machine/Cargo.toml b/core/state-machine/Cargo.toml index c0254116feee8924d0abf03f84cd69b1dcd98b34..61a99f8e94fdede21578e73a095fecf3888fccda 100644 --- a/core/state-machine/Cargo.toml +++ b/core/state-machine/Cargo.toml @@ -3,15 +3,17 @@ name = "substrate-state-machine" version = "0.1.0" authors = ["Parity Technologies "] description = "Substrate State Machine" +edition = "2018" [dependencies] hex-literal = "0.1.0" log = "0.4" -parking_lot = "0.4" +parking_lot = "0.7.1" heapsize = "0.4" -hash-db = { git = "https://github.com/paritytech/trie" } -trie-db = { git = "https://github.com/paritytech/trie" } -trie-root = { git = "https://github.com/paritytech/trie" } -substrate-trie = { path = "../trie" } -substrate-primitives = { path = "../primitives" } -parity-codec = "2.1" +hash-db = "0.11" +trie-db = "0.11" +trie-root = "0.11" +trie = { package = "substrate-trie", path = "../trie" } +primitives = { package = "substrate-primitives", path = "../primitives" } +panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } +parity-codec = "3.2" diff --git a/core/state-machine/src/backend.rs b/core/state-machine/src/backend.rs index f9949deae9db1daa7928609b069e920a28398971..0acbf278579ba3ab2b54a1e12bac0d5e80435a0c 100644 --- a/core/state-machine/src/backend.rs +++ b/core/state-machine/src/backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,10 +20,11 @@ use std::{error, fmt}; use std::cmp::Ord; use std::collections::HashMap; use std::marker::PhantomData; +use log::warn; use hash_db::Hasher; -use trie_backend::TrieBackend; -use trie_backend_essence::TrieBackendStorage; -use substrate_trie::{TrieDBMut, TrieMut, MemoryDB, trie_root, child_trie_root, default_child_trie_root}; +use crate::trie_backend::TrieBackend; +use crate::trie_backend_essence::TrieBackendStorage; +use trie::{TrieDBMut, TrieMut, MemoryDB, trie_root, child_trie_root, default_child_trie_root}; use heapsize::HeapSizeOf; /// A state backend is used to read state data and can have changes committed @@ -40,10 +41,15 @@ pub trait Backend { /// Type of trie backend storage. type TrieBackendStorage: TrieBackendStorage; - /// Get keyed storage associated with specific address, or None if there is nothing associated. + /// Get keyed storage or None if there is nothing associated. fn storage(&self, key: &[u8]) -> Result>, Self::Error>; - /// Get keyed child storage associated with specific address, or None if there is nothing associated. + /// Get keyed storage value hash or None if there is nothing associated. + fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + self.storage(key).map(|v| v.map(|v| H::hash(&v))) + } + + /// Get keyed child storage or None if there is nothing associated. fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error>; /// true if a key exists in storage. @@ -81,6 +87,9 @@ pub trait Backend { /// Get all key/value pairs into a Vec. fn pairs(&self) -> Vec<(Vec, Vec)>; + /// Get all keys with given prefix + fn keys(&self, prefix: &Vec) -> Vec>; + /// Try convert into trie backend. fn try_into_trie_backend(self) -> Option>; } @@ -110,7 +119,7 @@ impl Consolidate for MemoryDB { } /// Error impossible. -// TODO: use `!` type when stabilized. +// FIXME: use `!` type when stabilized. https://github.com/rust-lang/rust/issues/35121 #[derive(Debug)] pub enum Void {} @@ -278,8 +287,12 @@ impl Backend for InMemory where H::Out: HeapSizeOf { self.inner.get(&None).into_iter().flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.clone()))).collect() } + fn keys(&self, prefix: &Vec) -> Vec> { + self.inner.get(&None).into_iter().flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()).collect() + } + fn try_into_trie_backend(self) -> Option> { - let mut mdb = MemoryDB::default(); // TODO: should be more correct and use ::new() + let mut mdb = MemoryDB::default(); let mut root = None; for (storage_key, map) in self.inner { if storage_key != None { diff --git a/core/state-machine/src/basic.rs b/core/state-machine/src/basic.rs new file mode 100644 index 0000000000000000000000000000000000000000..ead191a3c05adfe09be0cc25aac593d22b106fae --- /dev/null +++ b/core/state-machine/src/basic.rs @@ -0,0 +1,183 @@ +// 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 . + +//! Basic implementation for Externalities. + +use std::collections::HashMap; +use std::iter::FromIterator; +use hash_db::Hasher; +use heapsize::HeapSizeOf; +use trie::trie_root; +use primitives::storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES}; +use parity_codec::Encode; +use super::{Externalities, OverlayedChanges}; + +/// Simple HashMap-based Externalities impl. +pub struct BasicExternalities { + inner: HashMap, Vec>, + changes: OverlayedChanges, + code: Option>, +} + +impl BasicExternalities { + /// Create a new instance of `BasicExternalities` + pub fn new(inner: HashMap, Vec>) -> Self { + Self::new_with_code(&[], inner) + } + + /// Create a new instance of `BasicExternalities` + pub fn new_with_code(code: &[u8], mut inner: HashMap, Vec>) -> Self { + let mut overlay = OverlayedChanges::default(); + super::set_changes_trie_config( + &mut overlay, + inner.get(&CHANGES_TRIE_CONFIG.to_vec()).cloned(), + false, + ).expect("changes trie configuration is correct in test env; qed"); + + inner.insert(HEAP_PAGES.to_vec(), 8u64.encode()); + + BasicExternalities { + inner, + changes: overlay, + code: Some(code.to_vec()), + } + } + + /// Insert key/value + pub fn insert(&mut self, k: Vec, v: Vec) -> Option> { + self.inner.insert(k, v) + } +} + +impl ::std::fmt::Debug for BasicExternalities { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{:?}", self.inner) + } +} + +impl PartialEq for BasicExternalities { + fn eq(&self, other: &BasicExternalities) -> bool { + self.inner.eq(&other.inner) + } +} + +impl FromIterator<(Vec, Vec)> for BasicExternalities { + fn from_iter, Vec)>>(iter: I) -> Self { + let mut t = Self::new(Default::default()); + t.inner.extend(iter); + t + } +} + +impl Default for BasicExternalities { + fn default() -> Self { Self::new(Default::default()) } +} + +impl From for HashMap, Vec> { + fn from(tex: BasicExternalities) -> Self { + tex.inner.into() + } +} + +impl From< HashMap, Vec> > for BasicExternalities { + fn from(hashmap: HashMap, Vec>) -> Self { + BasicExternalities { + inner: hashmap, + changes: Default::default(), + code: None, + } + } +} + +impl Externalities for BasicExternalities where H::Out: Ord + HeapSizeOf { + fn storage(&self, key: &[u8]) -> Option> { + match key { + CODE => self.code.clone(), + _ => self.inner.get(key).cloned(), + } + } + + fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> Option> { + None + } + + fn place_storage(&mut self, key: Vec, maybe_value: Option>) { + self.changes.set_storage(key.clone(), maybe_value.clone()); + match key.as_ref() { + CODE => self.code = maybe_value, + _ => { + match maybe_value { + Some(value) => { self.inner.insert(key, value); } + None => { self.inner.remove(&key); } + } + } + } + } + + fn place_child_storage(&mut self, _storage_key: Vec, _key: Vec, _value: Option>) -> bool { + false + } + + fn kill_child_storage(&mut self, _storage_key: &[u8]) { } + + fn clear_prefix(&mut self, prefix: &[u8]) { + self.changes.clear_prefix(prefix); + self.inner.retain(|key, _| !key.starts_with(prefix)); + } + + fn chain_id(&self) -> u64 { 42 } + + fn storage_root(&mut self) -> H::Out { + trie_root::(self.inner.clone()) + } + + fn child_storage_root(&mut self, _storage_key: &[u8]) -> Option> { + None + } + + fn storage_changes_root(&mut self, _parent: H::Out, _parent_num: u64) -> Option { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use primitives::{Blake2Hasher, H256}; + use hex_literal::{hex, hex_impl}; + + #[test] + fn commit_should_work() { + let mut ext = BasicExternalities::default(); + let ext = &mut ext as &mut Externalities; + ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); + ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); + ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); + const ROOT: [u8; 32] = hex!("0b33ed94e74e0f8e92a55923bece1ed02d16cf424e124613ddebc53ac3eeeabe"); + assert_eq!(ext.storage_root(), H256::from(ROOT)); + } + + #[test] + fn set_and_retrieve_code() { + let mut ext = BasicExternalities::default(); + let ext = &mut ext as &mut Externalities; + + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); + + assert_eq!(&ext.storage(CODE).unwrap(), &code); + } +} diff --git a/core/state-machine/src/changes_trie/build.rs b/core/state-machine/src/changes_trie/build.rs index c183f2b3cce23ca81f4b800dc32bf88cd29ad79e..9cb766874d8f847136093f334199c92046181d83 100644 --- a/core/state-machine/src/changes_trie/build.rs +++ b/core/state-machine/src/changes_trie/build.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,15 +17,15 @@ //! Structures and functions required to build changes trie for given block. use std::collections::{BTreeMap, BTreeSet}; -use codec::Decode; +use parity_codec::Decode; use hash_db::Hasher; use heapsize::HeapSizeOf; -use backend::Backend; -use overlayed_changes::OverlayedChanges; -use trie_backend_essence::{TrieBackendStorage, TrieBackendEssence}; -use changes_trie::build_iterator::digest_build_iterator; -use changes_trie::input::{InputKey, InputPair, DigestIndex, ExtrinsicIndex}; -use changes_trie::{AnchorBlockId, Configuration, Storage}; +use crate::backend::Backend; +use crate::overlayed_changes::OverlayedChanges; +use crate::trie_backend_essence::{TrieBackendStorage, TrieBackendEssence}; +use crate::changes_trie::build_iterator::digest_build_iterator; +use crate::changes_trie::input::{InputKey, InputPair, DigestIndex, ExtrinsicIndex}; +use crate::changes_trie::{AnchorBlockId, Configuration, Storage}; /// Prepare input pairs for building a changes trie of given block. /// @@ -142,12 +142,12 @@ fn prepare_digest_input<'a, S, H>( #[cfg(test)] mod test { - use codec::Encode; + use parity_codec::Encode; use primitives::Blake2Hasher; use primitives::storage::well_known_keys::EXTRINSIC_INDEX; - use backend::InMemory; - use changes_trie::storage::InMemoryStorage; - use overlayed_changes::OverlayedValue; + use crate::backend::InMemory; + use crate::changes_trie::storage::InMemoryStorage; + use crate::overlayed_changes::OverlayedValue; use super::*; fn prepare_for_build() -> (InMemory, InMemoryStorage, OverlayedChanges) { diff --git a/core/state-machine/src/changes_trie/build_iterator.rs b/core/state-machine/src/changes_trie/build_iterator.rs index 6cc86b294bee4963f22d049f5185182bf2469c2c..f9c6ba6e7b397021ca0c856499de012217815867 100644 --- a/core/state-machine/src/changes_trie/build_iterator.rs +++ b/core/state-machine/src/changes_trie/build_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ //! Structures and functions to return blocks whose changes are to be included //! in given block' changes trie. -use changes_trie::Configuration; +use crate::changes_trie::Configuration; /// Returns iterator of OTHER blocks that are required for inclusion into /// changes trie of given block. diff --git a/core/state-machine/src/changes_trie/changes_iterator.rs b/core/state-machine/src/changes_trie/changes_iterator.rs index e8bd1e7db6b1a8dab7d21dcaea1520924d89dc3d..f524b0799cc357779221d25b4040f7272379bc7c 100644 --- a/core/state-machine/src/changes_trie/changes_iterator.rs +++ b/core/state-machine/src/changes_trie/changes_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,27 +19,31 @@ use std::cell::RefCell; use std::collections::VecDeque; -use codec::{Decode, Encode}; +use parity_codec::{Decode, Encode}; use hash_db::{HashDB, Hasher}; use heapsize::HeapSizeOf; -use substrate_trie::{Recorder, MemoryDB}; -use changes_trie::{AnchorBlockId, Configuration, RootsStorage, Storage}; -use changes_trie::input::{DigestIndex, ExtrinsicIndex, DigestIndexValue, ExtrinsicIndexValue}; -use changes_trie::storage::{TrieBackendAdapter, InMemoryStorage}; -use proving_backend::ProvingBackendEssence; -use trie_backend_essence::{TrieBackendEssence}; +use trie::{Recorder, MemoryDB}; +use crate::changes_trie::{AnchorBlockId, Configuration, RootsStorage, Storage}; +use crate::changes_trie::input::{DigestIndex, ExtrinsicIndex, DigestIndexValue, ExtrinsicIndexValue}; +use crate::changes_trie::storage::{TrieBackendAdapter, InMemoryStorage}; +use crate::proving_backend::ProvingBackendEssence; +use crate::trie_backend_essence::{TrieBackendEssence}; /// Return changes of given key at given blocks range. /// `max` is the number of best known block. -pub fn key_changes, H: Hasher>( - config: &Configuration, - storage: &S, +/// Changes are returned in descending order (i.e. last block comes first). +pub fn key_changes<'a, S: Storage, H: Hasher>( + config: &'a Configuration, + storage: &'a S, begin: u64, - end: &AnchorBlockId, + end: &'a AnchorBlockId, max: u64, - key: &[u8], -) -> Result, String> where H::Out: HeapSizeOf { - DrilldownIterator { + key: &'a [u8], +) -> Result, String> where H::Out: HeapSizeOf { + // we can't query any roots before root + let max = ::std::cmp::min(max, end.number); + + Ok(DrilldownIterator { essence: DrilldownIteratorEssence { key, roots_storage: storage, @@ -53,7 +57,7 @@ pub fn key_changes, H: Hasher>( _hasher: ::std::marker::PhantomData::::default(), }, - }.collect() + }) } /// Returns proof of changes of given key at given blocks range. @@ -66,6 +70,9 @@ pub fn key_changes_proof, H: Hasher>( max: u64, key: &[u8], ) -> Result>, String> where H::Out: HeapSizeOf { + // we can't query any roots before root + let max = ::std::cmp::min(max, end.number); + let mut iter = ProvingDrilldownIterator { essence: DrilldownIteratorEssence { key, @@ -93,6 +100,7 @@ pub fn key_changes_proof, H: Hasher>( /// Check key changes proog and return changes of the key at given blocks range. /// `max` is the number of best known block. +/// Changes are returned in descending order (i.e. last block comes first). pub fn key_changes_proof_check, H: Hasher>( config: &Configuration, roots_storage: &S, @@ -102,7 +110,10 @@ pub fn key_changes_proof_check, H: Hasher>( max: u64, key: &[u8] ) -> Result, String> where H::Out: HeapSizeOf { - let mut proof_db = MemoryDB::::default(); // TODO: use new for correctness + // we can't query any roots before root + let max = ::std::cmp::min(max, end.number); + + let mut proof_db = MemoryDB::::default(); for item in proof { proof_db.insert(&item); } @@ -261,7 +272,7 @@ impl<'a, RS: 'a + RootsStorage, S: Storage, H: Hasher> DrilldownIteratorEs } /// Exploring drilldown operator. -struct DrilldownIterator<'a, RS: 'a + RootsStorage, S: 'a + Storage, H: Hasher> where H::Out: 'a { +pub struct DrilldownIterator<'a, RS: 'a + RootsStorage, S: 'a + Storage, H: Hasher> where H::Out: 'a { essence: DrilldownIteratorEssence<'a, RS, S, H>, } @@ -379,9 +390,10 @@ fn lower_bound_max_digest( #[cfg(test)] mod tests { + use std::iter::FromIterator; use primitives::Blake2Hasher; - use changes_trie::input::InputPair; - use changes_trie::storage::InMemoryStorage; + use crate::changes_trie::input::InputPair; + use crate::changes_trie::storage::InMemoryStorage; use super::*; fn prepare_for_drilldown() -> (Configuration, InMemoryStorage) { @@ -427,23 +439,28 @@ mod tests { fn drilldown_iterator_works() { let (config, storage) = prepare_for_drilldown(); let drilldown_result = key_changes::, Blake2Hasher>( - &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42]); + &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42]) + .and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)])); let drilldown_result = key_changes::, Blake2Hasher>( - &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 2 }, 4, &[42]); + &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 2 }, 4, &[42]) + .and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![])); let drilldown_result = key_changes::, Blake2Hasher>( - &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 3 }, 4, &[42]); + &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 3 }, 4, &[42]) + .and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(3, 0)])); let drilldown_result = key_changes::, Blake2Hasher>( - &config, &storage, 7, &AnchorBlockId { hash: Default::default(), number: 8 }, 8, &[42]); + &config, &storage, 7, &AnchorBlockId { hash: Default::default(), number: 8 }, 8, &[42]) + .and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1)])); let drilldown_result = key_changes::, Blake2Hasher>( - &config, &storage, 5, &AnchorBlockId { hash: Default::default(), number: 7 }, 8, &[42]); + &config, &storage, 5, &AnchorBlockId { hash: Default::default(), number: 7 }, 8, &[42]) + .and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(6, 3)])); } @@ -453,7 +470,8 @@ mod tests { storage.clear_storage(); assert!(key_changes::, Blake2Hasher>( - &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 100 }, 1000, &[42]).is_err()); + &config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 100 }, 1000, &[42]) + .and_then(|i| i.collect::, _>>()).is_err()); } #[test] diff --git a/core/state-machine/src/changes_trie/input.rs b/core/state-machine/src/changes_trie/input.rs index 5ab7e25e7c2d388b04b6b4cf297715d6b79b79f3..3154aff715c2ba79070b6ecd6dd3c49a77c0729b 100644 --- a/core/state-machine/src/changes_trie/input.rs +++ b/core/state-machine/src/changes_trie/input.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! Different types of changes trie input pairs. -use codec::{Decode, Encode, Input, Output}; +use parity_codec::{Decode, Encode, Input, Output}; /// Key of { changed key => set of extrinsic indices } mapping. #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/core/state-machine/src/changes_trie/mod.rs b/core/state-machine/src/changes_trie/mod.rs index 1d523854ee3e3a78e35a831d4a042065ad4adb4e..0119c3ca3105b609caa237173ae8505bfaa351a1 100644 --- a/core/state-machine/src/changes_trie/mod.rs +++ b/core/state-machine/src/changes_trie/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -44,15 +44,15 @@ mod storage; pub use self::storage::InMemoryStorage; pub use self::changes_iterator::{key_changes, key_changes_proof, key_changes_proof_check}; -pub use self::prune::prune; +pub use self::prune::{prune, oldest_non_pruned_trie}; use hash_db::Hasher; use heapsize::HeapSizeOf; -use backend::Backend; +use crate::backend::Backend; use primitives; -use changes_trie::build::prepare_input; -use overlayed_changes::OverlayedChanges; -use trie_backend_essence::TrieBackendStorage; +use crate::changes_trie::build::prepare_input; +use crate::overlayed_changes::OverlayedChanges; +use crate::trie_backend_essence::TrieBackendStorage; use trie::{DBValue, trie_root}; /// Changes that are made outside of extrinsics are marked with this index; diff --git a/core/state-machine/src/changes_trie/prune.rs b/core/state-machine/src/changes_trie/prune.rs index 9886105115059c7bed68ccfe7253fb726378af62..de872a325589e9854b135ab1c3acce981edac994 100644 --- a/core/state-machine/src/changes_trie/prune.rs +++ b/core/state-machine/src/changes_trie/prune.rs @@ -1,4 +1,4 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,11 +18,28 @@ use hash_db::Hasher; use heapsize::HeapSizeOf; -use substrate_trie::Recorder; -use proving_backend::ProvingBackendEssence; -use trie_backend_essence::TrieBackendEssence; -use changes_trie::{AnchorBlockId, Configuration, Storage}; -use changes_trie::storage::TrieBackendAdapter; +use trie::Recorder; +use log::warn; +use crate::proving_backend::ProvingBackendEssence; +use crate::trie_backend_essence::TrieBackendEssence; +use crate::changes_trie::{AnchorBlockId, Configuration, Storage}; +use crate::changes_trie::storage::TrieBackendAdapter; + +/// Get number of oldest block for which changes trie is not pruned +/// given changes trie configuration, pruning parameter and number of +/// best finalized block. +pub fn oldest_non_pruned_trie( + config: &Configuration, + min_blocks_to_keep: u64, + best_finalized_block: u64, +) -> u64 { + let max_digest_interval = config.max_digest_interval(); + let max_digest_block = best_finalized_block - best_finalized_block % max_digest_interval; + match pruning_range(config, min_blocks_to_keep, max_digest_block) { + Some((_, last_pruned_block)) => last_pruned_block + 1, + None => 1, + } +} /// Prune obslete changes tries. Puning happens at the same block, where highest /// level digest is created. Pruning guarantees to save changes tries for last @@ -46,7 +63,7 @@ pub fn prune, H: Hasher, F: FnMut(H::Out)>( }; // delete changes trie for every block in range - // TODO: limit `max_digest_interval` so that this cycle won't involve huge ranges + // FIXME: limit `max_digest_interval` so that this cycle won't involve huge ranges for block in first..last+1 { let root = match storage.root(current_block, block) { Ok(Some(root)) => root, @@ -136,8 +153,8 @@ mod tests { use std::collections::HashSet; use trie::MemoryDB; use primitives::Blake2Hasher; - use backend::insert_into_memory_db; - use changes_trie::storage::InMemoryStorage; + use crate::backend::insert_into_memory_db; + use crate::changes_trie::storage::InMemoryStorage; use super::*; fn config(interval: u64, levels: u32) -> Configuration { @@ -268,4 +285,23 @@ mod tests { assert_eq!(max_digest_intervals_to_keep(1024, 511), 2); assert_eq!(max_digest_intervals_to_keep(1024, 100), 10); } + + #[test] + fn oldest_non_pruned_trie_works() { + // when digests are not created at all + assert_eq!(oldest_non_pruned_trie(&config(0, 0), 100, 10), 1); + assert_eq!(oldest_non_pruned_trie(&config(0, 0), 100, 110), 11); + + // when only l1 digests are created + assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 50), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 110), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 210), 101); + + // when l2 digests are created + assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 50), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 110), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 210), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 10110), 1); + assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 20110), 10001); + } } diff --git a/core/state-machine/src/changes_trie/storage.rs b/core/state-machine/src/changes_trie/storage.rs index 088b605e9cc16a93f86565fb02599079c99b7f7a..4eb8db0de903543fe23a055fc37fb54bb7c939f7 100644 --- a/core/state-machine/src/changes_trie/storage.rs +++ b/core/state-machine/src/changes_trie/storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,15 +22,15 @@ use trie::DBValue; use heapsize::HeapSizeOf; use trie::MemoryDB; use parking_lot::RwLock; -use changes_trie::{AnchorBlockId, RootsStorage, Storage}; -use trie_backend_essence::TrieBackendStorage; +use crate::changes_trie::{AnchorBlockId, RootsStorage, Storage}; +use crate::trie_backend_essence::TrieBackendStorage; #[cfg(test)] use std::collections::HashSet; #[cfg(test)] -use backend::insert_into_memory_db; +use crate::backend::insert_into_memory_db; #[cfg(test)] -use changes_trie::input::InputPair; +use crate::changes_trie::input::InputPair; /// In-memory implementation of changes trie storage. pub struct InMemoryStorage where H::Out: HeapSizeOf { diff --git a/core/state-machine/src/ext.rs b/core/state-machine/src/ext.rs index 1bcb3fb732b1fc4b14c436de5343f566926f0c0b..abfde7ee7b9e0f8ee1c5b442200af21a5e5f826d 100644 --- a/core/state-machine/src/ext.rs +++ b/core/state-machine/src/ext.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,15 +17,16 @@ //! Conrete externalities implementation. use std::{error, fmt, cmp::Ord}; -use backend::{Backend, Consolidate}; -use changes_trie::{AnchorBlockId, Storage as ChangesTrieStorage, compute_changes_trie_root}; -use {Externalities, OverlayedChanges}; +use log::warn; +use crate::backend::{Backend, Consolidate}; +use crate::changes_trie::{AnchorBlockId, Storage as ChangesTrieStorage, compute_changes_trie_root}; +use crate::{Externalities, OverlayedChanges}; use hash_db::Hasher; use primitives::storage::well_known_keys::is_child_storage_key; -use substrate_trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root, is_child_trie_key_valid}; +use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root, is_child_trie_key_valid}; use heapsize::HeapSizeOf; -const EXT_NOT_ALLOWED_TO_FAIL: &'static str = "Externalities not allowed to fail within runtime"; +const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; /// Errors that can occur when interacting with the externalities. #[derive(Debug, Copy, Clone)] @@ -180,16 +181,25 @@ where H::Out: Ord + HeapSizeOf, { fn storage(&self, key: &[u8]) -> Option> { + let _guard = panic_handler::AbortGuard::new(true); self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) } + fn storage_hash(&self, key: &[u8]) -> Option { + let _guard = panic_handler::AbortGuard::new(true); + self.overlay.storage(key).map(|x| x.map(|x| H::hash(x))).unwrap_or_else(|| + self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) + } + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option> { + let _guard = panic_handler::AbortGuard::new(true); self.overlay.child_storage(storage_key, key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| self.backend.child_storage(storage_key, key).expect(EXT_NOT_ALLOWED_TO_FAIL)) } fn exists_storage(&self, key: &[u8]) -> bool { + let _guard = panic_handler::AbortGuard::new(true); match self.overlay.storage(key) { Some(x) => x.is_some(), _ => self.backend.exists_storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL), @@ -197,6 +207,7 @@ where } fn exists_child_storage(&self, storage_key: &[u8], key: &[u8]) -> bool { + let _guard = panic_handler::AbortGuard::new(true); match self.overlay.child_storage(storage_key, key) { Some(x) => x.is_some(), _ => self.backend.exists_child_storage(storage_key, key).expect(EXT_NOT_ALLOWED_TO_FAIL), @@ -204,6 +215,7 @@ where } fn place_storage(&mut self, key: Vec, value: Option>) { + let _guard = panic_handler::AbortGuard::new(true); if is_child_storage_key(&key) { warn!(target: "trie", "Refuse to directly set child storage key"); return; @@ -214,6 +226,7 @@ where } fn place_child_storage(&mut self, storage_key: Vec, key: Vec, value: Option>) -> bool { + let _guard = panic_handler::AbortGuard::new(true); if !is_child_storage_key(&storage_key) || !is_child_trie_key_valid::(&storage_key) { return false; } @@ -225,6 +238,7 @@ where } fn kill_child_storage(&mut self, storage_key: &[u8]) { + let _guard = panic_handler::AbortGuard::new(true); if !is_child_storage_key(storage_key) || !is_child_trie_key_valid::(storage_key) { return; } @@ -237,6 +251,7 @@ where } fn clear_prefix(&mut self, prefix: &[u8]) { + let _guard = panic_handler::AbortGuard::new(true); if is_child_storage_key(prefix) { warn!(target: "trie", "Refuse to directly clear prefix that is part of child storage key"); return; @@ -254,6 +269,7 @@ where } fn storage_root(&mut self) -> H::Out { + let _guard = panic_handler::AbortGuard::new(true); if let Some((_, ref root)) = self.storage_transaction { return root.clone(); } @@ -277,6 +293,7 @@ where } fn child_storage_root(&mut self, storage_key: &[u8]) -> Option> { + let _guard = panic_handler::AbortGuard::new(true); if !is_child_storage_key(storage_key) || !is_child_trie_key_valid::(storage_key) { return None; } @@ -289,6 +306,7 @@ where } fn storage_changes_root(&mut self, parent: H::Out, parent_num: u64) -> Option { + let _guard = panic_handler::AbortGuard::new(true); let root_and_tx = compute_changes_trie_root::<_, T, H>( self.backend, self.changes_trie_storage.clone(), @@ -297,7 +315,7 @@ where ); let root_and_tx = root_and_tx.map(|(root, changes)| { let mut calculated_root = Default::default(); - let mut mdb = MemoryDB::default(); // TODO: use new for correctness + let mut mdb = MemoryDB::default(); { let mut trie = TrieDBMut::::new(&mut mdb, &mut calculated_root); for (key, value) in changes { @@ -315,13 +333,14 @@ where #[cfg(test)] mod tests { - use codec::Encode; + use hex_literal::{hex, hex_impl}; + use parity_codec::Encode; use primitives::{Blake2Hasher}; use primitives::storage::well_known_keys::EXTRINSIC_INDEX; - use backend::InMemory; - use changes_trie::{Configuration as ChangesTrieConfiguration, + use crate::backend::InMemory; + use crate::changes_trie::{Configuration as ChangesTrieConfiguration, InMemoryStorage as InMemoryChangesTrieStorage}; - use overlayed_changes::OverlayedValue; + use crate::overlayed_changes::OverlayedValue; use super::*; type TestBackend = InMemory; diff --git a/core/state-machine/src/lib.rs b/core/state-machine/src/lib.rs index 5f9757bd55cd6064997c3ea30c65803adbc1d3f6..135c1dfc6be6654f58c714aa0cc3294826fe8330 100644 --- a/core/state-machine/src/lib.rs +++ b/core/state-machine/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,39 +18,27 @@ #![warn(missing_docs)] -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - -#[macro_use] -extern crate log; - -extern crate hash_db; -extern crate substrate_trie; - -extern crate parking_lot; -extern crate heapsize; -#[cfg_attr(test, macro_use)] extern crate substrate_primitives as primitives; -extern crate parity_codec as codec; -extern crate substrate_trie as trie; - -use std::fmt; +use std::{fmt, panic::UnwindSafe, result, marker::PhantomData}; +use log::warn; use hash_db::Hasher; use heapsize::HeapSizeOf; -use codec::Decode; -use primitives::storage::well_known_keys; +use parity_codec::{Decode, Encode}; +use primitives::{storage::well_known_keys, NativeOrEncoded, NeverNativeValue}; pub mod backend; mod changes_trie; mod ext; mod testing; +mod basic; mod overlayed_changes; mod proving_backend; mod trie_backend; mod trie_backend_essence; +use overlayed_changes::OverlayedChangeSet; pub use trie::{TrieMut, TrieDBMut, DBValue, MemoryDB}; pub use testing::TestExternalities; +pub use basic::BasicExternalities; pub use ext::Ext; pub use backend::Backend; pub use changes_trie::{ @@ -59,15 +47,14 @@ pub use changes_trie::{ RootsStorage as ChangesTrieRootsStorage, InMemoryStorage as InMemoryChangesTrieStorage, key_changes, key_changes_proof, key_changes_proof_check, - prune as prune_changes_tries}; + prune as prune_changes_tries, + oldest_non_pruned_trie as oldest_non_pruned_changes_trie +}; pub use overlayed_changes::OverlayedChanges; pub use proving_backend::{create_proof_check_backend, create_proof_check_backend_storage}; pub use trie_backend_essence::{TrieBackendStorage, Storage}; pub use trie_backend::TrieBackend; -/// Default num of pages for the heap -const DEFAULT_HEAP_PAGES :u64 = 1024; - /// State Machine Error bound. /// /// This should reflect WASM error type bound for future compatibility. @@ -96,12 +83,19 @@ impl fmt::Display for ExecutionError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } } +type CallResult = Result, E>; + /// Externalities: pinned to specific active address. pub trait Externalities { - /// Read storage of current contract being called. + /// Read runtime storage. fn storage(&self, key: &[u8]) -> Option>; - /// Read child storage of current contract being called. + /// Get storage value hash. This may be optimized for large values. + fn storage_hash(&self, key: &[u8]) -> Option { + self.storage(key).map(|v| H::hash(&v)) + } + + /// Read child runtime storage. fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option>; /// Set storage entry `key` of current contract being called (effective immediately). @@ -157,7 +151,7 @@ pub trait Externalities { /// Returns None if key provided is not a storage key. This can due to not being started with CHILD_STORAGE_KEY_PREFIX, or the trie implementation regards the key as invalid. fn child_storage_root(&mut self, storage_key: &[u8]) -> Option>; - /// Get the change trie root of the current storage overlay at a block wth given parent. + /// Get the change trie root of the current storage overlay at a block with given parent. fn storage_changes_root(&mut self, parent: H::Out, parent_num: u64) -> Option where H::Out: Ord; } @@ -168,15 +162,16 @@ pub trait CodeExecutor: Sized + Send + Sync { /// Call a given method in the runtime. Returns a tuple of the result (either the output data /// or an execution error) together with a `bool`, which is true if native execution was used. - fn call>( + fn call< + E: Externalities, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe + >( &self, ext: &mut E, - heap_pages: usize, - code: &[u8], method: &str, data: &[u8], - use_native: bool - ) -> (Result, Self::Error>, bool); + use_native: bool, + native_call: Option, + ) -> (CallResult, bool); } /// Strategy for executing a call into the runtime. @@ -188,8 +183,15 @@ pub enum ExecutionStrategy { AlwaysWasm, /// Run with both the wasm and the native variant (if compatible). Report any discrepency as an error. Both, + /// First native, then if that fails or is not possible, wasm. + NativeElseWasm, } +type DefaultHandler = fn( + CallResult, + CallResult, +) -> CallResult; + /// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. #[derive(Clone)] pub enum ExecutionManager { @@ -199,6 +201,8 @@ pub enum ExecutionManager { AlwaysWasm, /// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepency. Both(F), + /// First native, then if that fails or is not possible, wasm. + NativeElseWasm, } impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { @@ -206,194 +210,254 @@ impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { match *s { ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible, ExecutionManager::AlwaysWasm => ExecutionStrategy::AlwaysWasm, + ExecutionManager::NativeElseWasm => ExecutionStrategy::NativeElseWasm, ExecutionManager::Both(_) => ExecutionStrategy::Both, } } } +impl ExecutionStrategy { + /// Gets the corresponding manager for the execution strategy. + pub fn get_manager(self) -> ExecutionManager> { + match self { + ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, + ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, + ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm, + ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { + warn!( + "Consensus error between wasm {:?} and native {:?}. Using wasm.", + wasm_result, + native_result + ); + wasm_result + }), + } + } +} + + /// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn native_when_possible() -> ExecutionManager, E>, Result, E>)->Result, E>> { - ExecutionManager::NativeWhenPossible +pub fn native_when_possible() -> ExecutionManager> { + ExecutionManager::NativeWhenPossible +} + +/// Evaluate to ExecutionManager::NativeElseWasm, without having to figure out the type. +pub fn native_else_wasm() -> ExecutionManager> { + ExecutionManager::NativeElseWasm } /// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn always_wasm() -> ExecutionManager, E>, Result, E>)->Result, E>> { +pub fn always_wasm() -> ExecutionManager> { ExecutionManager::AlwaysWasm } -/// Execute a call using the given state backend, overlayed changes, and call executor. -/// Produces a state-backend-specific "transaction" which can be used to apply the changes -/// to the backing store, such as the disk. -/// -/// On an error, no prospective changes are written to the overlay. -/// -/// Note: changes to code will be in place if this call is made again. For running partial -/// blocks (e.g. a transaction at a time), ensure a different method is used. -pub fn execute( - backend: &B, - changes_trie_storage: Option<&T>, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - strategy: ExecutionStrategy, -) -> Result<(Vec, B::Transaction, Option>), Box> -where - H: Hasher, - Exec: CodeExecutor, - B: Backend, - T: ChangesTrieStorage, - H::Out: Ord + HeapSizeOf, -{ - execute_using_consensus_failure_handler( +/// Creates new substrate state machine. +pub fn new<'a, H, B, T, Exec>( + backend: &'a B, + changes_trie_storage: Option<&'a T>, + overlay: &'a mut OverlayedChanges, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], +) -> StateMachine<'a, H, B, T, Exec> { + StateMachine { backend, changes_trie_storage, overlay, exec, method, call_data, - match strategy { - ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, - ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, - ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { - warn!("Consensus error between wasm {:?} and native {:?}. Using wasm.", wasm_result, native_result); - wasm_result - }), - }, - true, - ) - .map(|(result, storage_tx, changes_tx)| ( - result, - storage_tx.expect("storage_tx is always computed when compute_tx is true; qed"), - changes_tx, - )) + _hasher: PhantomData, + } } -/// Execute a call using the given state backend, overlayed changes, and call executor. -/// Produces a state-backend-specific "transaction" which can be used to apply the changes -/// to the backing store, such as the disk. -/// -/// On an error, no prospective changes are written to the overlay. -/// -/// Note: changes to code will be in place if this call is made again. For running partial -/// blocks (e.g. a transaction at a time), ensure a different method is used. -pub fn execute_using_consensus_failure_handler( - backend: &B, - changes_trie_storage: Option<&T>, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - manager: ExecutionManager, - compute_tx: bool, -) -> Result<(Vec, Option, Option>), Box> -where +/// The substrate state machine. +pub struct StateMachine<'a, H, B, T, Exec> { + backend: &'a B, + changes_trie_storage: Option<&'a T>, + overlay: &'a mut OverlayedChanges, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], + _hasher: PhantomData, +} + +impl<'a, H, B, T, Exec> StateMachine<'a, H, B, T, Exec> where H: Hasher, Exec: CodeExecutor, B: Backend, T: ChangesTrieStorage, H::Out: Ord + HeapSizeOf, - Handler: FnOnce(Result, Exec::Error>, Result, Exec::Error>) -> Result, Exec::Error> { - let strategy: ExecutionStrategy = (&manager).into(); - - // make a copy. - let code = try_read_overlay_value(overlay, backend, well_known_keys::CODE)? - .ok_or_else(|| Box::new(ExecutionError::CodeEntryDoesNotExist) as Box)? - .to_vec(); - - let heap_pages = try_read_overlay_value(overlay, backend, well_known_keys::HEAP_PAGES)? - .and_then(|v| u64::decode(&mut &v[..])).unwrap_or(DEFAULT_HEAP_PAGES) as usize; - - // read changes trie configuration. The reason why we're doing it here instead of the - // `OverlayedChanges` constructor is that we need proofs for this read as a part of - // proof-of-execution on light clients. And the proof is recorded by the backend which - // is created after OverlayedChanges - - let init_overlay = |overlay: &mut OverlayedChanges, final_check: bool| { - let changes_trie_config = try_read_overlay_value( - overlay, - backend, - well_known_keys::CHANGES_TRIE_CONFIG - )?; - set_changes_trie_config(overlay, changes_trie_config, final_check) - }; - init_overlay(overlay, false)?; - - let result = { - let mut orig_prospective = overlay.prospective.clone(); - - let (result, was_native, storage_delta, changes_delta) = { - let ((result, was_native), (storage_delta, changes_delta)) = { - let mut externalities = ext::Ext::new(overlay, backend, changes_trie_storage); - let retval = exec.call( - &mut externalities, - heap_pages, - &code, - method, - call_data, - // attempt to run native first, if we're not directed to run wasm only - strategy != ExecutionStrategy::AlwaysWasm, - ); - let (storage_delta, changes_delta) = if compute_tx { - let (storage_delta, changes_delta) = externalities.transaction(); - (Some(storage_delta), changes_delta) - } else { - (None, None) - }; - (retval, (storage_delta, changes_delta)) - }; - (result, was_native, storage_delta, changes_delta) - }; + /// Execute a call using the given state backend, overlayed changes, and call executor. + /// Produces a state-backend-specific "transaction" which can be used to apply the changes + /// to the backing store, such as the disk. + /// + /// On an error, no prospective changes are written to the overlay. + /// + /// Note: changes to code will be in place if this call is made again. For running partial + /// blocks (e.g. a transaction at a time), ensure a different method is used. + pub fn execute( + &mut self, + strategy: ExecutionStrategy, + ) -> Result<(Vec, B::Transaction, Option>), Box> { + // We are not giving a native call and thus we are sure that the result can never be a native + // value. + self.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + strategy.get_manager(), + true, + None, + ) + .map(|(result, storage_tx, changes_tx)| ( + result.into_encoded(), + storage_tx.expect("storage_tx is always computed when compute_tx is true; qed"), + changes_tx, + )) + } - // run wasm separately if we did run native the first time and we're meant to run both - let (result, storage_delta, changes_delta) = if let (true, ExecutionManager::Both(on_consensus_failure)) = - (was_native, manager) - { - overlay.prospective = orig_prospective.clone(); - - let (wasm_result, wasm_storage_delta, wasm_changes_delta) = { - let ((result, _), (storage_delta, changes_delta)) = { - let mut externalities = ext::Ext::new(overlay, backend, changes_trie_storage); - let retval = exec.call( - &mut externalities, - heap_pages, - &code, - method, - call_data, - false, - ); - let (storage_delta, changes_delta) = if compute_tx { - let (storage_delta, changes_delta) = externalities.transaction(); - (Some(storage_delta), changes_delta) - } else { - (None, None) - }; - (retval, (storage_delta, changes_delta)) - }; - (result, storage_delta, changes_delta) - }; + fn execute_aux( + &mut self, + compute_tx: bool, + use_native: bool, + native_call: Option, + ) -> (CallResult, bool, Option, Option>) where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + { + let mut externalities = ext::Ext::new(self.overlay, self.backend, self.changes_trie_storage); + let (result, was_native) = self.exec.call( + &mut externalities, + self.method, + self.call_data, + use_native, + native_call, + ); + let (storage_delta, changes_delta) = if compute_tx { + let (storage_delta, changes_delta) = externalities.transaction(); + (Some(storage_delta), changes_delta) + } else { + (None, None) + }; + (result, was_native, storage_delta, changes_delta) + } - if (result.is_ok() && wasm_result.is_ok() && result.as_ref().unwrap() == wasm_result.as_ref().unwrap()/* && delta == wasm_delta*/) - || (result.is_err() && wasm_result.is_err()) - { + fn execute_call_with_both_strategy( + &mut self, + compute_tx: bool, + mut native_call: Option, + orig_prospective: OverlayedChangeSet, + on_consensus_failure: Handler, + ) -> (CallResult, Option, Option>) where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + Handler: FnOnce( + CallResult, + CallResult + ) -> CallResult + { + let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + + if was_native { + self.overlay.prospective = orig_prospective.clone(); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + + if (result.is_ok() && wasm_result.is_ok() + && result.as_ref().ok() == wasm_result.as_ref().ok()) + || result.is_err() && wasm_result.is_err() { (result, storage_delta, changes_delta) } else { - // Consensus error. (on_consensus_failure(wasm_result, result), wasm_storage_delta, wasm_changes_delta) } } else { (result, storage_delta, changes_delta) - }; - result.map(move |out| (out, storage_delta, changes_delta)) - }; + } + } - // ensure that changes trie config has not been changed - if result.is_ok() { - init_overlay(overlay, true)?; + fn execute_call_with_native_else_wasm_strategy( + &mut self, + compute_tx: bool, + mut native_call: Option, + orig_prospective: OverlayedChangeSet, + ) -> (CallResult, Option, Option>) where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + { + let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + + if !was_native || result.is_ok() { + (result, storage_delta, changes_delta) + } else { + self.overlay.prospective = orig_prospective.clone(); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + (wasm_result, wasm_storage_delta, wasm_changes_delta) + } } - result.map_err(|e| Box::new(e) as _) + /// Execute a call using the given state backend, overlayed changes, and call executor. + /// Produces a state-backend-specific "transaction" which can be used to apply the changes + /// to the backing store, such as the disk. + /// + /// On an error, no prospective changes are written to the overlay. + /// + /// Note: changes to code will be in place if this call is made again. For running partial + /// blocks (e.g. a transaction at a time), ensure a different method is used. + pub fn execute_using_consensus_failure_handler( + &mut self, + manager: ExecutionManager, + compute_tx: bool, + mut native_call: Option, + ) -> Result<(NativeOrEncoded, Option, Option>), Box> where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + Handler: FnOnce( + CallResult, + CallResult + ) -> CallResult + { + // read changes trie configuration. The reason why we're doing it here instead of the + // `OverlayedChanges` constructor is that we need proofs for this read as a part of + // proof-of-execution on light clients. And the proof is recorded by the backend which + // is created after OverlayedChanges + + let backend = self.backend.clone(); + let init_overlay = |overlay: &mut OverlayedChanges, final_check: bool| { + let changes_trie_config = try_read_overlay_value( + overlay, + backend, + well_known_keys::CHANGES_TRIE_CONFIG + )?; + set_changes_trie_config(overlay, changes_trie_config, final_check) + }; + init_overlay(self.overlay, false)?; + + let result = { + let orig_prospective = self.overlay.prospective.clone(); + + let (result, storage_delta, changes_delta) = match manager { + ExecutionManager::Both(on_consensus_failure) => { + self.execute_call_with_both_strategy(compute_tx, native_call.take(), orig_prospective, on_consensus_failure) + }, + ExecutionManager::NativeElseWasm => { + self.execute_call_with_native_else_wasm_strategy(compute_tx, native_call.take(), orig_prospective) + }, + ExecutionManager::AlwaysWasm => { + let (result, _, storage_delta, changes_delta) = self.execute_aux(compute_tx, false, native_call); + (result, storage_delta, changes_delta) + }, + ExecutionManager::NativeWhenPossible => { + let (result, _was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call); + (result, storage_delta, changes_delta) + }, + }; + result.map(move |out| (out, storage_delta, changes_delta)) + }; + + if result.is_ok() { + init_overlay(self.overlay, true)?; + } + + result.map_err(|e| Box::new(e) as _) + } } /// Prove execution using the given state backend, overlayed changes, and call executor. @@ -438,18 +502,22 @@ where H::Out: Ord + HeapSizeOf, { let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let (result, _, _) = execute_using_consensus_failure_handler::, _, _>( - &proving_backend, - None, + let mut sm = StateMachine { + backend: &proving_backend, + changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, overlay, exec, method, call_data, - native_when_possible(), + _hasher: PhantomData, + }; + let (result, _, _) = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + native_else_wasm(), false, + None, )?; let proof = proving_backend.extract_proof(); - Ok((result, proof)) + Ok((result.into_encoded(), proof)) } /// Check execution proof, generated by `prove_execution` call. @@ -483,16 +551,20 @@ where Exec: CodeExecutor, H::Out: Ord + HeapSizeOf, { - execute_using_consensus_failure_handler::, _, _>( - trie_backend, - None, + let mut sm = StateMachine { + backend: trie_backend, + changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, overlay, exec, method, call_data, - native_when_possible(), + _hasher: PhantomData, + }; + sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + native_else_wasm(), false, - ).map(|(result, _, _)| result) + None, + ).map(|(result, _, _)| result.into_encoded()) } /// Generate storage read proof. @@ -555,7 +627,7 @@ where /// differs from previous OR config decode has failed. pub(crate) fn set_changes_trie_config(overlay: &mut OverlayedChanges, config: Option>, final_check: bool) -> Result<(), Box> { let config = match config { - Some(v) => Some(changes_trie::Configuration::decode(&mut &v[..]) + Some(v) => Some(Decode::decode(&mut &v[..]) .ok_or_else(|| Box::new("Failed to decode changes trie configuration".to_owned()) as Box)?), None => None, }; @@ -590,7 +662,7 @@ where #[cfg(test)] mod tests { use std::collections::HashMap; - use codec::Encode; + use parity_codec::Encode; use overlayed_changes::OverlayedValue; use super::*; use super::backend::InMemory; @@ -599,7 +671,7 @@ mod tests { InMemoryStorage as InMemoryChangesTrieStorage, Configuration as ChangesTrieConfig, }; - use primitives::{Blake2Hasher}; + use primitives::{Blake2Hasher, map}; struct DummyCodeExecutor { change_changes_trie_config: bool, @@ -611,26 +683,41 @@ mod tests { impl CodeExecutor for DummyCodeExecutor { type Error = u8; - fn call>( + fn call, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result>( &self, ext: &mut E, - _heap_pages: usize, - _code: &[u8], _method: &str, _data: &[u8], - use_native: bool - ) -> (Result, Self::Error>, bool) { + use_native: bool, + _native_call: Option, + ) -> (CallResult, bool) { if self.change_changes_trie_config { - ext.place_storage(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), Some(ChangesTrieConfig { - digest_interval: 777, - digest_levels: 333, - }.encode())); + ext.place_storage( + well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), + Some( + ChangesTrieConfig { + digest_interval: 777, + digest_levels: 333, + }.encode() + ) + ); } let using_native = use_native && self.native_available; match (using_native, self.native_succeeds, self.fallback_succeeds) { - (true, true, _) | (false, _, true) => - (Ok(vec![ext.storage(b"value1").unwrap()[0] + ext.storage(b"value2").unwrap()[0]]), using_native), + (true, true, _) | (false, _, true) => { + ( + Ok( + NativeOrEncoded::Encoded( + vec![ + ext.storage(b"value1").unwrap()[0] + + ext.storage(b"value2").unwrap()[0] + ] + ) + ), + using_native + ) + }, _ => (Err(0), using_native), } } @@ -640,7 +727,7 @@ mod tests { #[test] fn execute_works() { - assert_eq!(execute( + assert_eq!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), &mut Default::default(), @@ -652,14 +739,35 @@ mod tests { }, "test", &[], + ).execute( ExecutionStrategy::NativeWhenPossible ).unwrap().0, vec![66]); } + + #[test] + fn execute_works_with_native_else_wasm() { + assert_eq!(new( + &trie_backend::tests::test_trie(), + Some(&InMemoryChangesTrieStorage::new()), + &mut Default::default(), + &DummyCodeExecutor { + change_changes_trie_config: false, + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + ).execute( + ExecutionStrategy::NativeElseWasm + ).unwrap().0, vec![66]); + } + #[test] fn dual_execution_strategy_detects_consensus_failure() { let mut consensus_failed = false; - assert!(execute_using_consensus_failure_handler( + assert!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), &mut Default::default(), @@ -671,12 +779,14 @@ mod tests { }, "test", &[], + ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( ExecutionManager::Both(|we, _ne| { consensus_failed = true; println!("HELLO!"); we }), true, + None, ).is_err()); assert!(consensus_failed); } @@ -776,7 +886,7 @@ mod tests { #[test] fn cannot_change_changes_trie_config() { - assert!(execute( + assert!(new( &trie_backend::tests::test_trie(), Some(&InMemoryChangesTrieStorage::new()), &mut Default::default(), @@ -788,7 +898,27 @@ mod tests { }, "test", &[], + ).execute( ExecutionStrategy::NativeWhenPossible ).is_err()); } + + #[test] + fn cannot_change_changes_trie_config_with_native_else_wasm() { + assert!(new( + &trie_backend::tests::test_trie(), + Some(&InMemoryChangesTrieStorage::new()), + &mut Default::default(), + &DummyCodeExecutor { + change_changes_trie_config: true, + native_available: false, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + ).execute( + ExecutionStrategy::NativeElseWasm + ).is_err()); + } } diff --git a/core/state-machine/src/overlayed_changes.rs b/core/state-machine/src/overlayed_changes.rs index 29ff7262da2e8f74316144acffb743a0b7b73b3d..865ee86105aea729e2e8c56c60b31cdf81609c4f 100644 --- a/core/state-machine/src/overlayed_changes.rs +++ b/core/state-machine/src/overlayed_changes.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,8 +18,8 @@ #[cfg(test)] use std::iter::FromIterator; use std::collections::{HashMap, HashSet}; -use codec::Decode; -use changes_trie::{NO_EXTRINSIC_INDEX, Configuration as ChangesTrieConfig}; +use parity_codec::Decode; +use crate::changes_trie::{NO_EXTRINSIC_INDEX, Configuration as ChangesTrieConfig}; use primitives::storage::well_known_keys::EXTRINSIC_INDEX; /// The overlayed changes to state to be queried on top of the backend. @@ -44,7 +44,7 @@ pub struct OverlayedValue { /// Current value. None if value has been deleted. pub value: Option>, /// The set of extinsic indices where the values has been changed. - /// Is filled only if runtime ahs announced changes trie support. + /// Is filled only if runtime has announced changes trie support. pub extrinsics: Option>, } @@ -276,7 +276,7 @@ impl OverlayedChanges { /// Inserts storage entry responsible for current extrinsic index. #[cfg(test)] pub(crate) fn set_extrinsic_index(&mut self, extrinsic_index: u32) { - use codec::Encode; + use parity_codec::Encode; self.prospective.top.insert(EXTRINSIC_INDEX.to_vec(), OverlayedValue { value: Some(extrinsic_index.encode()), extrinsics: None, @@ -309,12 +309,13 @@ impl From>> for OverlayedValue { #[cfg(test)] mod tests { + use hex_literal::{hex, hex_impl}; use primitives::{Blake2Hasher, H256}; use primitives::storage::well_known_keys::EXTRINSIC_INDEX; - use backend::InMemory; - use changes_trie::InMemoryStorage as InMemoryChangesTrieStorage; - use ext::Ext; - use {Externalities}; + use crate::backend::InMemory; + use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage; + use crate::ext::Ext; + use crate::Externalities; use super::*; fn strip_extrinsic_index(map: &HashMap, OverlayedValue>) -> HashMap, OverlayedValue> { diff --git a/core/state-machine/src/proving_backend.rs b/core/state-machine/src/proving_backend.rs index 85afc0b3dc24e01640f987cdb60a8c4906f01c75..81d68352c8699bd20d493c40fd972f0b7b10e52b 100644 --- a/core/state-machine/src/proving_backend.rs +++ b/core/state-machine/src/proving_backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,13 +17,14 @@ //! Proving state machine backend. use std::cell::RefCell; +use log::debug; use hash_db::Hasher; use heapsize::HeapSizeOf; use hash_db::HashDB; use trie::{Recorder, MemoryDB, TrieError, default_child_trie_root, read_trie_value_with, read_child_trie_value_with, record_all_keys}; -use trie_backend::TrieBackend; -use trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}; -use {Error, ExecutionError, Backend}; +use crate::trie_backend::TrieBackend; +use crate::trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}; +use crate::{Error, ExecutionError, Backend}; /// Patricia trie-based backend essence which also tracks all touched storage trie values. /// These can be sent to remote node and used as a proof of execution. @@ -47,7 +48,7 @@ impl<'a, S, H> ProvingBackendEssence<'a, S, H> let map_e = |e| format!("Trie lookup error: {}", e); - read_trie_value_with(&eph, self.backend.root(), key, &mut *self.proof_recorder).map_err(map_e) + read_trie_value_with::>(&eph, self.backend.root(), key, &mut *self.proof_recorder).map_err(map_e) } pub fn child_storage(&mut self, storage_key: &[u8], key: &[u8]) -> Result>, String> { @@ -73,7 +74,7 @@ impl<'a, S, H> ProvingBackendEssence<'a, S, H> let mut iter = move || -> Result<(), Box>> { let root = self.backend.root(); - record_all_keys::(&eph, root, &mut *self.proof_recorder) + record_all_keys::(&eph, root, &mut *self.proof_recorder) }; if let Err(e) = iter() { @@ -146,6 +147,10 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> self.backend.pairs() } + fn keys(&self, prefix: &Vec) -> Vec> { + self.backend.keys(prefix) + } + fn storage_root(&self, delta: I) -> (H::Out, MemoryDB) where I: IntoIterator, Option>)> { @@ -191,7 +196,7 @@ where H: Hasher, H::Out: HeapSizeOf, { - let mut db = MemoryDB::default(); // TODO: use new for correctness + let mut db = MemoryDB::default(); for item in proof { db.insert(&item); } @@ -200,8 +205,8 @@ where #[cfg(test)] mod tests { - use backend::{InMemory}; - use trie_backend::tests::test_trie; + use crate::backend::{InMemory}; + use crate::trie_backend::tests::test_trie; use super::*; use primitives::{Blake2Hasher}; diff --git a/core/state-machine/src/testing.rs b/core/state-machine/src/testing.rs index 876a190a966a93ef7bad9ff3fbc1c295dd95247b..216b3ebdc25ffb2ac743ca64a47f15a7a210af36 100644 --- a/core/state-machine/src/testing.rs +++ b/core/state-machine/src/testing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,9 +21,10 @@ use std::iter::FromIterator; use hash_db::Hasher; use heapsize::HeapSizeOf; use trie::trie_root; -use backend::InMemory; -use changes_trie::{compute_changes_trie_root, InMemoryStorage as ChangesTrieInMemoryStorage, AnchorBlockId}; -use primitives::storage::well_known_keys::CHANGES_TRIE_CONFIG; +use crate::backend::InMemory; +use crate::changes_trie::{compute_changes_trie_root, InMemoryStorage as ChangesTrieInMemoryStorage, AnchorBlockId}; +use primitives::storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES}; +use parity_codec::Encode; use super::{Externalities, OverlayedChanges}; /// Simple HashMap-based Externalities impl. @@ -31,11 +32,17 @@ pub struct TestExternalities where H::Out: HeapSizeOf { inner: HashMap, Vec>, changes_trie_storage: ChangesTrieInMemoryStorage, changes: OverlayedChanges, + code: Option>, } impl TestExternalities where H::Out: HeapSizeOf { /// Create a new instance of `TestExternalities` pub fn new(inner: HashMap, Vec>) -> Self { + Self::new_with_code(&[], inner) + } + + /// Create a new instance of `TestExternalities` + pub fn new_with_code(code: &[u8], mut inner: HashMap, Vec>) -> Self { let mut overlay = OverlayedChanges::default(); super::set_changes_trie_config( &mut overlay, @@ -43,10 +50,13 @@ impl TestExternalities where H::Out: HeapSizeOf { false, ).expect("changes trie configuration is correct in test env; qed"); + inner.insert(HEAP_PAGES.to_vec(), 8u64.encode()); + TestExternalities { inner, changes_trie_storage: ChangesTrieInMemoryStorage::new(), changes: overlay, + code: Some(code.to_vec()), } } @@ -71,9 +81,7 @@ impl PartialEq for TestExternalities where H::Out: HeapSizeOf { impl FromIterator<(Vec, Vec)> for TestExternalities where H::Out: HeapSizeOf { fn from_iter, Vec)>>(iter: I) -> Self { let mut t = Self::new(Default::default()); - for i in iter { - t.inner.insert(i.0, i.1); - } + t.inner.extend(iter); t } } @@ -94,13 +102,17 @@ impl From< HashMap, Vec> > for TestExternalities where inner: hashmap, changes_trie_storage: ChangesTrieInMemoryStorage::new(), changes: Default::default(), + code: None, } } } impl Externalities for TestExternalities where H::Out: Ord + HeapSizeOf { fn storage(&self, key: &[u8]) -> Option> { - self.inner.get(key).map(|x| x.to_vec()) + match key { + CODE => self.code.clone(), + _ => self.inner.get(key).cloned(), + } } fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> Option> { @@ -109,9 +121,14 @@ impl Externalities for TestExternalities where H::Out: Ord + He fn place_storage(&mut self, key: Vec, maybe_value: Option>) { self.changes.set_storage(key.clone(), maybe_value.clone()); - match maybe_value { - Some(value) => { self.inner.insert(key, value); } - None => { self.inner.remove(&key); } + match key.as_ref() { + CODE => self.code = maybe_value, + _ => { + match maybe_value { + Some(value) => { self.inner.insert(key, value); } + None => { self.inner.remove(&key); } + } + } } } @@ -150,6 +167,7 @@ impl Externalities for TestExternalities where H::Out: Ord + He mod tests { use super::*; use primitives::{Blake2Hasher, H256}; + use hex_literal::{hex, hex_impl}; #[test] fn commit_should_work() { @@ -157,7 +175,17 @@ mod tests { ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); - const ROOT: [u8; 32] = hex!("0b41e488cccbd67d1f1089592c2c235f5c5399b053f7fe9152dd4b5f279914cd"); + const ROOT: [u8; 32] = hex!("0b33ed94e74e0f8e92a55923bece1ed02d16cf424e124613ddebc53ac3eeeabe"); assert_eq!(ext.storage_root(), H256::from(ROOT)); } + + #[test] + fn set_and_retrieve_code() { + let mut ext = TestExternalities::::default(); + + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); + + assert_eq!(&ext.storage(CODE).unwrap(), &code); + } } diff --git a/core/state-machine/src/trie_backend.rs b/core/state-machine/src/trie_backend.rs index f29608b5d136d1b92ed4910a3f9f213a5f197ac4..5de6c8837b8e3403be8de706c6d1e71a7902b97d 100644 --- a/core/state-machine/src/trie_backend.rs +++ b/core/state-machine/src/trie_backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,11 +16,12 @@ //! Trie-based state machine backend. +use log::{warn, debug}; use hash_db::Hasher; use heapsize::HeapSizeOf; use trie::{TrieDB, TrieError, Trie, MemoryDB, delta_trie_root, default_child_trie_root, child_delta_trie_root}; -use trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral}; -use {Backend}; +use crate::trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral}; +use crate::Backend; /// Patricia trie-based backend. Transaction type is an overlay of changes to commit. pub struct TrieBackend, H: Hasher> { @@ -82,7 +83,7 @@ impl, H: Hasher> Backend for TrieBackend where } fn pairs(&self) -> Vec<(Vec, Vec)> { - let mut read_overlay = MemoryDB::default(); // TODO: use new for correctness + let mut read_overlay = MemoryDB::default(); let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay); let collect_all = || -> Result<_, Box>> { @@ -105,6 +106,26 @@ impl, H: Hasher> Backend for TrieBackend where } } + fn keys(&self, prefix: &Vec) -> Vec> { + let mut read_overlay = MemoryDB::default(); + let eph = Ephemeral::new(self.essence.backend_storage(), &mut read_overlay); + + let collect_all = || -> Result<_, Box>> { + let trie = TrieDB::::new(&eph, self.essence.root())?; + let mut v = Vec::new(); + for x in trie.iter()? { + let (key, _) = x?; + if key.starts_with(prefix) { + v.push(key.to_vec()); + } + } + + Ok(v) + }; + + collect_all().map_err(|e| debug!(target: "trie", "Error extracting trie keys: {}", e)).unwrap_or_default() + } + fn storage_root(&self, delta: I) -> (H::Out, MemoryDB) where I: IntoIterator, Option>)> { @@ -117,7 +138,7 @@ impl, H: Hasher> Backend for TrieBackend where &mut write_overlay, ); - match delta_trie_root::(&mut eph, root, delta) { + match delta_trie_root::(&mut eph, root, delta) { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } @@ -148,7 +169,7 @@ impl, H: Hasher> Backend for TrieBackend where &mut write_overlay, ); - match child_delta_trie_root::(storage_key, &mut eph, root.clone(), delta) { + match child_delta_trie_root::(storage_key, &mut eph, root.clone(), delta) { Ok(ret) => root = ret, Err(e) => warn!(target: "trie", "Failed to write to trie: {}", e), } @@ -173,7 +194,7 @@ pub mod tests { fn test_db() -> (MemoryDB, H256) { let mut root = H256::default(); - let mut mdb = MemoryDB::::default(); // TODO: use new() to be more correct + let mut mdb = MemoryDB::::default(); { let mut trie = TrieDBMut::new(&mut mdb, &mut root); trie.insert(b"key", b"value").expect("insert failed"); @@ -210,7 +231,7 @@ pub mod tests { #[test] fn pairs_are_empty_on_empty_storage() { assert!(TrieBackend::, Blake2Hasher>::new( - MemoryDB::default(), // TODO: use new() to be more correct + MemoryDB::default(), Default::default(), ).pairs().is_empty()); } diff --git a/core/state-machine/src/trie_backend_essence.rs b/core/state-machine/src/trie_backend_essence.rs index cd5c0469414e64900266f4d09af61b28d6a31c74..b429e7aa046194aa1ec0d0f2b993a73c2caf2feb 100644 --- a/core/state-machine/src/trie_backend_essence.rs +++ b/core/state-machine/src/trie_backend_essence.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,13 +17,13 @@ //! Trie-based state machine backend essence used to read values //! from storage. -use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; +use log::{debug, warn}; use hash_db::{self, Hasher}; use heapsize::HeapSizeOf; use trie::{TrieDB, Trie, MemoryDB, DBValue, TrieError, default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie}; -use changes_trie::Storage as ChangesTrieStorage; +use crate::changes_trie::Storage as ChangesTrieStorage; /// Patricia trie-based storage trait. pub trait Storage: Send + Sync { @@ -105,7 +105,7 @@ impl, H: Hasher> TrieBackendEssence where H::Out: overlay: &mut read_overlay, }; - if let Err(e) = for_keys_in_child_trie::(storage_key, &eph, &root, f) { + if let Err(e) = for_keys_in_child_trie::>(storage_key, &eph, &root, f) { debug!(target: "trie", "Error while iterating child storage: {}", e); } } @@ -148,6 +148,17 @@ pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { overlay: &'a mut MemoryDB, } +impl<'a, + S: 'a + TrieBackendStorage, + H: 'a + Hasher +> hash_db::AsPlainDB + for Ephemeral<'a, S, H> + where H::Out: HeapSizeOf +{ + fn as_plain_db<'b>(&'b self) -> &'b (hash_db::PlainDB + 'b) { self } + fn as_plain_db_mut<'b>(&'b mut self) -> &'b mut (hash_db::PlainDB + 'b) { self } +} + impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher @@ -171,50 +182,97 @@ impl<'a, S: TrieBackendStorage, H: Hasher> Ephemeral<'a, S, H> { impl<'a, S: 'a + TrieBackendStorage, H: Hasher -> hash_db::HashDB +> hash_db::PlainDB for Ephemeral<'a, S, H> where H::Out: HeapSizeOf { - fn keys(&self) -> HashMap { - self.overlay.keys() // TODO: iterate backing - } - fn get(&self, key: &H::Out) -> Option { - match self.overlay.raw(key) { - Some((val, i)) => { - if i <= 0 { + if let Some(val) = hash_db::PlainDB::get(self.overlay, key) { + Some(val) + } else { + match self.storage.get(&key) { + Ok(x) => x, + Err(e) => { + warn!(target: "trie", "Failed to read from DB: {}", e); None - } else { - Some(val.clone()) - } + }, } - None => match self.storage.get(&key) { + } + } + + fn contains(&self, key: &H::Out) -> bool { + hash_db::PlainDB::get(self, key).is_some() + } + + fn emplace(&mut self, key: H::Out, value: DBValue) { + hash_db::PlainDB::emplace(self.overlay, key, value) + } + + fn remove(&mut self, key: &H::Out) { + hash_db::PlainDB::remove(self.overlay, key) + } +} + +impl<'a, + S: 'a + TrieBackendStorage, + H: Hasher +> hash_db::PlainDBRef + for Ephemeral<'a, S, H> + where H::Out: HeapSizeOf +{ + fn get(&self, key: &H::Out) -> Option { hash_db::PlainDB::get(self, key) } + fn contains(&self, key: &H::Out) -> bool { hash_db::PlainDB::contains(self, key) } +} + +impl<'a, + S: 'a + TrieBackendStorage, + H: Hasher +> hash_db::HashDB + for Ephemeral<'a, S, H> + where H::Out: HeapSizeOf +{ + fn get(&self, key: &H::Out) -> Option { + if let Some(val) = hash_db::HashDB::get(self.overlay, key) { + Some(val) + } else { + match self.storage.get(&key) { Ok(x) => x, Err(e) => { warn!(target: "trie", "Failed to read from DB: {}", e); None }, - }, + } } } fn contains(&self, key: &H::Out) -> bool { - self.get(key).is_some() + hash_db::HashDB::get(self, key).is_some() } fn insert(&mut self, value: &[u8]) -> H::Out { - self.overlay.insert(value) + hash_db::HashDB::insert(self.overlay, value) } fn emplace(&mut self, key: H::Out, value: DBValue) { - self.overlay.emplace(key, value) + hash_db::HashDB::emplace(self.overlay, key, value) } fn remove(&mut self, key: &H::Out) { - self.overlay.remove(key) + hash_db::HashDB::remove(self.overlay, key) } } +impl<'a, + S: 'a + TrieBackendStorage, + H: Hasher +> hash_db::HashDBRef + for Ephemeral<'a, S, H> + where H::Out: HeapSizeOf +{ + fn get(&self, key: &H::Out) -> Option { hash_db::HashDB::get(self, key) } + fn contains(&self, key: &H::Out) -> bool { hash_db::HashDB::contains(self, key) } +} + /// Key-value pairs storage that is used by trie backend essence. pub trait TrieBackendStorage: Send + Sync { /// Get the value stored at key. @@ -231,7 +289,7 @@ impl TrieBackendStorage for Arc> { // This implementation is used by test storage trie clients. impl TrieBackendStorage for MemoryDB { fn get(&self, key: &H::Out) -> Result, String> { - Ok(>::get(self, key)) + Ok(hash_db::PlainDB::get(self, key)) } } diff --git a/core/telemetry/Cargo.toml b/core/telemetry/Cargo.toml index c74cb956d7ed2d9185fea51d9688a8c2f60c13bb..0553c4f16b7571948897a7808335497412f08a5f 100644 --- a/core/telemetry/Cargo.toml +++ b/core/telemetry/Cargo.toml @@ -1,13 +1,17 @@ [package] name = "substrate-telemetry" -version = "0.3.0" +version = "0.3.1" authors = ["Parity Technologies "] description = "Telemetry utils" +edition = "2018" [dependencies] -parking_lot = "0.4" +parking_lot = "0.7.1" lazy_static = "1.0" log = "0.4" +rand = "0.6" +serde = "1.0.81" +serde_derive = "1.0" slog = "^2" slog-json = "^2" slog-async = "^2" diff --git a/core/telemetry/src/lib.rs b/core/telemetry/src/lib.rs index 927994cca5172e4d7e5c967bea51193783f5d07b..21289459c624173c0f5b65ef90b43e12c8bda489 100644 --- a/core/telemetry/src/lib.rs +++ b/core/telemetry/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,28 +21,26 @@ //! server (if there is one). We use the async drain adapter of `slog` //! so that the logging thread doesn't get held up at all. -extern crate parking_lot; -extern crate ws; -extern crate slog_async; -extern crate slog_json; -#[macro_use] -extern crate log; -#[macro_use(o)] -extern crate slog; -extern crate slog_scope; - use std::{io, time, thread}; use std::sync::Arc; use parking_lot::Mutex; -use slog::Drain; +use slog::{Drain, o}; +use log::trace; +use rand::{thread_rng, Rng}; pub use slog_scope::with_logger; +pub use slog; +use serde_derive::{Serialize, Deserialize}; +use slog::OwnedKVList; +use slog::Record; +use core::result; /// Configuration for telemetry. pub struct TelemetryConfig { - /// URL of the telemetry WebSocket server. - pub url: String, - /// What do do when we connect to the server. - pub on_connect: Box, + /// Collection of telemetry WebSocket servers with a corresponding verbosity level. + pub endpoints: TelemetryEndpoints, + /// What do do when we connect to the servers. + /// Note that this closure is executed each time we connect to a telemetry endpoint. + pub on_connect: Box, } /// Telemetry service guard. @@ -51,66 +49,165 @@ pub type Telemetry = slog_scope::GlobalLoggerGuard; /// Size of the channel for passing messages to telemetry thread. const CHANNEL_SIZE: usize = 262144; +/// Log levels. +pub const SUBSTRATE_DEBUG: &str = "9"; +pub const SUBSTRATE_INFO: &str = "0"; + +pub const CONSENSUS_TRACE: &str = "9"; +pub const CONSENSUS_DEBUG: &str = "5"; +pub const CONSENSUS_WARN: &str = "4"; +pub const CONSENSUS_INFO: &str = "3"; + +/// Multiply logging to all drains. This is similar to `slog::Duplicate`, which is +/// limited to two drains though and doesn't support dynamic nesting at runtime. +#[derive(Debug, Clone)] +pub struct Multiply (pub Vec>); + +impl Multiply { + pub fn new(v: Vec>) -> Self { + Multiply(v) + } +} + +impl Drain for Multiply { + type Ok = Vec; + type Err = Vec; + + fn log(&self, record: &Record, logger_values: &OwnedKVList) -> result::Result { + let mut oks = Vec::new(); + let mut errs = Vec::new(); + + self.0.iter().for_each(|l| { + let res: Result<::Ok, ::Err> = (*l).log(record, logger_values); + match res { + Ok(o) => oks.push(o), + Err(e) => errs.push(e), + } + }); + + if !errs.is_empty() { + result::Result::Err(errs) + } else { + result::Result::Ok(oks) + } + } +} + /// Initialise telemetry. pub fn init_telemetry(config: TelemetryConfig) -> slog_scope::GlobalLoggerGuard { - let writer = TelemetryWriter::new(); - let out_sync = writer.out.clone(); - let log = slog::Logger::root( - slog_async::Async::new( - slog_json::Json::default(writer).fuse() - ).chan_size(CHANNEL_SIZE) + let mut endpoint_drains: Vec>> = Vec::new(); + let mut out_syncs = Vec::new(); + + // Set up a filter/drain for each endpoint + config.endpoints.0.iter().for_each(|(url, verbosity)| { + let writer = TelemetryWriter::new(Arc::new(url.to_owned())); + let out_sync = writer.out.clone(); + out_syncs.push(out_sync); + + let until_verbosity = *verbosity; + let filter = slog::Filter( + slog_json::Json::default(writer).fuse(), + move |rec| { + let tag = rec.tag().parse::() + .expect("`telemetry!` macro requires tag."); + tag <= until_verbosity + }); + + let filter = Box::new(filter) as Box>; + endpoint_drains.push(filter); + }); + + // Set up logging to all endpoints + let drain = slog_async::Async::new(Multiply::new(endpoint_drains).fuse()); + let root = slog::Logger::root(drain.chan_size(CHANNEL_SIZE) .overflow_strategy(slog_async::OverflowStrategy::DropAndReport) .build().fuse(), o!() ); - let logger_guard = slog_scope::set_global_logger(log); - - thread::spawn(move || { - loop { - trace!(target: "telemetry", "Connecting to Telemetry..."); - let _ = ws::connect(config.url.as_str(), |out| Connection::new(out, &*out_sync, &config)); - - thread::sleep(time::Duration::from_millis(5000)); - } + let logger_guard = slog_scope::set_global_logger(root); + + // Spawn a thread for each endpoint + let on_connect = Arc::new(config.on_connect); + config.endpoints.0.into_iter().for_each(|(url, verbosity)| { + let inner_verbosity = Arc::new(verbosity.to_owned()); + let inner_on_connect = Arc::clone(&on_connect); + + let out_sync = out_syncs.remove(0); + let out_sync = Arc::clone(&out_sync); + + thread::spawn(move || { + loop { + let on_connect = Arc::clone(&inner_on_connect); + let out_sync = Arc::clone(&out_sync); + let verbosity = Arc::clone(&inner_verbosity); + + trace!(target: "telemetry", + "Connecting to Telemetry at {} with verbosity {}", url, Arc::clone(&verbosity)); + + let _ = ws::connect(url.to_owned(), + |out| { + Connection::new(out, Arc::clone(&out_sync), Arc::clone(&on_connect), url.clone()) + }); + + // Sleep for a random time between 5-10 secs. If there are general connection + // issues not all threads should be synchronized in their re-connection time. + let random_sleep = thread_rng().gen_range(0, 5); + thread::sleep(time::Duration::from_secs(5) + time::Duration::from_secs(random_sleep)); + } + }); }); return logger_guard; } -/// Exactly equivalent to `slog_scope::info`, provided as a convenience. +/// Translates to `slog_scope::info`, but contains an additional verbosity +/// parameter which the log record is tagged with. Additionally the verbosity +/// parameter is added to the record as a key-value pair. #[macro_export] macro_rules! telemetry { - ( $($t:tt)* ) => { $crate::with_logger(|l| slog_info!(l, $($t)* )) } + ( $a:expr; $b:expr; $( $t:tt )* ) => { + $crate::with_logger(|l| { + $crate::slog::slog_info!(l, #$a, $b; "verbosity" => stringify!($a), $($t)* ) + }) + } } -struct Connection<'a> { +struct Connection { out: ws::Sender, - out_sync: &'a Mutex>, - config: &'a TelemetryConfig, + out_sync: Arc>>, + on_connect: Arc>, + url: String, } -impl<'a> Connection<'a> { - fn new(out: ws::Sender, out_sync: &'a Mutex>, config: &'a TelemetryConfig) -> Self { +impl Connection { + fn new( + out: ws::Sender, + out_sync: Arc>>, + on_connect: Arc>, + url: String + ) -> Self { Connection { out, out_sync, - config, + on_connect, + url, } } } -impl<'a> ws::Handler for Connection<'a> { +impl ws::Handler for Connection { fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> { - trace!(target: "telemetry", "Connected!"); + trace!(target: "telemetry", "Connected to {}!", self.url); *self.out_sync.lock() = Some(self.out.clone()); - (self.config.on_connect)(); + (self.on_connect)(); Ok(()) } fn on_close(&mut self, code: ws::CloseCode, reason: &str) { *self.out_sync.lock() = None; - trace!(target: "telemetry", "Connection closing due to ({:?}) {}", code, reason); + trace!(target: "telemetry", "Connection to {} closing due to ({:?}) {}", + self.url, code, reason); } fn on_error(&mut self, _: ws::Error) { @@ -125,15 +222,17 @@ impl<'a> ws::Handler for Connection<'a> { struct TelemetryWriter { buffer: Vec, out: Arc>>, + url: Arc, } impl TelemetryWriter { - fn new() -> Self { + fn new(url: Arc) -> Self { let out = Arc::new(Mutex::new(None)); TelemetryWriter { buffer: Vec::new(), out, + url, } } } @@ -163,11 +262,11 @@ impl io::Write for TelemetryWriter { let error = if let Some(ref mut o) = *out { let r = o.send(s); - trace!(target: "telemetry", "Sent to telemetry: {} -> {:?}", s, r); + trace!(target: "telemetry", "Sent to telemetry {}: {} -> {:?}", self.url, s, r); r.is_err() } else { - trace!(target: "telemetry", "Telemetry socket closed, failed to send: {}", s); + trace!(target: "telemetry", "Telemetry socket closed to {}, failed to send: {}", self.url, s); false }; @@ -179,3 +278,12 @@ impl io::Write for TelemetryWriter { Ok(()) } } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TelemetryEndpoints (Vec<(String, u8)>); + +impl TelemetryEndpoints { + pub fn new(endpoints: Vec<(String, u8)>) -> Self { + TelemetryEndpoints(endpoints) + } +} diff --git a/core/test-client/Cargo.toml b/core/test-client/Cargo.toml index 9f282f9db3f60dd232c806fa43b9e8fcfa8b4b0a..5049b2ff9fd62d5511b246a0a90bf25d6be8bd40 100644 --- a/core/test-client/Cargo.toml +++ b/core/test-client/Cargo.toml @@ -2,14 +2,17 @@ name = "substrate-test-client" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -substrate-client = { path = "../client" } -parity-codec = "2.1" -substrate-executor = { path = "../executor" } -substrate-consensus-common = { path = "../consensus/common" } -substrate-keyring = { path = "../../core/keyring" } -substrate-primitives = { path = "../primitives" } -substrate-state-machine = { path = "../state-machine" } -substrate-test-runtime = { path = "../test-runtime" } -sr-primitives = { path = "../sr-primitives" } +client = { package = "substrate-client", path = "../client" } +client-db = { package = "substrate-client-db", path = "../client/db", features = ["test-helpers"] } +futures = { version = "0.1.17" } +parity-codec = "3.2" +executor = { package = "substrate-executor", path = "../executor" } +consensus = { package = "substrate-consensus-common", path = "../consensus/common" } +keyring = { package = "substrate-keyring", path = "../../core/keyring" } +primitives = { package = "substrate-primitives", path = "../primitives" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +runtime = { package = "substrate-test-runtime", path = "../test-runtime" } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } diff --git a/core/test-client/src/block_builder_ext.rs b/core/test-client/src/block_builder_ext.rs index 651559114af88fb22bf692cf9709f59125f65b95..e427b5789291e705605b553332e0e7f21abffcd7 100644 --- a/core/test-client/src/block_builder_ext.rs +++ b/core/test-client/src/block_builder_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,8 @@ //! Block Builder extensions for tests. -use codec; use client; -use keyring; +use super::AccountKeyring; use runtime; use runtime_primitives::traits::ProvideRuntimeApi; use client::block_builder::api::BlockBuilder; @@ -29,9 +28,9 @@ pub trait BlockBuilderExt { fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error>; } -impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime::Block, (), A> where +impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime::Block, A> where A: ProvideRuntimeApi + client::blockchain::HeaderBackend + 'a, - A::Api: BlockBuilder + A::Api: BlockBuilder { fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error> { self.push(sign_tx(transfer)) @@ -39,6 +38,8 @@ impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime: } fn sign_tx(transfer: runtime::Transfer) -> runtime::Extrinsic { - let signature = keyring::Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&codec::Encode::encode(&transfer)).into(); - runtime::Extrinsic { transfer, signature } + let signature = AccountKeyring::from_public(&transfer.from) + .unwrap() + .sign(&parity_codec::Encode::encode(&transfer)); + runtime::Extrinsic::Transfer(transfer, signature) } diff --git a/core/test-client/src/client_ext.rs b/core/test-client/src/client_ext.rs index d4ca6361ee3ac64b31265528351495eb5f745084..511b55ff622806cdd080e9bc9b39295e867dee93 100644 --- a/core/test-client/src/client_ext.rs +++ b/core/test-client/src/client_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ //! Client extension for tests. use client::{self, Client}; -use consensus::{ImportBlock, BlockImport, BlockOrigin}; +use consensus::{ImportBlock, BlockImport, BlockOrigin, Error as ConsensusError, ForkChoiceStrategy}; use runtime_primitives::Justification; use runtime_primitives::generic::BlockId; use primitives::Blake2Hasher; @@ -27,11 +27,11 @@ use runtime; pub trait TestClient: Sized { /// Import block to the chain. No finality. fn import(&self, origin: BlockOrigin, block: runtime::Block) - -> client::error::Result<()>; + -> Result<(), ConsensusError>; /// Import block with justification, finalizes block. fn import_justified(&self, origin: BlockOrigin, block: runtime::Block, justification: Justification) - -> client::error::Result<()>; + -> Result<(), ConsensusError>; /// Finalize a block. fn finalize_block(&self, id: BlockId, justification: Option) -> client::error::Result<()>; @@ -44,10 +44,10 @@ impl TestClient for Client where B: client::backend::Backend, E: client::CallExecutor, - Self: BlockImport, + Self: BlockImport, { fn import(&self, origin: BlockOrigin, block: runtime::Block) - -> client::error::Result<()> + -> Result<(), ConsensusError> { let import = ImportBlock { origin, @@ -57,13 +57,14 @@ impl TestClient for Client body: Some(block.extrinsics), finalized: false, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ()) } fn import_justified(&self, origin: BlockOrigin, block: runtime::Block, justification: Justification) - -> client::error::Result<()> + -> Result<(), ConsensusError> { let import = ImportBlock { origin, @@ -73,6 +74,7 @@ impl TestClient for Client body: Some(block.extrinsics), finalized: true, auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, }; self.import_block(import, None).map(|_| ()) diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index 66b057350a2172bc9901886ad3240a55e47f8bfb..6eb6db4d4bcea62dfe577d28db5f57718d277043 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,46 +18,48 @@ #![warn(missing_docs)] -extern crate parity_codec as codec; -extern crate substrate_primitives as primitives; -extern crate sr_primitives as runtime_primitives; -#[macro_use] extern crate substrate_executor as executor; - -pub extern crate substrate_client as client; -pub extern crate substrate_keyring as keyring; -pub extern crate substrate_test_runtime as runtime; -pub extern crate substrate_consensus_common as consensus; -extern crate substrate_state_machine as state_machine; - pub mod client_ext; pub mod trait_tests; mod block_builder_ext; pub use client_ext::TestClient; pub use block_builder_ext::BlockBuilderExt; +pub use client; +pub use client::ExecutionStrategies; pub use client::blockchain; pub use client::backend; pub use executor::NativeExecutor; +pub use runtime; +pub use consensus; +pub use keyring::{AuthorityKeyring, AccountKeyring}; use std::sync::Arc; +use futures::future::FutureResult; use primitives::Blake2Hasher; -use runtime_primitives::StorageMap; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT}; +use runtime_primitives::StorageOverlay; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor}; use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; -use keyring::Keyring; +use state_machine::ExecutionStrategy; +use client::LocalCallExecutor; mod local_executor { #![allow(missing_docs)] - use super::runtime; - // TODO: change the macro and pass in the `BlakeHasher` that dispatch needs from here instead - native_executor_instance!(pub LocalExecutor, runtime::api::dispatch, runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); + use runtime; + use executor::native_executor_instance; + // FIXME #1576 change the macro and pass in the `BlakeHasher` that dispatch needs from here instead + native_executor_instance!( + pub LocalExecutor, + runtime::api::dispatch, + runtime::native_version, + include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm") + ); } /// Native executor used for tests. pub use local_executor::LocalExecutor; /// Test client database backend. -pub type Backend = client::in_mem::Backend; +pub type Backend = client_db::Backend; /// Test client executor. pub type Executor = client::LocalCallExecutor< @@ -65,41 +67,154 @@ pub type Executor = client::LocalCallExecutor< executor::NativeExecutor, >; +/// Test client light database backend. +pub type LightBackend = client::light::backend::Backend< + client_db::light::LightStorage, + LightFetcher, + Blake2Hasher, +>; + +/// Test client light fetcher. +pub struct LightFetcher; + +/// Test client light executor. +pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor< + runtime::Block, + LightBackend, + client::light::call_executor::RemoteCallExecutor< + client::light::blockchain::Blockchain< + client_db::light::LightStorage, + LightFetcher + >, + LightFetcher + >, + client::LocalCallExecutor< + client::light::backend::Backend< + client_db::light::LightStorage, + LightFetcher, + Blake2Hasher + >, + executor::NativeExecutor + > +>; + /// Creates new client instance used for tests. pub fn new() -> client::Client { - new_with_backend(Arc::new(Backend::new()), false) + new_with_backend(Arc::new(Backend::new_test(::std::u32::MAX, ::std::u64::MAX)), false) +} + +/// Creates new light client instance used for tests. +pub fn new_light() -> client::Client { + let storage = client_db::light::LightStorage::new_test(); + let blockchain = Arc::new(client::light::blockchain::Blockchain::new(storage)); + let backend = Arc::new(LightBackend::new(blockchain.clone())); + let executor = NativeExecutor::new(None); + let fetcher = Arc::new(LightFetcher); + let remote_call_executor = client::light::call_executor::RemoteCallExecutor::new(blockchain.clone(), fetcher); + let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor); + let call_executor = LightExecutor::new(backend.clone(), remote_call_executor, local_call_executor); + client::Client::new(backend, call_executor, genesis_storage(false), Default::default()).unwrap() +} + +/// Creates new client instance used for tests with the given api execution strategy. +pub fn new_with_execution_strategy( + execution_strategy: ExecutionStrategy +) -> client::Client { + let backend = Arc::new(Backend::new_test(::std::u32::MAX, ::std::u64::MAX)); + let executor = NativeExecutor::new(None); + let executor = LocalCallExecutor::new(backend.clone(), executor); + + let execution_strategies = ExecutionStrategies { + syncing: execution_strategy, + importing: execution_strategy, + block_construction: execution_strategy, + other: execution_strategy, + }; + + client::Client::new( + backend, + executor, + genesis_storage(false), + execution_strategies + ).expect("Creates new client") } /// Creates new test client instance that suports changes trie creation. -pub fn new_with_changes_trie() -> client::Client { - new_with_backend(Arc::new(Backend::new()), true) +pub fn new_with_changes_trie() + -> client::Client +{ + new_with_backend(Arc::new(Backend::new_test(::std::u32::MAX, ::std::u64::MAX)), true) } -/// Creates new client instance used for tests with an explicitely provided backend. +/// Creates new client instance used for tests with an explicitly provided backend. /// This is useful for testing backend implementations. pub fn new_with_backend( backend: Arc, support_changes_trie: bool -) -> client::Client>, runtime::Block, runtime::RuntimeApi> - where - B: backend::LocalBackend, +) -> client::Client< + B, + client::LocalCallExecutor>, + runtime::Block, + runtime::RuntimeApi +> where B: backend::LocalBackend { - let executor = NativeExecutor::new(); + let executor = NativeExecutor::new(None); client::new_with_backend(backend, executor, genesis_storage(support_changes_trie)).unwrap() } fn genesis_config(support_changes_trie: bool) -> GenesisConfig { GenesisConfig::new(support_changes_trie, vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into(), - ], 1000) + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Bob.into(), + AuthorityKeyring::Charlie.into(), + ], vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ], + 1000 + ) } -fn genesis_storage(support_changes_trie: bool) -> StorageMap { +fn genesis_storage(support_changes_trie: bool) -> StorageOverlay { let mut storage = genesis_config(support_changes_trie).genesis_map(); let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(storage.clone().into_iter()); let block: runtime::Block = client::genesis::construct_genesis_block(state_root); storage.extend(additional_storage_with_genesis(&block)); storage } + +impl client::light::fetcher::Fetcher for LightFetcher { + type RemoteHeaderResult = FutureResult; + type RemoteReadResult = FutureResult>, client::error::Error>; + type RemoteCallResult = FutureResult, client::error::Error>; + type RemoteChangesResult = FutureResult, u32)>, client::error::Error>; + + fn remote_header( + &self, + _request: client::light::fetcher::RemoteHeaderRequest, + ) -> Self::RemoteHeaderResult { + unimplemented!("not (yet) used in tests") + } + + fn remote_read( + &self, + _request: client::light::fetcher::RemoteReadRequest, + ) -> Self::RemoteReadResult { + unimplemented!("not (yet) used in tests") + } + + fn remote_call( + &self, + _request: client::light::fetcher::RemoteCallRequest, + ) -> Self::RemoteCallResult { + unimplemented!("not (yet) used in tests") + } + + fn remote_changes( + &self, + _request: client::light::fetcher::RemoteChangesRequest, + ) -> Self::RemoteChangesResult { + unimplemented!("not (yet) used in tests") + } +} diff --git a/core/test-client/src/trait_tests.rs b/core/test-client/src/trait_tests.rs index 982c92d291de84d14d33427075157abbe6fc8c40..aa51f7d8bf9e33b24bad88060c5b8dca23a04018 100644 --- a/core/test-client/src/trait_tests.rs +++ b/core/test-client/src/trait_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,19 +20,18 @@ #![allow(missing_docs)] use std::sync::Arc; -use keyring::Keyring; use consensus::BlockOrigin; use primitives::Blake2Hasher; -use ::TestClient; +use crate::{TestClient, AccountKeyring}; use runtime_primitives::traits::Block as BlockT; -use backend; -use blockchain::{Backend as BlockChainBackendT, HeaderBackend}; -use ::BlockBuilderExt; +use crate::backend; +use crate::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; +use crate::{BlockBuilderExt, new_with_backend}; use runtime::{self, Transfer}; use runtime_primitives::generic::BlockId; /// helper to test the `leaves` implementation for various backends -pub fn test_leaves_for_backend(backend: Arc) where +pub fn test_leaves_for_backend(backend: Arc) where B: backend::LocalBackend, { // block tree: @@ -41,7 +40,7 @@ pub fn test_leaves_for_backend(backend: Arc) where // B2 -> C3 // A1 -> D2 - let client = ::new_with_backend(backend.clone(), false); + let client = new_with_backend(backend.clone(), false); let genesis_hash = client.info().unwrap().chain.genesis_hash; @@ -88,8 +87,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -117,8 +116,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -132,8 +131,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -144,8 +143,98 @@ pub fn test_leaves_for_backend(backend: Arc) where vec![a5.hash(), b4.hash(), c3.hash(), d2.hash()]); } +/// helper to test the `children` implementation for various backends +pub fn test_children_for_backend(backend: Arc) where + B: backend::LocalBackend, +{ + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + + let client = new_with_backend(backend.clone(), false); + + // G -> A1 + let a1 = client.new_block().unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at(&BlockId::Hash(a2.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at(&BlockId::Hash(a3.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at(&BlockId::Hash(a4.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at(&BlockId::Hash(b3.hash())).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.bake().unwrap(); + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.info().unwrap().chain.genesis_hash; + + let children1 = backend.blockchain().children(a4.hash()).unwrap(); + assert_eq!(vec![a5.hash()], children1); + + let children2 = backend.blockchain().children(a1.hash()).unwrap(); + assert_eq!(vec![a2.hash(), b2.hash(), d2.hash()], children2); + + let children3 = backend.blockchain().children(genesis_hash).unwrap(); + assert_eq!(vec![a1.hash()], children3); + + let children4 = backend.blockchain().children(b2.hash()).unwrap(); + assert_eq!(vec![b3.hash(), c3.hash()], children4); +} -pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where +pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where B: backend::LocalBackend, { // block tree: @@ -153,7 +242,7 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where // A1 -> B2 -> B3 -> B4 // B2 -> C3 // A1 -> D2 - let client = ::new_with_backend(backend, false); + let client = new_with_backend(backend, false); // G -> A1 let a1 = client.new_block().unwrap().bake().unwrap(); @@ -179,8 +268,8 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -199,8 +288,8 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -211,8 +300,8 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); diff --git a/core/test-runtime/Cargo.toml b/core/test-runtime/Cargo.toml index bc5bfe4905232729845629de2d28c8bdb739fa8b..812dd4bc28faab91b5285554f14433abba4526a4 100644 --- a/core/test-runtime/Cargo.toml +++ b/core/test-runtime/Cargo.toml @@ -2,23 +2,30 @@ name = "substrate-test-runtime" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] log = { version = "0.4", optional = true } hex-literal = { version = "0.1.0", optional = true } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-keyring = { path = "../keyring", optional = true } -substrate-client = { path = "../client", optional = true } -substrate-primitives = { path = "../primitives", default-features = false } -substrate-consensus-aura-primitives = { path = "../consensus/aura/primitives", default-features = false } -sr-std = { path = "../sr-std", default-features = false } -sr-io = { path = "../sr-io", default-features = false } -sr-primitives = { path = "../sr-primitives", default-features = false } -sr-version = { path = "../sr-version", default-features = false } -srml-support = { path = "../../srml/support", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +keyring = { package = "substrate-keyring", path = "../keyring", optional = true } +substrate-client = { path = "../client", default-features = false } +primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } +inherents = { package = "substrate-inherents", path = "../inherents", default-features = false } +consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../consensus/aura/primitives", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } +runtime_version = { package = "sr-version", path = "../sr-version", default-features = false } +runtime_support = { package = "srml-support", path = "../../srml/support", default-features = false } +executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } +cfg-if = "0.1.6" + +[dev-dependencies] +substrate-executor = { path = "../executor" } +substrate-test-client = { path = "../test-client" } [features] default = ["std"] @@ -27,14 +34,16 @@ std = [ "hex-literal", "serde", "serde_derive", - "substrate-client", - "substrate-keyring", + "substrate-client/std", + "keyring", "parity-codec/std", - "sr-std/std", - "sr-io/std", - "srml-support/std", - "substrate-primitives/std", - "sr-primitives/std", - "sr-version/std", - "substrate-consensus-aura-primitives/std", + "rstd/std", + "runtime_io/std", + "runtime_support/std", + "primitives/std", + "inherents/std", + "runtime_primitives/std", + "runtime_version/std", + "consensus_aura/std", + "executive/std", ] diff --git a/core/test-runtime/src/genesismap.rs b/core/test-runtime/src/genesismap.rs index 5e6adec86aff563dc7599ce335306db4918983ce..13e9e5ec9a55dee734fa17f662061a4851d16293 100644 --- a/core/test-runtime/src/genesismap.rs +++ b/core/test-runtime/src/genesismap.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,38 +18,35 @@ use std::collections::HashMap; use runtime_io::twox_128; -use codec::{Encode, KeyedVec, Joiner}; -use primitives::{AuthorityId, ChangesTrieConfiguration}; -use primitives::storage::well_known_keys; +use super::AccountId; +use parity_codec::{Encode, KeyedVec, Joiner}; +use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys}; use runtime_primitives::traits::Block; +use primitives::ed25519::Public as AuthorityId; /// Configuration of a general Substrate test genesis block. pub struct GenesisConfig { pub changes_trie_config: Option, pub authorities: Vec, - pub balances: Vec<(AuthorityId, u64)>, + pub balances: Vec<(AccountId, u64)>, } impl GenesisConfig { - pub fn new_simple(authorities: Vec, balance: u64) -> Self { - Self::new(false, authorities, balance) - } - - pub fn new(support_changes_trie: bool, authorities: Vec, balance: u64) -> Self { + pub fn new(support_changes_trie: bool, authorities: Vec, endowed_accounts: Vec, balance: u64) -> Self { GenesisConfig { changes_trie_config: match support_changes_trie { true => Some(super::changes_trie_config()), false => None, }, authorities: authorities.clone(), - balances: authorities.into_iter().map(|a| (a, balance)).collect(), + balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), } } pub fn genesis_map(&self) -> HashMap, Vec> { let wasm_runtime = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm").to_vec(); let mut map: HashMap, Vec> = self.balances.iter() - .map(|&(account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) + .map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) .chain(vec![ (well_known_keys::CODE.into(), wasm_runtime), @@ -68,7 +65,7 @@ impl GenesisConfig { } } -pub fn additional_storage_with_genesis(genesis_block: &::Block) -> HashMap, Vec> { +pub fn additional_storage_with_genesis(genesis_block: &crate::Block) -> HashMap, Vec> { map![ twox_128(&b"latest"[..]).to_vec() => genesis_block.hash().as_fixed_bytes().to_vec() ] diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index cceeee74d114da7f98b1e012231cfcb6b101a551..36950bfb1b517dd52e8ecc197831ea77ad5d6f3e 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,53 +19,31 @@ #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] -extern crate serde; - -extern crate sr_std as rstd; -extern crate parity_codec as codec; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_consensus_aura_primitives as consensus_aura; - -#[macro_use] -extern crate substrate_client as client; - -#[macro_use] -extern crate srml_support as runtime_support; -#[macro_use] -extern crate parity_codec_derive; -extern crate sr_io as runtime_io; -#[macro_use] -extern crate sr_version as runtime_version; - -#[cfg(test)] -#[macro_use] -extern crate hex_literal; -#[cfg(test)] -extern crate substrate_keyring as keyring; -#[cfg_attr(any(feature = "std", test), macro_use)] -extern crate substrate_primitives as primitives; - -#[cfg(feature = "std")] pub mod genesismap; +pub mod genesismap; pub mod system; -use rstd::prelude::*; -use codec::{Encode, Decode}; +use rstd::{prelude::*, marker::PhantomData}; +use parity_codec::{Encode, Decode, Input}; -use client::{runtime_api as client_api, block_builder::api as block_builder_api}; +use substrate_client::{ + runtime_api as client_api, block_builder::api as block_builder_api, decl_runtime_apis, + impl_runtime_apis, +}; use runtime_primitives::{ - ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity, + ApplyResult, transaction_validity::TransactionValidity, + create_runtime_str, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, - GetNodeBlockType, GetRuntimeBlockType - }, CheckInherentError + GetNodeBlockType, GetRuntimeBlockType, + }, }; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; -use primitives::AuthorityId; -use primitives::OpaqueMetadata; +use primitives::{ed25519, sr25519, OpaqueMetadata}; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; -use consensus_aura::api as aura_api; +use inherents::{CheckInherentsResult, InherentData}; +use cfg_if::cfg_if; /// Test runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -100,12 +78,22 @@ pub struct Transfer { pub nonce: u64, } +impl Transfer { + /// Convert into a signed extrinsic. + #[cfg(feature = "std")] + pub fn into_signed_tx(self) -> Extrinsic { + let signature = keyring::AccountKeyring::from_public(&self.from) + .expect("Creates keyring from public key.").sign(&self.encode()).into(); + Extrinsic::Transfer(self, signature) + } +} + /// Extrinsic for test-runtime. #[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] -pub struct Extrinsic { - pub transfer: Transfer, - pub signature: Ed25519Signature, +pub enum Extrinsic { + AuthoritiesChange(Vec), + Transfer(Transfer, AccountSignature), } #[cfg(feature = "std")] @@ -120,10 +108,15 @@ impl BlindCheckable for Extrinsic { type Checked = Self; fn check(self) -> Result { - if ::runtime_primitives::verify_encoded_lazy(&self.signature, &self.transfer, &self.transfer.from) { - Ok(self) - } else { - Err("bad signature") + match self { + Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), + Extrinsic::Transfer(transfer, signature) => { + if runtime_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { + Ok(Extrinsic::Transfer(transfer, signature)) + } else { + Err(runtime_primitives::BAD_SIGNATURE) + } + }, } } } @@ -134,8 +127,23 @@ impl ExtrinsicT for Extrinsic { } } +impl Extrinsic { + pub fn transfer(&self) -> &Transfer { + match self { + Extrinsic::Transfer(ref transfer, _) => transfer, + _ => panic!("cannot convert to transfer ref"), + } + } +} + +// The identity type used by authorities. +pub type AuthorityId = ed25519::Public; +// The signature type used by authorities. +pub type AuthoritySignature = ed25519::Signature; /// An identifier for an account on this system. -pub type AccountId = H256; +pub type AccountId = sr25519::Public; +// The signature type used by accounts/transactions. +pub type AccountSignature = sr25519::Signature; /// A simple hash type for all our hashing. pub type Hash = H256; /// The block number type used in this runtime. @@ -143,7 +151,7 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = runtime_primitives::generic::DigestItem; +pub type DigestItem = runtime_primitives::generic::DigestItem; /// The digest of a block. pub type Digest = runtime_primitives::generic::Digest; /// A test block. @@ -171,86 +179,307 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration { } } -pub mod test_api { - use super::AccountId; - - decl_runtime_apis! { - pub trait TestAPI { - fn balance_of(id: AccountId) -> u64; - } - } -} - -pub struct Runtime; - -impl GetNodeBlockType for Runtime { - type NodeBlock = Block; +/// A type that can not be decoded. +#[derive(PartialEq)] +pub struct DecodeFails { + _phantom: PhantomData, } -impl GetRuntimeBlockType for Runtime { - type RuntimeBlock = Block; +impl Encode for DecodeFails { + fn encode(&self) -> Vec { + Vec::new() + } } -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - version() - } - - fn authorities() -> Vec { - system::authorities() - } - - fn execute_block(block: Block) { - system::execute_block(block) - } - - fn initialise_block(header: ::Header) { - system::initialise_block(header) +impl DecodeFails { + /// Create a new instance. + pub fn new() -> DecodeFails { + DecodeFails { + _phantom: Default::default(), } } +} - impl client_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - unimplemented!() - } +impl Decode for DecodeFails { + fn decode(_: &mut I) -> Option { + // decoding always fails + None } +} - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { - system::validate_transaction(utx) +cfg_if! { + if #[cfg(feature = "std")] { + decl_runtime_apis! { + #[api_version(2)] + pub trait TestAPI { + /// Return the balance of the given account id. + fn balance_of(id: AccountId) -> u64; + /// A benchmark function that adds one to the given value and returns the result. + fn benchmark_add_one(val: &u64) -> u64; + /// A benchmark function that adds one to each value in the given vector and returns the + /// result. + fn benchmark_vector_add_one(vec: &Vec) -> Vec; + /// A function that always fails to convert a parameter between runtime and node. + fn fail_convert_parameter(param: DecodeFails); + /// A function that always fails to convert its return value between runtime and node. + fn fail_convert_return_value() -> DecodeFails; + /// A function for that the signature changed in version `2`. + #[changed_in(2)] + fn function_signature_changed() -> Vec; + /// The new signature. + fn function_signature_changed() -> u64; + fn fail_on_native() -> u64; + fn fail_on_wasm() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; + } + } + } else { + decl_runtime_apis! { + pub trait TestAPI { + /// Return the balance of the given account id. + fn balance_of(id: AccountId) -> u64; + /// A benchmark function that adds one to the given value and returns the result. + fn benchmark_add_one(val: &u64) -> u64; + /// A benchmark function that adds one to each value in the given vector and returns the + /// result. + fn benchmark_vector_add_one(vec: &Vec) -> Vec; + /// A function that always fails to convert a parameter between runtime and node. + fn fail_convert_parameter(param: DecodeFails); + /// A function that always fails to convert its return value between runtime and node. + fn fail_convert_return_value() -> DecodeFails; + /// In wasm we just emulate the old behavior. + fn function_signature_changed() -> Vec; + fn fail_on_native() -> u64; + fn fail_on_wasm() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; + } } } +} - impl block_builder_api::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { - system::execute_transaction(extrinsic) - } +pub struct Runtime; - fn finalise_block() -> ::Header { - system::finalise_block() - } +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} - fn inherent_extrinsics(_data: ()) -> Vec<::Extrinsic> { - unimplemented!() - } +impl GetRuntimeBlockType for Runtime { + type RuntimeBlock = Block; +} - fn check_inherents(_block: Block, _data: ()) -> Result<(), CheckInherentError> { - Ok(()) - } +/// Adds one to the given input and returns the final result. +#[inline(never)] +fn benchmark_add_one(i: u64) -> u64 { + i + 1 +} - fn random_seed() -> ::Hash { - unimplemented!() +/// The `benchmark_add_one` function as function pointer. +#[cfg(not(feature = "std"))] +static BENCHMARK_ADD_ONE: runtime_io::ExchangeableFunction u64> = runtime_io::ExchangeableFunction::new(benchmark_add_one); + +cfg_if! { + if #[cfg(feature = "std")] { + impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn authorities() -> Vec { + system::authorities() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialise_block(header: &::Header) { + system::initialise_block(header) + } + } + + impl client_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl client_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + system::validate_transaction(utx) + } + } + + impl block_builder_api::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + system::execute_transaction(extrinsic) + } + + fn finalise_block() -> ::Header { + system::finalise_block() + } + + fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { + vec![] + } + + fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { + CheckInherentsResult::new() + } + + fn random_seed() -> ::Hash { + unimplemented!() + } + } + + impl self::TestAPI for Runtime { + fn balance_of(id: AccountId) -> u64 { + system::balance_of(id) + } + + fn benchmark_add_one(val: &u64) -> u64 { + val + 1 + } + + fn benchmark_vector_add_one(vec: &Vec) -> Vec { + let mut vec = vec.clone(); + vec.iter_mut().for_each(|v| *v += 1); + vec + } + + fn fail_convert_parameter(_: DecodeFails) {} + + fn fail_convert_return_value() -> DecodeFails { + DecodeFails::new() + } + + fn function_signature_changed() -> u64 { + 1 + } + + fn fail_on_native() -> u64 { + panic!("Failing because we are on native") + } + fn fail_on_wasm() -> u64 { + 1 + } + fn benchmark_indirect_call() -> u64 { + let function = benchmark_add_one; + (0..1000).fold(0, |p, i| p + function(i)) + } + fn benchmark_direct_call() -> u64 { + (0..1000).fold(0, |p, i| p + benchmark_add_one(i)) + } + } + + impl consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1 } + } } - } - - impl self::test_api::TestAPI for Runtime { - fn balance_of(id: AccountId) -> u64 { - system::balance_of(id) + } else { + impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn authorities() -> Vec { + system::authorities() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialise_block(header: &::Header) { + system::initialise_block(header) + } + } + + impl client_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl client_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + system::validate_transaction(utx) + } + } + + impl block_builder_api::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + system::execute_transaction(extrinsic) + } + + fn finalise_block() -> ::Header { + system::finalise_block() + } + + fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { + vec![] + } + + fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { + CheckInherentsResult::new() + } + + fn random_seed() -> ::Hash { + unimplemented!() + } + } + + impl self::TestAPI for Runtime { + fn balance_of(id: AccountId) -> u64 { + system::balance_of(id) + } + + fn benchmark_add_one(val: &u64) -> u64 { + val + 1 + } + + fn benchmark_vector_add_one(vec: &Vec) -> Vec { + let mut vec = vec.clone(); + vec.iter_mut().for_each(|v| *v += 1); + vec + } + + fn fail_convert_parameter(_: DecodeFails) {} + + fn fail_convert_return_value() -> DecodeFails { + DecodeFails::new() + } + + fn function_signature_changed() -> Vec { + let mut vec = Vec::new(); + vec.push(1); + vec.push(2); + vec + } + + fn fail_on_native() -> u64 { + 1 + } + + fn fail_on_wasm() -> u64 { + panic!("Failing because we are on wasm") + } + + fn benchmark_indirect_call() -> u64 { + (0..10000).fold(0, |p, i| p + BENCHMARK_ADD_ONE.get()(i)) + } + + fn benchmark_direct_call() -> u64 { + (0..10000).fold(0, |p, i| p + benchmark_add_one(i)) + } + } + + impl consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1 } + } } } - - impl aura_api::AuraApi for Runtime { - fn slot_duration() -> u64 { 1 } - } -} +} \ No newline at end of file diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 3703fb553e68521abf8cb23dfe73815730aa9386..7c76fdd72b9211806fb6eb4a65ea82305efc95e0 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,13 +20,14 @@ use rstd::prelude::*; use runtime_io::{storage_root, enumerated_trie_root, storage_changes_root, twox_128}; use runtime_support::storage::{self, StorageValue, StorageMap}; -use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT}; +use runtime_support::storage_items; +use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT, NumberFor, Block as BlockT}; use runtime_primitives::generic; use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; -use codec::{KeyedVec, Encode}; -use super::{AccountId, BlockNumber, Extrinsic, H256 as Hash, Block, Header, Digest}; -use primitives::{Blake2Hasher}; -use primitives::storage::well_known_keys; +use parity_codec::{KeyedVec, Encode}; +use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest}; +use primitives::{Blake2Hasher, storage::well_known_keys}; +use primitives::ed25519::Public as AuthorityId; const NONCE_OF: &[u8] = b"nonce:"; const BALANCE_OF: &[u8] = b"balance:"; @@ -36,6 +37,7 @@ storage_items! { // The current block number being processed. Set by `execute_block`. Number: b"sys:num" => required BlockNumber; ParentHash: b"sys:pha" => required Hash; + NewAuthorities: b"sys:new_auth" => Vec; } pub fn balance_of_key(who: AccountId) -> Vec { @@ -50,8 +52,8 @@ pub fn nonce_of(who: AccountId) -> u64 { storage::get_or(&who.to_keyed_vec(NONCE_OF), 0) } -/// Get authorities ar given block. -pub fn authorities() -> Vec<::primitives::AuthorityId> { +/// Get authorities at given block. +pub fn authorities() -> Vec { let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT) .expect("There are always authorities in test-runtime"); (0..len) @@ -61,31 +63,65 @@ pub fn authorities() -> Vec<::primitives::AuthorityId> { .collect() } -pub fn initialise_block(header: Header) { +pub fn initialise_block(header: &Header) { // populate environment. ::put(&header.number); ::put(&header.parent_hash); storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); } +fn execute_extrinsics_without_checks(extrinsics: Vec<::Extrinsic>) { + // execute transactions + extrinsics.into_iter().enumerate().for_each(|(i, e)| { + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); + execute_transaction_backend(&e).unwrap_or_else(|_| panic!("Invalid transaction")); + storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); + }); +} + /// Actually execute all transitioning for `block`. -pub fn execute_block(block: Block) { - let ref header = block.header; +pub fn polish_block(block: &mut Block) { + let header = &mut block.header; // check transaction trie root represents the transactions. let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); let txs = txs.iter().map(Vec::as_slice).collect::>(); let txs_root = enumerated_trie_root::(&txs).into(); info_expect_equal_hash(&txs_root, &header.extrinsics_root); - assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + header.extrinsics_root = txs_root; // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).map_err(|_| ()).expect("Extrinsic error"); + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); + header.state_root = storage_root().into(); + + // check digest + let mut digest = Digest::default(); + if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into(), header.number - 1) { + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); + } + if let Some(new_authorities) = ::take() { + digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); + } + header.digest = digest; +} + +pub fn execute_block(block: Block) { + let ref header = block.header; + + // check transaction trie root represents the transactions. + let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); + let txs = txs.iter().map(Vec::as_slice).collect::>(); + let txs_root = enumerated_trie_root::(&txs).into(); + info_expect_equal_hash(&txs_root, &header.extrinsics_root); + assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + + execute_extrinsics_without_checks(block.extrinsics); + // check storage root. let storage_root = storage_root().into(); info_expect_equal_hash(&storage_root, &header.state_root); @@ -94,30 +130,46 @@ pub fn execute_block(block: Block) { // check digest let mut digest = Digest::default(); if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into(), header.number - 1) { - digest.push(generic::DigestItem::ChangesTrieRoot::(storage_changes_root.into())); + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); + } + if let Some(new_authorities) = ::take() { + digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); } assert!(digest == header.digest, "Header digest items must match that calculated."); } +/// The block executor. +pub struct BlockExecutor; + +impl executive::ExecuteBlock for BlockExecutor { + fn execute_block(block: Block) { + execute_block(block); + } + + fn execute_extrinsics_without_checks(_: NumberFor, extrinsics: Vec<::Extrinsic>) { + execute_extrinsics_without_checks(extrinsics); + } +} + /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { - let tx = match check_signature(&utx) { - Ok(tx) => tx, - Err(_) => return TransactionValidity::Invalid, - }; + if check_signature(&utx).is_err() { + return TransactionValidity::Invalid(ApplyError::BadSignature as i8); + } + let tx = utx.transfer(); let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::get_or(&nonce_key, 0); if tx.nonce < expected_nonce { - return TransactionValidity::Invalid; + return TransactionValidity::Invalid(ApplyError::Stale as i8); } if tx.nonce > expected_nonce + 64 { - return TransactionValidity::Unknown; + return TransactionValidity::Unknown(ApplyError::Future as i8); } let hash = |from: &AccountId, nonce: u64| { - twox_128(&nonce.to_keyed_vec(from.as_bytes())).to_vec() + twox_128(&nonce.to_keyed_vec(&from.encode())).to_vec() }; let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { let mut deps = Vec::new(); @@ -135,11 +187,10 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { priority: tx.amount, requires, provides, - longevity: 64 + longevity: 64, } } - /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { @@ -164,7 +215,10 @@ pub fn finalise_block() -> Header { let mut digest = Digest::default(); if let Some(storage_changes_root) = storage_changes_root { - digest.push(generic::DigestItem::ChangesTrieRoot::(storage_changes_root)); + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); + } + if let Some(new_authorities) = ::take() { + digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); } Header { @@ -177,21 +231,21 @@ pub fn finalise_block() -> Header { } #[inline(always)] -fn check_signature(utx: &Extrinsic) -> Result<::Transfer, ApplyError> { +fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { use runtime_primitives::traits::BlindCheckable; - - let utx = match utx.clone().check() { - Ok(tx) => tx, - Err(_) => return Err(ApplyError::BadSignature), - }; - - Ok(utx.transfer) + utx.clone().check().map_err(|_| ApplyError::BadSignature)?; + Ok(()) } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { - // check signature - let tx = check_signature(utx)?; + check_signature(utx)?; + match utx { + Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), + Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), + } +} +fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // check nonce let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::get_or(&nonce_key, 0); @@ -217,6 +271,12 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { Ok(ApplyOutcome::Success) } +fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { + let new_authorities: Vec = new_authorities.iter().cloned().collect(); + ::put(new_authorities); + Ok(ApplyOutcome::Success) +} + #[cfg(feature = "std")] fn info_expect_equal_hash(given: &Hash, expected: &Hash) { use primitives::hexdisplay::HexDisplay; @@ -243,114 +303,146 @@ mod tests { use super::*; use runtime_io::{with_externalities, twox_128, TestExternalities}; - use codec::{Joiner, KeyedVec}; - use keyring::Keyring; - use ::{Header, Digest, Extrinsic, Transfer}; - use primitives::{Blake2Hasher}; + use parity_codec::{Joiner, KeyedVec}; + use substrate_test_client::{AuthorityKeyring, AccountKeyring}; + use crate::{Header, Extrinsic, Transfer}; + use primitives::{Blake2Hasher, map}; use primitives::storage::well_known_keys; + use substrate_executor::WasmExecutor; + + const WASM_CODE: &'static [u8] = + include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"); fn new_test_ext() -> TestExternalities { TestExternalities::new(map![ twox_128(b"latest").to_vec() => vec![69u8; 32], twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Alice.to_raw_public().to_vec(), - twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Bob.to_raw_public().to_vec(), - twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Charlie.to_raw_public().to_vec(), - twox_128(&Keyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(), + twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(), + twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(), + twox_128(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ]) } - fn construct_signed_tx(tx: Transfer) -> Extrinsic { - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); - Extrinsic { transfer: tx, signature } - } - - #[test] - fn block_import_works() { - let mut t = new_test_ext(); - + fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { let h = Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("3d6f3663e052a7d325d3ac6cdbd3cd4033132f5bfe5852d51d4e42e7021ee69b").into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }; - - let b = Block { + let mut b = Block { header: h, extrinsics: vec![], }; - with_externalities(&mut t, || { - execute_block(b); - }); + with_externalities(&mut new_test_ext(), || polish_block(&mut b)); + + block_executor(b, &mut new_test_ext()); } #[test] - fn block_import_with_transaction_works() { - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 111); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 0); + fn block_import_works_native() { + block_import_works(|b, ext| { + with_externalities(ext, || { + execute_block(b); + }); }); + } + + #[test] + fn block_import_works_wasm() { + block_import_works(|b, ext| { + WasmExecutor::new().call(ext, 8, &WASM_CODE, "Core_execute_block", &b.encode()).unwrap(); + }) + } - let b = Block { + fn block_import_with_transaction_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { + let mut b1 = Block { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("c3d2cc317b5897af4c7f65d76b028971ce9fad745678732ff6d42301b4245a9c").into(), - extrinsics_root: hex!("4e689a607609f69df099af82577ae6c5969c44f1afe33a43cd7af926eba42272").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ - construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Bob.to_raw_public().into(), + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), amount: 69, nonce: 0, - }) + }.into_signed_tx() ], }; - with_externalities(&mut t, || { - execute_block(b.clone()); - - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 69); - }); + let mut dummy_ext = new_test_ext(); + with_externalities(&mut dummy_ext, || polish_block(&mut b1)); - let b = Block { + let mut b2 = Block { header: Header { - parent_hash: b.header.hash(), + parent_hash: b1.header.hash(), number: 2, - state_root: hex!("2c822d948bb68d7f7a1976d4f827a276a95a3ba1c4c15dbfab3bafbeb85f2b4d").into(), - extrinsics_root: hex!("009268a854b21f339c53d3c7a6619a27f564703311d91f11f61573a7fed5ca1c").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ - construct_signed_tx(Transfer { - from: Keyring::Bob.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + Transfer { + from: AccountKeyring::Bob.into(), + to: AccountKeyring::Alice.into(), amount: 27, nonce: 0, - }), - construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Charlie.to_raw_public().into(), + }.into_signed_tx(), + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), amount: 69, nonce: 1, - }), + }.into_signed_tx(), ], }; + with_externalities(&mut dummy_ext, || polish_block(&mut b2)); + drop(dummy_ext); + + let mut t = new_test_ext(); + with_externalities(&mut t, || { - execute_block(b); + assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); + }); + + block_executor(b1, &mut t); - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 0); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Charlie.to_raw_public().into()), 69); + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); }); + + block_executor(b2, &mut t); + + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); + assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); + }); + } + + #[test] + fn block_import_with_transaction_works_native() { + block_import_with_transaction_works(|b, ext| { + with_externalities(ext, || { + execute_block(b); + }); + }); + } + + #[test] + fn block_import_with_transaction_works_wasm() { + block_import_with_transaction_works(|b, ext| { + WasmExecutor::new().call(ext, 8, &WASM_CODE, "Core_execute_block", &b.encode()).unwrap(); + }) } } diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index 03a7ef0a00d3b3041e3ee8d0490663a42ca5251a..f933220f0b40b3f5a99bd3e3455ec0c6309a04ab 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -1,30 +1,51 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -37,37 +58,80 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + [[package]] name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.25" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -77,7 +141,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -95,8 +167,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam" -version = "0.2.12" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-deque" @@ -109,11 +200,20 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -121,10 +221,10 @@ name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -132,31 +232,40 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -169,9 +278,72 @@ name = "crunchy" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crypto-mac" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -187,18 +359,43 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fixed-hash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -221,6 +418,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -241,21 +443,42 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "gcc" -version = "0.3.55" +name = "generic-array" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "generic-array" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "hash-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -266,9 +489,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -283,6 +511,35 @@ dependencies = [ "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -295,7 +552,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -308,7 +582,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -317,6 +591,11 @@ name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -329,20 +608,15 @@ dependencies = [ [[package]] name = "kvdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -352,24 +626,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "lock_api" -version = "0.1.5" +name = "libsecp256k1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "log" -version = "0.3.9" +name = "lock_api" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -377,30 +656,17 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "mashup" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mashup-impl" -version = "0.1.9" +name = "matches" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "matches" -version = "0.1.8" +name = "memchr" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -410,10 +676,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -422,6 +688,17 @@ name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "merlin" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.16" @@ -432,11 +709,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -448,7 +725,7 @@ dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,7 +734,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -477,8 +754,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -502,44 +779,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" -version = "0.10.15" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.39" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "owning_ref" version = "0.4.0" @@ -551,25 +834,27 @@ dependencies = [ [[package]] name = "parity-bytes" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" [[package]] name = "parity-codec" -version = "2.1.5" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-codec-derive" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -577,69 +862,58 @@ name = "parity-wasm" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.7.0" +name = "parking_lot_core" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.2.14" +name = "paste" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.3.1" +name = "paste-impl" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.4.0" +name = "pbkdf2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -652,6 +926,25 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "primitive-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack" version = "0.4.1" @@ -660,6 +953,16 @@ dependencies = [ "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack-impl" version = "0.4.1" @@ -667,7 +970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -675,72 +978,74 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -748,7 +1053,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -756,31 +1061,56 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "0.8.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -790,31 +1120,60 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.43" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ring" -version = "0.12.1" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -835,6 +1194,31 @@ name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safe-mix" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -855,27 +1239,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -883,9 +1267,44 @@ name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sha2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha3" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -909,37 +1328,40 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slog-scope" -version = "4.0.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "spin" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "sr-api-macros" version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -947,13 +1369,15 @@ name = "sr-io" version = "0.1.0" dependencies = [ "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -963,10 +1387,9 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -983,22 +1406,34 @@ dependencies = [ name = "sr-version" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + +[[package]] +name = "srml-executive" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", ] [[package]] name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -1007,46 +1442,67 @@ dependencies = [ name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-metadata 0.1.0", "srml-support-procedural 0.1.0", + "substrate-inherents 0.1.0", ] [[package]] name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "substrate-primitives 0.1.0", ] [[package]] @@ -1059,6 +1515,17 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-client" version = "0.1.0" @@ -1066,24 +1533,24 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", - "substrate-telemetry 0.3.0", + "substrate-telemetry 0.3.1", "substrate-trie 0.4.0", ] @@ -1091,119 +1558,146 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-version 0.1.0", - "srml-support 0.1.0", "substrate-client 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-executor" version = "0.1.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-inherents" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", ] [[package]] name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" -version = "0.3.0" +version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1211,48 +1705,71 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", + "srml-executive 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-inherents 0.1.0", + "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-test-runtime-wasm" +version = "0.1.0" +dependencies = [ + "substrate-test-runtime 0.1.0", +] + [[package]] name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "memory-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" -version = "0.14.9" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "syn" -version = "0.15.22" +name = "synstructure" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1266,39 +1783,62 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1306,101 +1846,114 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1408,49 +1961,57 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1458,16 +2019,27 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1481,25 +2053,20 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "untrusted" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1513,21 +2080,21 @@ dependencies = [ ] [[package]] -name = "vcpkg" -version = "0.2.6" +name = "utf8-ranges" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "void" -version = "1.0.2" +name = "vcpkg" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1566,16 +2133,16 @@ name = "ws" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1589,64 +2156,96 @@ dependencies = [ ] [metadata] -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" -"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" +"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" "checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" +"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" -"checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" @@ -1655,90 +2254,112 @@ dependencies = [ "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" -"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" -"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" +"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" +"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9723236a9525c757d9725b993511e3fc941e33f27751942232f0058298297edf" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" +"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" -"checksum trie-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-root 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" +"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" -"checksum uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a60b9508cff2b7c27ed41200dd668806280740fadc8c88440e9c88625e84f1a" +"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/core/test-runtime/wasm/Cargo.toml b/core/test-runtime/wasm/Cargo.toml index 0d8894e8cf2e8c3ab75394a10ee7b4b9a5428003..7b11859874e9421a86ebdccb66352b25a539e6c4 100644 --- a/core/test-runtime/wasm/Cargo.toml +++ b/core/test-runtime/wasm/Cargo.toml @@ -1,41 +1,22 @@ [package] -name = "substrate-test-runtime" +name = "substrate-test-runtime-wasm" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" + +[lib] +name = "substrate_test_runtime" +crate-type = ["cdylib"] [dependencies] -log = { version = "0.4", optional = true } -hex-literal = { version = "0.1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../primitives", default-features = false } -substrate-consensus-aura-primitives = { path = "../../consensus/aura/primitives", default-features = false } -substrate-client = { path = "../../client", default-features = false } -sr-std = { path = "../../sr-std", default-features = false } -sr-io = { path = "../../sr-io", default-features = false } -sr-version = { path = "../../sr-version", default-features = false } -sr-primitives = { path = "../../sr-primitives", default-features = false } -srml-support = { path = "../../../srml/support", default-features = false } +substrate-test-runtime = { path = "..", default-features = false } [features] default = [] std = [ - "log", - "hex-literal", - "parity-codec/std", - "sr-std/std", - "sr-io/std", - "srml-support/std", - "sr-version/std", - "substrate-primitives/std", - "substrate-client/std", - "sr-primitives/std", - "substrate-consensus-aura-primitives/std", + "substrate-test-runtime/std", ] -[lib] -crate-type = ["cdylib"] - [profile.release] panic = "abort" lto = true diff --git a/core/test-runtime/wasm/build.sh b/core/test-runtime/wasm/build.sh index 24a0d162dad2b589e7c073befcb18064c0815b2e..abca9a60e9c4a7a5e68723cfd80c350a5c74d09a 100755 --- a/core/test-runtime/wasm/build.sh +++ b/core/test-runtime/wasm/build.sh @@ -6,7 +6,7 @@ if cargo --version | grep -q "nightly"; then else CARGO_CMD="cargo +nightly" fi -$CARGO_CMD build --target=wasm32-unknown-unknown --release +CARGO_INCREMENTAL=0 RUSTFLAGS="-C link-arg=--export-table" $CARGO_CMD build --target=wasm32-unknown-unknown --release for i in substrate_test_runtime do wasm-gc target/wasm32-unknown-unknown/release/$i.wasm target/wasm32-unknown-unknown/release/$i.compact.wasm diff --git a/core/test-runtime/wasm/src b/core/test-runtime/wasm/src deleted file mode 120000 index 5cd551cf2693e4b4f65d7954ec621454c2b20326..0000000000000000000000000000000000000000 --- a/core/test-runtime/wasm/src +++ /dev/null @@ -1 +0,0 @@ -../src \ No newline at end of file diff --git a/core/test-runtime/wasm/src/lib.rs b/core/test-runtime/wasm/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..6620f276d0397fbd44840aef3f1500b2877798cb --- /dev/null +++ b/core/test-runtime/wasm/src/lib.rs @@ -0,0 +1,21 @@ +// 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 . + +//! The Substrate test runtime reexported for WebAssembly compile. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use substrate_test_runtime::*; diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 9ed2d76370c16e6e2bed6555008d25a6bc2b666a..82ede8590330a37e4885336de3322530ee251f8a 100644 Binary files a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 93768f16d2264126cc8d605ca598ddf87842d53a..1286b7bde4b093de55512f1fba4528ef44b8cf3c 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -2,18 +2,19 @@ name = "substrate-transaction-pool" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] error-chain = "0.12" futures = "0.1" log = "0.4" -parity-codec = "2.1" -parking_lot = "0.4" +parity-codec = "3.2" +parking_lot = "0.7.1" sr-primitives = { path = "../sr-primitives" } -substrate-client = { path = "../client" } +client = { package = "substrate-client", path = "../client" } substrate-primitives = { path = "../primitives" } -substrate-transaction-graph = { path = "./graph" } +txpool = { package = "substrate-transaction-graph", path = "./graph" } [dev-dependencies] -substrate-test-client = { path = "../../core/test-client" } -substrate-keyring = { path = "../../core/keyring" } +keyring = { package = "substrate-keyring", path = "../../core/keyring" } +test_client = { package = "substrate-test-client", path = "../../core/test-client" } diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml index 9c154d4b3a4053ff6c413cdb5ce500f3a54d7d88..98d84934289d7a73c0772338eeb120e34adb4ab5 100644 --- a/core/transaction-pool/graph/Cargo.toml +++ b/core/transaction-pool/graph/Cargo.toml @@ -2,16 +2,18 @@ name = "substrate-transaction-graph" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] error-chain = "0.12" futures = "0.1" log = "0.4" -parking_lot = "0.4" +parking_lot = "0.7.1" serde = "1.0" serde_derive = "1.0" sr-primitives = { path = "../../sr-primitives" } [dev-dependencies] assert_matches = "1.1" -substrate-test-runtime = { path = "../../test-runtime" } +parity-codec = "3.2" +test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } diff --git a/core/transaction-pool/graph/src/base_pool.rs b/core/transaction-pool/graph/src/base_pool.rs index e6ad3cd6dd6c5a60d31b99b07938f5dbbba18b47..5a1bee00f387185e9bad51f95d50ac059e884301 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/core/transaction-pool/graph/src/base_pool.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,6 +24,8 @@ use std::{ }; use serde::Serialize; +use error_chain::bail; +use log::{trace, debug, warn}; use sr_primitives::traits::Member; use sr_primitives::transaction_validity::{ TransactionTag as Tag, @@ -31,9 +33,9 @@ use sr_primitives::transaction_validity::{ TransactionPriority as Priority, }; -use error; -use future::{FutureTransactions, WaitingTransaction}; -use ready::ReadyTransactions; +use crate::error; +use crate::future::{FutureTransactions, WaitingTransaction}; +use crate::ready::ReadyTransactions; /// Successful import result. #[derive(Debug, PartialEq, Eq)] @@ -84,6 +86,8 @@ pub struct PruneStatus { pub struct Transaction { /// Raw extrinsic representing that transaction. pub data: Extrinsic, + /// Number of bytes encoding of the transaction requires. + pub bytes: usize, /// Transaction hash (unique) pub hash: Hash, /// Transaction priority (higher = better) @@ -134,7 +138,7 @@ impl BasePool, ) -> error::Result> { if self.future.contains(&tx.hash) || self.ready.contains(&tx.hash) { - bail!(error::ErrorKind::AlreadyImported) + bail!(error::ErrorKind::AlreadyImported(Box::new(tx.hash.clone()))) } let tx = WaitingTransaction::new(tx, self.ready.provided_tags()); @@ -226,6 +230,73 @@ impl BasePool Vec>>> { + let ready = self.ready.by_hash(hashes); + let future = self.future.by_hash(hashes); + + ready + .into_iter() + .zip(future) + .map(|(a, b)| a.or(b)) + .collect() + } + + /// Makes sure that the transactions in the queues stay within provided limits. + /// + /// Removes and returns worst transactions from the queues and all transactions that depend on them. + /// Technically the worst transaction should be evaluated by computing the entire pending set. + /// We use a simplified approach to remove the transaction that occupies the pool for the longest time. + pub fn enforce_limits(&mut self, ready: &Limit, future: &Limit) -> Vec>> { + let mut removed = vec![]; + + while ready.is_exceeded(self.ready.len(), self.ready.bytes()) { + // find the worst transaction + let minimal = self.ready + .fold(|minimal, current| { + let transaction = ¤t.transaction; + match minimal { + None => Some(transaction.clone()), + Some(ref tx) if tx.insertion_id > transaction.insertion_id => { + Some(transaction.clone()) + }, + other => other, + } + }); + + if let Some(minimal) = minimal { + removed.append(&mut self.remove_invalid(&[minimal.transaction.hash.clone()])) + } else { + break; + } + } + + while future.is_exceeded(self.future.len(), self.future.bytes()) { + // find the worst transaction + 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, + } + }); + + if let Some(minimal) = minimal { + removed.append(&mut self.remove_invalid(&[minimal.transaction.hash.clone()])) + } else { + break; + } + } + + removed + } + /// Removes all transactions represented by the hashes and all other transactions /// that depend on them. /// @@ -236,7 +307,7 @@ impl BasePool Vec>> { let mut removed = self.ready.remove_invalid(hashes); - removed.extend(self.future.remove(hashes).into_iter().map(Arc::new)); + removed.extend(self.future.remove(hashes)); removed } @@ -281,7 +352,9 @@ impl BasePool Status { Status { ready: self.ready.len(), + ready_bytes: self.ready.bytes(), future: self.future.len(), + future_bytes: self.future.bytes(), } } } @@ -290,8 +363,35 @@ impl BasePool bool { + self.ready == 0 && self.future == 0 + } +} + +/// Queue limits +#[derive(Debug, Clone)] +pub struct Limit { + /// Maximal number of transactions in the queue. + pub count: usize, + /// Maximal size of encodings of all transactions 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)] @@ -312,6 +412,7 @@ mod tests { // when pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1u64, priority: 5u64, valid_till: 64u64, @@ -332,6 +433,7 @@ mod tests { // when pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -340,6 +442,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -361,6 +464,7 @@ mod tests { // when pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -371,6 +475,7 @@ mod tests { assert_eq!(pool.ready.len(), 0); pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -391,6 +496,7 @@ mod tests { // when pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -399,6 +505,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![3u8], + bytes: 1, hash: 3, priority: 5u64, valid_till: 64u64, @@ -407,6 +514,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -415,6 +523,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![4u8], + bytes: 1, hash: 4, priority: 1_000u64, valid_till: 64u64, @@ -426,6 +535,7 @@ mod tests { let res = pool.import(Transaction { data: vec![5u8], + bytes: 1, hash: 5, priority: 5u64, valid_till: 64u64, @@ -456,6 +566,7 @@ mod tests { let mut pool = pool(); pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -464,6 +575,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![3u8], + bytes: 1, hash: 3, priority: 5u64, valid_till: 64u64, @@ -476,6 +588,7 @@ mod tests { // when pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -494,6 +607,7 @@ mod tests { // let's close the cycle with one additional transaction let res = pool.import(Transaction { data: vec![4u8], + bytes: 1, hash: 4, priority: 50u64, valid_till: 64u64, @@ -521,6 +635,7 @@ mod tests { let mut pool = pool(); pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -529,6 +644,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![3u8], + bytes: 1, hash: 3, priority: 5u64, valid_till: 64u64, @@ -541,6 +657,7 @@ mod tests { // when pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -559,6 +676,7 @@ mod tests { // let's close the cycle with one additional transaction let err = pool.import(Transaction { data: vec![4u8], + bytes: 1, hash: 4, priority: 1u64, // lower priority than Tx(2) valid_till: 64u64, @@ -581,6 +699,7 @@ mod tests { let mut pool = pool(); pool.import(Transaction { data: vec![5u8], + bytes: 1, hash: 5, priority: 5u64, valid_till: 64u64, @@ -589,6 +708,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -597,6 +717,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![3u8], + bytes: 1, hash: 3, priority: 5u64, valid_till: 64u64, @@ -605,6 +726,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -613,6 +735,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![4u8], + bytes: 1, hash: 4, priority: 1_000u64, valid_till: 64u64, @@ -622,6 +745,7 @@ mod tests { // future pool.import(Transaction { data: vec![6u8], + bytes: 1, hash: 6, priority: 1_000u64, valid_till: 64u64, @@ -647,6 +771,7 @@ mod tests { // future (waiting for 0) pool.import(Transaction { data: vec![5u8], + bytes: 1, hash: 5, priority: 5u64, valid_till: 64u64, @@ -656,6 +781,7 @@ mod tests { // ready pool.import(Transaction { data: vec![1u8], + bytes: 1, hash: 1, priority: 5u64, valid_till: 64u64, @@ -664,6 +790,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![2u8], + bytes: 1, hash: 2, priority: 5u64, valid_till: 64u64, @@ -672,6 +799,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![3u8], + bytes: 1, hash: 3, priority: 5u64, valid_till: 64u64, @@ -680,6 +808,7 @@ mod tests { }).unwrap(); pool.import(Transaction { data: vec![4u8], + bytes: 1, hash: 4, priority: 1_000u64, valid_till: 64u64, diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index 308d575a2c7d04d14eabf2b61978be9373ecd447..435ca922cd58eed93cfb4c8e1cb781186b73bb4c 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,18 +17,21 @@ //! Transaction pool errors. use sr_primitives::transaction_validity::TransactionPriority as Priority; +use error_chain::{ + error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind +}; error_chain! { errors { /// Transaction is not verifiable yet, but might be in the future. - UnknownTransactionValidity { + UnknownTransactionValidity(e: i8) { description("Runtime cannot determine validity of the transaction yet."), - display("Unkown Transaction Validity"), + display("Unkown Transaction Validity. Error code: {}", e), } /// Transaction is invalid - InvalidTransaction { + InvalidTransaction(e: i8) { description("Runtime check for the transaction failed."), - display("Invalid Transaction"), + display("Invalid Transaction. Error Code: {}", e), } /// The transaction is temporarily baned TemporarilyBanned { @@ -36,9 +39,9 @@ error_chain! { display("Temporarily Banned"), } /// The transaction is already in the pool. - AlreadyImported { - description("Transaction is already in the pool."), - display("Already imported"), + AlreadyImported(hash: Box<::std::any::Any + Send>) { + description("Transaction is already in the pool"), + display("[{:?}] Already imported", hash), } /// The transaction cannot be imported cause it's a replacement and has too low priority. TooLowPriority(old: Priority, new: Priority) { @@ -50,6 +53,11 @@ error_chain! { description("Transaction was not imported because of detected cycle."), display("Cycle Detected"), } + /// Transaction was dropped immediately after it got inserted. + ImmediatelyDropped { + description("Transaction couldn't enter the pool because of the limit."), + display("Immediately Dropped"), + } } } diff --git a/core/transaction-pool/graph/src/future.rs b/core/transaction-pool/graph/src/future.rs index da6e8e55f2d35d6f4b1e9d75a138114de9c65f73..bf25ed90df8f2ff6602fc533d82c446f3b0566ce 100644 --- a/core/transaction-pool/graph/src/future.rs +++ b/core/transaction-pool/graph/src/future.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,21 +17,35 @@ use std::{ collections::{HashMap, HashSet}, hash, + sync::Arc, + time, }; use sr_primitives::transaction_validity::{ TransactionTag as Tag, }; -use base_pool::Transaction; +use crate::base_pool::Transaction; /// Transaction with partially satisfied dependencies. #[derive(Debug)] pub struct WaitingTransaction { /// Transaction details. - pub transaction: Transaction, + pub transaction: Arc>, /// Tags that are required and have not been satisfied yet by other transactions in the pool. pub missing_tags: HashSet, + /// Time of import to the Future Queue. + pub imported_at: time::Instant, +} + +impl Clone for WaitingTransaction { + fn clone(&self) -> Self { + WaitingTransaction { + transaction: self.transaction.clone(), + missing_tags: self.missing_tags.clone(), + imported_at: self.imported_at.clone(), + } + } } impl WaitingTransaction { @@ -47,8 +61,9 @@ impl WaitingTransaction { .collect(); WaitingTransaction { - transaction, + transaction: Arc::new(transaction), missing_tags, + imported_at: time::Instant::now(), } } @@ -104,7 +119,7 @@ impl FutureTransactions { // Add all tags that are missing for tag in &tx.missing_tags { - let mut entry = self.wanted_tags.entry(tag.clone()).or_insert_with(HashSet::new); + let entry = self.wanted_tags.entry(tag.clone()).or_insert_with(HashSet::new); entry.insert(tx.transaction.hash.clone()); } @@ -117,6 +132,11 @@ impl FutureTransactions { self.waiting.contains_key(hash) } + /// Returns a list of known transactions + pub fn by_hash(&self, hashes: &[Hash]) -> Vec>>> { + hashes.iter().map(|h| self.waiting.get(h).map(|x| x.transaction.clone())).collect() + } + /// Satisfies provided tags in transactions that are waiting for them. /// /// Returns (and removes) transactions that became ready after their last tag got @@ -128,8 +148,7 @@ impl FutureTransactions { if let Some(hashes) = self.wanted_tags.remove(tag.as_ref()) { for hash in hashes { let is_ready = { - let mut tx = self.waiting.get_mut(&hash) - .expect(WAITING_PROOF); + let tx = self.waiting.get_mut(&hash).expect(WAITING_PROOF); tx.satisfy_tag(tag.as_ref()); tx.is_ready() }; @@ -148,13 +167,13 @@ impl FutureTransactions { /// Removes transactions for given list of hashes. /// /// Returns a list of actually removed transactions. - pub fn remove(&mut self, hashes: &[Hash]) -> Vec> { + pub fn remove(&mut self, hashes: &[Hash]) -> Vec>> { let mut removed = vec![]; for hash in hashes { if let Some(waiting_tx) = self.waiting.remove(hash) { // remove from wanted_tags as well for tag in waiting_tx.missing_tags { - let remove = if let Some(mut wanted) = self.wanted_tags.get_mut(&tag) { + let remove = if let Some(wanted) = self.wanted_tags.get_mut(&tag) { wanted.remove(hash); wanted.is_empty() } else { false }; @@ -169,13 +188,25 @@ impl FutureTransactions { removed } + /// Fold a list of future transactions to compute a single value. + pub fn fold, &WaitingTransaction) -> Option>(&mut self, f: F) -> Option { + self.waiting + .values() + .fold(None, f) + } + /// Returns iterator over all future transactions pub fn all(&self) -> impl Iterator> { - self.waiting.values().map(|waiting| &waiting.transaction) + self.waiting.values().map(|waiting| &*waiting.transaction) } /// Returns number of transactions in the Future queue. pub fn len(&self) -> usize { self.waiting.len() } + + /// Returns sum of encoding lengths of all transactions in this queue. + pub fn bytes(&self) -> usize { + self.waiting.values().fold(0, |acc, tx| acc + tx.transaction.bytes) + } } diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index a4879f3cb0e78d37e489fe69b9775b9557f583f8..ea890a5cd0f2182d3d85c95250bf37c6914957eb 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,28 +20,10 @@ //! and their priority. //! The pool is able to return an iterator that traverses transaction //! graph in the correct order taking into account priorities and dependencies. -//! -//! TODO [ToDr] -//! - [ ] Multi-threading (getting ready transactions should not block the pool) #![warn(missing_docs)] #![warn(unused_extern_crates)] -extern crate futures; -extern crate parking_lot; -extern crate sr_primitives; - -extern crate serde; -#[macro_use] extern crate error_chain; -#[macro_use] extern crate log; -#[macro_use] extern crate serde_derive; - -#[cfg(test)] -extern crate substrate_test_runtime as test_runtime; -#[cfg(test)] -#[macro_use] -extern crate assert_matches; - mod future; mod listener; mod pool; diff --git a/core/transaction-pool/graph/src/listener.rs b/core/transaction-pool/graph/src/listener.rs index d4645eb2c55dc8fc4a058ab1aeb7f141e45409f7..ac59b4c57e102c01b5344a6ef8aba3a0c5161162 100644 --- a/core/transaction-pool/graph/src/listener.rs +++ b/core/transaction-pool/graph/src/listener.rs @@ -1,5 +1,5 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,8 +20,9 @@ use std::{ hash, }; use serde::Serialize; -use watcher; +use crate::watcher; use sr_primitives::traits; +use log::warn; /// Extrinsic pool default listener. pub struct Listener { diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index a16db8206ef3f5a5c8360ce6214be7b8996fc90f..0c4b4a6c1343d1c19faeefd36d63c8c7777c4113 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,18 +15,20 @@ // along with Substrate. If not, see . use std::{ - collections::HashMap, + collections::{HashSet, HashMap}, hash, sync::Arc, time, }; -use base_pool as base; -use error; -use listener::Listener; -use rotator::PoolRotator; -use watcher::Watcher; +use crate::base_pool as base; +use crate::error; +use crate::listener::Listener; +use crate::rotator::PoolRotator; +use crate::watcher::Watcher; use serde::Serialize; +use error_chain::bail; +use log::debug; use futures::sync::mpsc; use parking_lot::{Mutex, RwLock}; @@ -36,6 +38,8 @@ use sr_primitives::{ transaction_validity::{TransactionValidity, TransactionTag as Tag}, }; +pub use crate::base_pool::Limit; + /// Modification notification event stream type; pub type EventStream = mpsc::UnboundedReceiver<()>; @@ -60,7 +64,7 @@ pub trait ChainApi: Send + Sync { type Error: From + error::IntoPoolError; /// Verify extrinsic at given block. - fn validate_transaction(&self, at: &BlockId, uxt: &ExtrinsicFor) -> Result; + fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result; /// Returns a block number given the block id. fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error>; @@ -68,17 +72,38 @@ pub trait ChainApi: Send + Sync { /// Returns a block hash given the block id. fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error>; - /// Hash the extrinsic. - fn hash(&self, uxt: &ExtrinsicFor) -> Self::Hash; + /// Returns hash and encoding length of the extrinsic. + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize); } /// Pool configuration options. -#[derive(Debug, Clone, Default)] -pub struct Options; +#[derive(Debug, Clone)] +pub struct Options { + /// Ready queue limits. + pub ready: Limit, + /// Future queue limits. + pub future: Limit, +} + +impl Default for Options { + fn default() -> Self { + Options { + ready: Limit { + count: 512, + total_bytes: 10 * 1024 * 1024, + }, + future: Limit { + count: 128, + total_bytes: 1 * 1024 * 1024, + }, + } + } +} /// Extrinsics pool. pub struct Pool { api: B, + options: Options, listener: RwLock, BlockHash>>, pool: RwLock, @@ -89,7 +114,6 @@ pub struct Pool { } impl Pool { - /// Imports a bunch of unverified extrinsics to the pool pub fn submit_at(&self, at: &BlockId, xts: T) -> Result, B::Error>>, B::Error> where T: IntoIterator> @@ -97,18 +121,19 @@ impl Pool { let block_number = self.api.block_id_to_number(at)? .ok_or_else(|| error::ErrorKind::Msg(format!("Invalid block id: {:?}", at)).into())?; - Ok(xts + let results = xts .into_iter() .map(|xt| -> Result<_, B::Error> { - let hash = self.api.hash(&xt); + let (hash, bytes) = self.api.hash_and_length(&xt); if self.rotator.is_banned(&hash) { bail!(error::Error::from(error::ErrorKind::TemporarilyBanned)) } - match self.api.validate_transaction(at, &xt)? { + match self.api.validate_transaction(at, xt.clone())? { TransactionValidity::Valid { priority, requires, provides, longevity } => { Ok(base::Transaction { - data: xt, + data: xt, + bytes, hash, priority, requires, @@ -116,12 +141,12 @@ impl Pool { valid_till: block_number.as_().saturating_add(longevity), }) }, - TransactionValidity::Invalid => { - bail!(error::Error::from(error::ErrorKind::InvalidTransaction)) + TransactionValidity::Invalid(e) => { + bail!(error::Error::from(error::ErrorKind::InvalidTransaction(e))) }, - TransactionValidity::Unknown => { + TransactionValidity::Unknown(e) => { self.listener.write().invalid(&hash); - bail!(error::Error::from(error::ErrorKind::UnknownTransactionValidity)) + bail!(error::Error::from(error::ErrorKind::UnknownTransactionValidity(e))) }, } }) @@ -136,7 +161,42 @@ impl Pool { fire_events(&mut *listener, &imported); Ok(imported.hash().clone()) }) - .collect()) + .collect::>(); + + let removed = self.enforce_limits(); + + Ok(results.into_iter().map(|res| match res { + Ok(ref hash) if removed.contains(hash) => Err(error::Error::from(error::ErrorKind::ImmediatelyDropped).into()), + other => other, + }).collect()) + } + + fn enforce_limits(&self) -> HashSet> { + let status = self.pool.read().status(); + let ready_limit = &self.options.ready; + let future_limit = &self.options.future; + + if ready_limit.is_exceeded(status.ready, status.ready_bytes) + || future_limit.is_exceeded(status.future, status.future_bytes) { + // clean up the pool + let removed = { + let mut pool = self.pool.write(); + let removed = pool.enforce_limits(ready_limit, future_limit) + .into_iter().map(|x| x.hash.clone()).collect::>(); + // ban all removed transactions + self.rotator.ban(&std::time::Instant::now(), removed.iter().map(|x| x.clone())); + removed + }; + // run notifications + let mut listener = self.listener.write(); + for h in &removed { + listener.dropped(h, None); + } + + removed + } else { + Default::default() + } } /// Imports one unverified extrinsic to the pool @@ -146,15 +206,83 @@ impl Pool { /// Import a single extrinsic and starts to watch their progress in the pool. pub fn submit_and_watch(&self, at: &BlockId, xt: ExtrinsicFor) -> Result, BlockHash>, B::Error> { - let hash = self.api.hash(&xt); + let hash = self.api.hash_and_length(&xt).0; let watcher = self.listener.write().create_watcher(hash); self.submit_one(at, xt)?; Ok(watcher) } + /// Prunes ready transactions. + /// + /// Used to clear the pool from transactions 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 fn prune(&self, at: &BlockId, parent: &BlockId, extrinsics: &[ExtrinsicFor]) -> Result<(), B::Error> { + let mut tags = Vec::with_capacity(extrinsics.len()); + // Get details of all extrinsics that are already in the pool + let hashes = extrinsics.iter().map(|extrinsic| self.api.hash_and_length(extrinsic).0).collect::>(); + let in_pool = self.pool.read().by_hash(&hashes); + { + // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option)`) + let all = extrinsics.iter().zip(in_pool.iter()); + + for (extrinsic, existing_in_pool) in all { + match *existing_in_pool { + // reuse the tags for extrinsis that were found in the pool + Some(ref transaction) => { + tags.extend(transaction.provides.iter().cloned()); + }, + // if it's not found in the pool query the runtime at parent block + // to get validity info and tags that the extrinsic provides. + None => { + let validity = self.api.validate_transaction(parent, extrinsic.clone()); + match validity { + Ok(TransactionValidity::Valid { mut provides, .. }) => { + tags.append(&mut provides); + }, + // silently ignore invalid extrinsics, + // cause they might just be inherent + _ => {} + } + }, + } + } + } + + self.prune_tags(at, tags, in_pool.into_iter().filter_map(|x| x).map(|x| x.hash.clone()))?; + + Ok(()) + } + /// Prunes ready transactions that provide given list of tags. - pub fn prune_tags(&self, at: &BlockId, tags: impl IntoIterator) -> Result<(), B::Error> { + /// + /// Given tags are assumed to be always provided now, so all transactions + /// 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 transactions in the pool that: + /// 1. Provide that tag directly + /// 2. Are a dependency of pruned transaction. + /// + /// By removing predecessor transactions as well we might actually end up + /// pruning too much, so all removed transactions are reverified against + /// the runtime (`validate_transaction`) to make sure they are invalid. + /// + /// However we avoid revalidating transactions that are contained within + /// the second parameter of `known_imported_hashes`. These transactions + /// (if pruned) are not revalidated and become temporarily banned to + /// prevent importing them in the (near) future. + pub fn prune_tags( + &self, + at: &BlockId, + tags: impl IntoIterator, + known_imported_hashes: impl IntoIterator> + Clone, + ) -> Result<(), B::Error> { + // Perform tag-based pruning in the base pool let status = self.pool.write().prune_tags(tags); + // Notify event listeners of all transactions + // that were promoted to `Ready` or were dropped. { let mut listener = self.listener.write(); for promoted in &status.promoted { @@ -164,26 +292,37 @@ impl Pool { listener.dropped(f, None); } } + // make sure that we don't revalidate extrinsics that were part of the recently + // imported block. This is especially important for UTXO-like chains cause the + // inputs are pruned so such transaction would go to future again. + self.rotator.ban(&std::time::Instant::now(), known_imported_hashes.clone().into_iter()); + // try to re-submit pruned transactions since some of them might be still valid. + // note that `known_imported_hashes` will be rejected here due to temporary ban. let hashes = status.pruned.iter().map(|tx| tx.hash.clone()).collect::>(); let results = self.submit_at(at, status.pruned.into_iter().map(|tx| tx.data.clone()))?; - // Fire mined event for transactions that became invalid. + + // Collect the hashes of transactions that now became invalid (meaning that they are succesfuly pruned). let hashes = results.into_iter().enumerate().filter_map(|(idx, r)| match r.map_err(error::IntoPoolError::into_pool_error) { Err(Ok(err)) => match err.kind() { - error::ErrorKind::InvalidTransaction => Some(hashes[idx].clone()), + error::ErrorKind::InvalidTransaction(_) => Some(hashes[idx].clone()), _ => None, }, _ => None, }); + // Fire `pruned` notifications for collected hashes and make sure to include + // `known_imported_hashes` since they were just imported as part of the block. + let hashes = hashes.chain(known_imported_hashes.into_iter()); { let header_hash = self.api.block_id_to_hash(at)? .ok_or_else(|| error::ErrorKind::Msg(format!("Invalid block id: {:?}", at)).into())?; let mut listener = self.listener.write(); for h in hashes { - listener.pruned(header_hash, &h) + listener.pruned(header_hash, &h); } } - // clear old transactions + // perform regular cleanup of old transactions in the pool + // and update temporary bans. self.clear_stale(at)?; Ok(()) } @@ -222,14 +361,12 @@ impl Pool { Ok(()) } -} -impl Pool { /// Create a new transaction pool. - /// TODO [ToDr] Options - pub fn new(_options: Options, api: B) -> Self { + pub fn new(options: Options, api: B) -> Self { Pool { api, + options, listener: Default::default(), pool: Default::default(), import_notification_sinks: Default::default(), @@ -256,7 +393,7 @@ impl Pool { pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { // temporarily ban invalid transactions debug!(target: "txpool", "Banning invalid transactions: {:?}", hashes); - self.rotator.ban(&time::Instant::now(), hashes); + self.rotator.ban(&time::Instant::now(), hashes.iter().cloned()); let invalid = self.pool.write().remove_invalid(hashes); @@ -279,8 +416,9 @@ impl Pool { } /// Returns transaction hash - pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { - self.api.hash(xt) + #[cfg(test)] + fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { + self.api.hash_and_length(xt).0 } } @@ -314,7 +452,10 @@ fn fire_events( mod tests { use super::*; use futures::Stream; - use test_runtime::{Block, Extrinsic, Transfer}; + use parity_codec::Encode; + use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; + use assert_matches::assert_matches; + use crate::watcher; #[derive(Debug, Default)] struct TestApi; @@ -325,12 +466,12 @@ mod tests { type Error = error::Error; /// Verify extrinsic at given block. - fn validate_transaction(&self, at: &BlockId, uxt: &ExtrinsicFor) -> Result { + fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result { let block_number = self.block_id_to_number(at)?.unwrap(); - let nonce = uxt.transfer.nonce; + let nonce = uxt.transfer().nonce; if nonce < block_number { - Ok(TransactionValidity::Invalid) + Ok(TransactionValidity::Invalid(0)) } else { Ok(TransactionValidity::Valid { priority: 4, @@ -352,22 +493,23 @@ mod tests { /// 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((*num).into()), + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), BlockId::Hash(_) => None, }) } /// Hash the extrinsic. - fn hash(&self, uxt: &ExtrinsicFor) -> Self::Hash { - (uxt.transfer.from.to_low_u64_be() << 5) + uxt.transfer.nonce + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + let len = uxt.encode().len(); + ( + (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, + len + ) } } fn uxt(transfer: Transfer) -> Extrinsic { - Extrinsic { - transfer, - signature: Default::default(), - } + Extrinsic::Transfer(transfer, Default::default()) } fn pool() -> Pool { @@ -382,8 +524,8 @@ mod tests { // when let hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -397,14 +539,14 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); // when - pool.rotator.ban(&time::Instant::now(), &[pool.hash_of(&uxt)]); + pool.rotator.ban(&time::Instant::now(), vec![pool.hash_of(&uxt)]); let res = pool.submit_one(&BlockId::Number(0), uxt); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); @@ -422,21 +564,21 @@ mod tests { // when let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); // future doesn't count let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -458,20 +600,20 @@ mod tests { // given let pool = pool(); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); let hash3 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -489,6 +631,84 @@ mod tests { assert!(pool.rotator.is_banned(&hash3)); } + #[test] + fn should_ban_mined_transactions() { + // given + let pool = pool(); + let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + })).unwrap(); + + // when + pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()]).unwrap(); + + // then + assert!(pool.rotator.is_banned(&hash1)); + } + + #[test] + fn should_limit_futures() { + // given + let limit = Limit { + count: 100, + total_bytes: 200, + }; + let pool = Pool::new(Options { + ready: limit.clone(), + future: limit.clone(), + }, TestApi::default()); + + let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + })).unwrap(); + assert_eq!(pool.status().future, 1); + + // when + let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 10, + })).unwrap(); + + // then + assert_eq!(pool.status().future, 1); + assert!(pool.rotator.is_banned(&hash1)); + assert!(!pool.rotator.is_banned(&hash2)); + } + + #[test] + fn should_error_if_reject_immediately() { + // given + let limit = Limit { + count: 100, + total_bytes: 10, + }; + let pool = Pool::new(Options { + ready: limit.clone(), + future: limit.clone(), + }, TestApi::default()); + + // when + pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + })).unwrap_err(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } + + mod listener { use super::*; @@ -497,8 +717,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -506,14 +726,39 @@ mod tests { assert_eq!(pool.status().future, 0); // when - pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]]).unwrap(); + pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![]).unwrap(); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); // then let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Finalised(2.into())))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2).into())))); + assert_eq!(stream.next(), None); + } + + #[test] + fn should_trigger_ready_and_finalised_when_pruning_via_hash() { + // given + let pool = pool(); + let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + })).unwrap(); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + + // when + pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64]).unwrap(); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // then + let mut stream = watcher.into_stream().wait(); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2).into())))); assert_eq!(stream.next(), None); } @@ -522,8 +767,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); @@ -532,8 +777,8 @@ mod tests { // when pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -541,8 +786,8 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Future))); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Future))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); } #[test] @@ -550,8 +795,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -564,8 +809,8 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Invalid))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Invalid))); assert_eq!(stream.next(), None); } @@ -574,8 +819,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: 1.into(), - to: 2.into(), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -591,8 +836,45 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(::watcher::Status::Broadcast(peers)))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Broadcast(peers)))); + } + + #[test] + fn should_trigger_dropped() { + // given + let limit = Limit { + count: 1, + total_bytes: 1000, + }; + let pool = Pool::new(Options { + ready: limit.clone(), + future: limit.clone(), + }, TestApi::default()); + + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }); + let watcher = pool.submit_and_watch(&BlockId::Number(0), xt).unwrap(); + assert_eq!(pool.status().ready, 1); + + // when + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(1)), + amount: 4, + nonce: 1, + }); + pool.submit_one(&BlockId::Number(1), xt).unwrap(); + assert_eq!(pool.status().ready, 1); + + // then + let mut stream = watcher.into_stream().wait(); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Dropped))); } } } diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index 1a531b3f4902fc72ecc06f357722b198adbb5508..5a9ea11e50a2c7731d3d2c154cbc9244cf80ccba 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,19 +22,26 @@ use std::{ }; use serde::Serialize; +use log::debug; +use error_chain::bail; use parking_lot::RwLock; use sr_primitives::traits::Member; use sr_primitives::transaction_validity::{ TransactionTag as Tag, }; -use error; -use future::WaitingTransaction; -use base_pool::Transaction; +use crate::error; +use crate::future::WaitingTransaction; +use crate::base_pool::Transaction; +/// An in-pool transaction reference. +/// +/// Should be cheap to clone. #[derive(Debug)] pub struct TransactionRef { + /// The actual transaction data. pub transaction: Arc>, + /// Unique id when transaction was inserted into the pool. pub insertion_id: u64, } @@ -69,7 +76,7 @@ impl PartialEq for TransactionRef { impl Eq for TransactionRef {} #[derive(Debug)] -struct ReadyTx { +pub struct ReadyTx { /// A reference to a transaction pub transaction: TransactionRef, /// A list of transactions that get unlocked by this one @@ -150,6 +157,7 @@ impl ReadyTransactions { /// /// The transaction needs to have all tags satisfied (be ready) by transactions /// that are in this queue. + /// Returns transactions that were replaced by the one imported. pub fn import( &mut self, tx: WaitingTransaction, @@ -160,17 +168,17 @@ impl ReadyTransactions { self.insertion_id += 1; let insertion_id = self.insertion_id; let hash = tx.transaction.hash.clone(); - let tx = tx.transaction; + let transaction = tx.transaction; - let replaced = self.replace_previous(&tx)?; + let replaced = self.replace_previous(&transaction)?; let mut goes_to_best = true; let mut ready = self.ready.write(); // Add links to transactions that unlock the current one - for tag in &tx.requires { + for tag in &transaction.requires { // Check if the transaction that satisfies the tag is still in the queue. if let Some(other) = self.provided_tags.get(tag) { - let mut tx = ready.get_mut(other).expect(HASH_READY); + let tx = ready.get_mut(other).expect(HASH_READY); tx.unlocks.push(hash.clone()); // this transaction depends on some other, so it doesn't go to best directly. goes_to_best = false; @@ -178,13 +186,13 @@ impl ReadyTransactions { } // update provided_tags - for tag in tx.provides.clone() { - self.provided_tags.insert(tag, hash.clone()); + for tag in &transaction.provides { + self.provided_tags.insert(tag.clone(), hash.clone()); } let transaction = TransactionRef { insertion_id, - transaction: Arc::new(tx), + transaction }; // insert to best if it doesn't require any other transaction to be included before it @@ -202,11 +210,27 @@ impl ReadyTransactions { Ok(replaced) } + /// Fold a list of ready transactions to compute a single value. + pub fn fold, &ReadyTx) -> Option>(&mut self, f: F) -> Option { + self.ready + .read() + .values() + .fold(None, f) + } + /// Returns true if given hash is part of the queue. pub fn contains(&self, hash: &Hash) -> bool { self.ready.read().contains_key(hash) } + /// Retrieve transaction by hash + pub fn by_hash(&self, hashes: &[Hash]) -> Vec>>> { + let ready = self.ready.read(); + hashes.iter().map(|hash| { + ready.get(hash).map(|x| x.transaction.transaction.clone()) + }).collect() + } + /// Removes invalid transactions from the ready pool. /// /// NOTE removing a transaction will also cause a removal of all transactions that depend on that one @@ -391,6 +415,10 @@ impl ReadyTransactions { self.ready.read().len() } + /// Returns sum of encoding lengths of all transactions in this queue. + pub fn bytes(&self) -> usize { + self.ready.read().values().fold(0, |acc, tx| acc + tx.transaction.transaction.bytes) + } } pub struct BestIterator { @@ -466,6 +494,7 @@ mod tests { fn tx(id: u8) -> Transaction> { Transaction { data: vec![id], + bytes: 1, hash: id as u64, priority: 1, valid_till: 2, @@ -524,6 +553,7 @@ mod tests { tx4.provides = vec![]; let tx5 = Transaction { data: vec![5], + bytes: 1, hash: 5, priority: 1, valid_till: u64::max_value(), // use the max_value() here for testing. diff --git a/core/transaction-pool/graph/src/rotator.rs b/core/transaction-pool/graph/src/rotator.rs index e5ba7ccde654062ddb118e3f4cd3eb08127ff8b7..2ca51ef74e880007285ec8b0f279019fb2b5fa3f 100644 --- a/core/transaction-pool/graph/src/rotator.rs +++ b/core/transaction-pool/graph/src/rotator.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,11 +22,12 @@ use std::{ collections::HashMap, hash, + iter, time::{Duration, Instant}, }; use parking_lot::RwLock; -use base_pool::Transaction; +use crate::base_pool::Transaction; /// Expected size of the banned extrinsics cache. const EXPECTED_SIZE: usize = 2048; @@ -58,11 +59,11 @@ impl PoolRotator { } /// Bans given set of hashes. - pub fn ban(&self, now: &Instant, hashes: &[Hash]) { + pub fn ban(&self, now: &Instant, hashes: impl IntoIterator) { let mut banned = self.banned_until.write(); for hash in hashes { - banned.insert(hash.clone(), *now + self.ban_time); + banned.insert(hash, *now + self.ban_time); } if banned.len() > 2 * EXPECTED_SIZE { @@ -83,7 +84,7 @@ impl PoolRotator { return false; } - self.ban(now, &[xt.hash.clone()]); + self.ban(now, iter::once(xt.hash.clone())); true } @@ -113,6 +114,7 @@ mod tests { let hash = 5u64; let tx = Transaction { data: (), + bytes: 1, hash: hash.clone(), priority: 5, valid_till: 1, @@ -177,6 +179,7 @@ mod tests { let hash = i; Transaction { data: (), + bytes: 2, hash, priority: 5, valid_till, diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs index 7ca4a6628341beb9c6425dfc80433b81dfa28df5..419a98ca79230085f4dd2f5125224478c1661dba 100644 --- a/core/transaction-pool/graph/src/watcher.rs +++ b/core/transaction-pool/graph/src/watcher.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ use futures::{ Stream, sync::mpsc, }; +use serde_derive::{Serialize, Deserialize}; /// Possible extrinsic status events #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs index a29010b50c8c1a35eb4ab7d711b35943438154ee..84475376fe6377ff6c71afd2499bb941bd453865 100644 --- a/core/transaction-pool/src/api.rs +++ b/core/transaction-pool/src/api.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -34,7 +34,7 @@ use sr_primitives::{ transaction_validity::TransactionValidity, }; -use error; +use crate::error; /// The transaction pool logic pub struct ChainApi { @@ -63,11 +63,10 @@ impl txpool::ChainApi for ChainApi where type Hash = H256; type Error = error::Error; - fn validate_transaction(&self, at: &BlockId, uxt: &txpool::ExtrinsicFor) -> error::Result { + fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { Ok(self.client.runtime_api().validate_transaction(at, uxt)?) } - // TODO [toDr] Use proper lbock number type fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { Ok(self.client.block_number_from_id(at)?) } @@ -76,7 +75,9 @@ impl txpool::ChainApi for ChainApi where Ok(self.client.block_hash_from_id(at)?) } - fn hash(&self, ex: &txpool::ExtrinsicFor) -> Self::Hash { - Blake2Hasher::hash(&ex.encode()) + fn hash_and_length(&self, ex: &txpool::ExtrinsicFor) -> (Self::Hash, usize) { + ex.using_encoded(|x| { + (Blake2Hasher::hash(x), x.len()) + }) } } diff --git a/core/transaction-pool/src/error.rs b/core/transaction-pool/src/error.rs index 009c80a3155bfbd35e5e47ff563aedcb1461f4b1..e1223c537de3731446840f1176489f2ebfec0d2e 100644 --- a/core/transaction-pool/src/error.rs +++ b/core/transaction-pool/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,6 +18,9 @@ use client; use txpool; +use error_chain::{ + error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind +}; error_chain! { links { diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index 44f63ed37d299a593b486beda9855325d96dd1df..1899c601b2fdbbc8b73aac524c5bd030026615e5 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,21 +19,6 @@ #![warn(missing_docs)] #![warn(unused_extern_crates)] -extern crate parity_codec; -extern crate sr_primitives; -extern crate substrate_client as client; -extern crate substrate_primitives; - -pub extern crate substrate_transaction_graph as txpool; - -#[macro_use] -extern crate error_chain; - -#[cfg(test)] -extern crate substrate_test_client as test_client; -#[cfg(test)] -extern crate substrate_keyring as keyring; - mod api; #[cfg(test)] mod tests; @@ -41,3 +26,4 @@ mod tests; pub mod error; pub use api::ChainApi; +pub use txpool; diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs index e02bf054014b427ee7008b19c88f07d34e2fb7b3..cab44f49cc79c4b812c513a2cc197b0a5e00d01d 100644 --- a/core/transaction-pool/src/tests.rs +++ b/core/transaction-pool/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,10 +17,9 @@ use super::*; -use keyring::Keyring::{self, *}; use parity_codec::Encode; use txpool::{self, Pool}; -use test_client::runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}; +use test_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; use sr_primitives::{ generic::{self, BlockId}, traits::{Hash as HashT, BlakeTwo256}, @@ -40,20 +39,20 @@ impl txpool::ChainApi for TestApi { type Hash = Hash; type Error = error::Error; - fn validate_transaction(&self, at: &BlockId, uxt: &txpool::ExtrinsicFor) -> error::Result { + fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { let expected = index(at); - let requires = if expected == uxt.transfer.nonce { + let requires = if expected == uxt.transfer().nonce { vec![] } else { - vec![vec![uxt.transfer.nonce as u8 - 1]] + vec![vec![uxt.transfer().nonce as u8 - 1]] }; - let provides = vec![vec![uxt.transfer.nonce as u8]]; + let provides = vec![vec![uxt.transfer().nonce as u8]]; Ok(TransactionValidity::Valid { priority: 1, requires, provides, - longevity: 64 + longevity: 64, }) } @@ -68,8 +67,9 @@ impl txpool::ChainApi for TestApi { }) } - fn hash(&self, ex: &txpool::ExtrinsicFor) -> Self::Hash { - BlakeTwo256::hash(&ex.encode()) + fn hash_and_length(&self, ex: &txpool::ExtrinsicFor) -> (Self::Hash, usize) { + let encoded = ex.encode(); + (BlakeTwo256::hash(&encoded), encoded.len()) } } @@ -85,18 +85,15 @@ fn number_of(at: &BlockId) -> u64 { } } -fn uxt(who: Keyring, nonce: Index) -> Extrinsic { +fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { let transfer = Transfer { - from: who.to_raw_public().into(), + from: who.into(), to: AccountId::default(), nonce, amount: 1, }; let signature = transfer.using_encoded(|e| who.sign(e)); - Extrinsic { - transfer, - signature: signature.into(), - } + Extrinsic::Transfer(transfer, signature.into()) } fn pool() -> Pool { @@ -109,7 +106,7 @@ fn submission_should_work() { assert_eq!(209, index(&BlockId::number(0))); pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209]); } @@ -119,7 +116,7 @@ fn multiple_submission_should_work() { pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); } @@ -128,7 +125,7 @@ fn early_nonce_should_be_culled() { let pool = pool(); pool.submit_one(&BlockId::number(0), uxt(Alice, 208)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); } @@ -137,11 +134,11 @@ fn late_nonce_should_be_queued() { let pool = pool(); pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); } @@ -151,12 +148,12 @@ fn prune_tags_should_work() { pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); - pool.prune_tags(&BlockId::number(1), vec![vec![209]]).unwrap(); + pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![]).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![210]); } @@ -169,7 +166,7 @@ fn should_ban_invalid_transactions() { pool.submit_one(&BlockId::number(0), uxt.clone()).unwrap_err(); // when - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer.nonce).collect(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); // then diff --git a/core/trie/Cargo.toml b/core/trie/Cargo.toml index 955c6b95cd4e232f420dd501ec89affad07abbf8..9d93cbe599b6558d4f7ec5fc2f768c924efacf8a 100644 --- a/core/trie/Cargo.toml +++ b/core/trie/Cargo.toml @@ -5,24 +5,25 @@ authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-codec node format" repository = "https://github.com/paritytech/parity-common" license = "GPL-3.0" +edition = "2018" [[bench]] name = "bench" harness = false [dependencies] -parity-codec = { version = "2.1" } -hash-db = { git = "https://github.com/paritytech/trie", default-features = false } -trie-db = { git = "https://github.com/paritytech/trie", optional = true } -trie-root = { git = "https://github.com/paritytech/trie", default-features = false } -memory-db = { git = "https://github.com/paritytech/trie", optional = true } +codec = { package = "parity-codec", version = "3.2" } +hash-db = { version = "0.11", default-features = false } +trie-db = { version = "0.11", optional = true } +trie-root = { version = "0.11", default-features = false } +memory-db = { version = "0.11", optional = true } [dev-dependencies] substrate-primitives = { path = "../primitives" } -trie-bench = { git = "https://github.com/paritytech/trie" } -trie-standardmap = { git = "https://github.com/paritytech/trie" } -keccak-hasher = { git = "https://github.com/paritytech/trie" } -criterion = "0.1.2" +trie-bench = { version = "0.11" } +trie-standardmap = { version = "0.11" } +keccak-hasher = { version = "0.11" } +criterion = "0.2" hex-literal = "0.1.0" [features] @@ -32,4 +33,4 @@ std = [ "memory-db", "trie-db", "trie-root/std" -] \ No newline at end of file +] diff --git a/core/trie/benches/bench.rs b/core/trie/benches/bench.rs index 75fe648b8f5cdb9628957733d2e900ab12c67bca..179dc6aaf8413c0c85e88f3c95ecda7d3e089d5b 100644 --- a/core/trie/benches/bench.rs +++ b/core/trie/benches/bench.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -14,17 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -#[macro_use] -extern crate criterion; -use criterion::Criterion; +use criterion::{Criterion, criterion_group, criterion_main}; criterion_group!(benches, benchmark); criterion_main!(benches); -extern crate substrate_primitives; -extern crate keccak_hasher; -extern crate substrate_trie; -extern crate trie_bench; - fn benchmark(c: &mut Criterion) { trie_bench::standard_benchmark::< substrate_primitives::Blake2Hasher, diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs index 3b9791e99a13b413a2758e7e4bcf0df615d0d2b7..071f49d87551490531f2d9dfa7fd89552fed652f 100644 --- a/core/trie/src/lib.rs +++ b/core/trie/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -16,21 +16,7 @@ //! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie"). -// TODO: no_std - -extern crate trie_root; -extern crate parity_codec as codec; -extern crate trie_db; -extern crate hash_db; -extern crate memory_db; - -#[cfg(test)] -extern crate substrate_primitives; -#[cfg(test)] -extern crate trie_standardmap; -#[cfg(test)] -#[macro_use] -extern crate hex_literal; +// FIXME: no_std - https://github.com/paritytech/substrate/issues/1574 mod error; mod node_header; @@ -54,6 +40,8 @@ pub trait AsHashDB: hash_db::AsHashDB {} impl> AsHashDB for T {} /// As in `hash_db`, but less generic, trait exposed. pub type HashDB<'a, H> = hash_db::HashDB + 'a; +/// As in `hash_db`, but less generic, trait exposed. +pub type PlainDB<'a, K> = hash_db::PlainDB + 'a; /// As in `memory_db`, but less generic, trait exposed. pub type MemoryDB = memory_db::MemoryDB; @@ -74,18 +62,23 @@ pub fn trie_root(input: I) -> H::Out where } /// Determine a trie root given a hash DB and delta values. -pub fn delta_trie_root(db: &mut HashDB, mut root: H::Out, delta: I) -> Result>> where +pub fn delta_trie_root( + db: &mut DB, + mut root: H::Out, + delta: I +) -> Result>> where I: IntoIterator)>, A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, + DB: hash_db::HashDB, { { - let mut trie = TrieDBMut::::from_existing(db, &mut root)?; + let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?; for (key, change) in delta { match change { Some(val) => trie.insert(key.as_ref(), val.as_ref())?, - None => trie.remove(key.as_ref())?, // TODO: archive mode + None => trie.remove(key.as_ref())?, }; } } @@ -94,13 +87,22 @@ pub fn delta_trie_root(db: &mut HashDB, mut root: H::Out, } /// Read a value from the trie. -pub fn read_trie_value(db: &HashDB, root: &H::Out, key: &[u8]) -> Result>, Box>> { - Ok(TrieDB::::new(db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) +pub fn read_trie_value>( + db: &DB, + root: &H::Out, + key: &[u8] +) -> Result>, Box>> { + Ok(TrieDB::::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) } /// Read a value from the trie with given Query. -pub fn read_trie_value_with>(db: &HashDB, root: &H::Out, key: &[u8], query: Q) -> Result>, Box>> { - Ok(TrieDB::::new(db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) +pub fn read_trie_value_with, DB: hash_db::HashDBRef>( + db: &DB, + root: &H::Out, + key: &[u8], + query: Q +) -> Result>, Box>> { + Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) } /// Determine a trie root node's data given its ordered contents, closed form. @@ -116,10 +118,11 @@ pub fn unhashed_trie(input: I) -> Vec where /// compact-encoded index (using `parity-codec` crate). pub fn ordered_trie_root(input: I) -> H::Out where - I: IntoIterator + Iterator, + I: IntoIterator, A: AsRef<[u8]>, { trie_root::(input + .into_iter() .enumerate() .map(|(i, v)| (codec::Encode::encode(&codec::Compact(i as u32)), v)) ) @@ -150,21 +153,27 @@ pub fn child_trie_root(_storage_key: &[u8], input: I) -> Vec } /// Determine a child trie root given a hash DB and delta values. H is the default hasher, but a generic implementation may ignore this type parameter and use other hashers. -pub fn child_delta_trie_root(_storage_key: &[u8], db: &mut HashDB, root_vec: Vec, delta: I) -> Result, Box>> where +pub fn child_delta_trie_root( + _storage_key: &[u8], + db: &mut DB, + root_vec: Vec, + delta: I +) -> Result, Box>> where I: IntoIterator)>, A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, + DB: hash_db::HashDB + hash_db::PlainDB, { let mut root = H::Out::default(); root.as_mut().copy_from_slice(&root_vec); // root is fetched from DB, not writable by runtime, so it's always valid. { - let mut trie = TrieDBMut::::from_existing(db, &mut root)?; + let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?; for (key, change) in delta { match change { Some(val) => trie.insert(key.as_ref(), val.as_ref())?, - None => trie.remove(key.as_ref())?, // TODO: archive mode + None => trie.remove(key.as_ref())?, }; } } @@ -173,11 +182,18 @@ pub fn child_delta_trie_root(_storage_key: &[u8], db: &mut H } /// Call `f` for all keys in a child trie. -pub fn for_keys_in_child_trie(_storage_key: &[u8], db: &HashDB, root_slice: &[u8], mut f: F) -> Result<(), Box>> { +pub fn for_keys_in_child_trie( + _storage_key: &[u8], + db: &DB, + root_slice: &[u8], + mut f: F +) -> Result<(), Box>> where + DB: hash_db::HashDBRef + hash_db::PlainDBRef, +{ let mut root = H::Out::default(); root.as_mut().copy_from_slice(root_slice); // root is fetched from DB, not writable by runtime, so it's always valid. - let trie = TrieDB::::new(db, &root)?; + let trie = TrieDB::::new(&*db, &root)?; let iter = trie.iter()?; for x in iter { @@ -189,8 +205,14 @@ pub fn for_keys_in_child_trie(_storage_key: &[u8], d } /// Record all keys for a given root. -pub fn record_all_keys(db: &HashDB, root: &H::Out, recorder: &mut Recorder) -> Result<(), Box>> { - let trie = TrieDB::::new(db, root)?; +pub fn record_all_keys( + db: &DB, + root: &H::Out, + recorder: &mut Recorder +) -> Result<(), Box>> where + DB: hash_db::HashDBRef +{ + let trie = TrieDB::::new(&*db, root)?; let iter = trie.iter()?; for x in iter { @@ -206,19 +228,34 @@ pub fn record_all_keys(db: &HashDB, root: &H::Out, recorder: &mut } /// Read a value from the child trie. -pub fn read_child_trie_value(_storage_key: &[u8], db: &HashDB, root_slice: &[u8], key: &[u8]) -> Result>, Box>> { +pub fn read_child_trie_value( + _storage_key: &[u8], + db: &DB, + root_slice: &[u8], + key: &[u8] +) -> Result>, Box>> where + DB: hash_db::HashDBRef + hash_db::PlainDBRef, +{ let mut root = H::Out::default(); root.as_mut().copy_from_slice(root_slice); // root is fetched from DB, not writable by runtime, so it's always valid. - Ok(TrieDB::::new(db, &root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) + Ok(TrieDB::::new(&*db, &root)?.get(key).map(|x| x.map(|val| val.to_vec()))?) } /// Read a value from the child trie with given query. -pub fn read_child_trie_value_with>(_storage_key: &[u8], db: &HashDB, root_slice: &[u8], key: &[u8], query: Q) -> Result>, Box>> { +pub fn read_child_trie_value_with, DB>( + _storage_key: &[u8], + db: &DB, + root_slice: &[u8], + key: &[u8], + query: Q +) -> Result>, Box>> where + DB: hash_db::HashDBRef + hash_db::PlainDBRef, +{ let mut root = H::Out::default(); root.as_mut().copy_from_slice(root_slice); // root is fetched from DB, not writable by runtime, so it's always valid. - Ok(TrieDB::::new(db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) + Ok(TrieDB::::new(&*db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) } // Utilities (not exported): @@ -280,6 +317,7 @@ mod tests { use hash_db::{HashDB, Hasher}; use trie_db::{DBValue, TrieMut, Trie}; use trie_standardmap::{Alphabet, ValueMode, StandardMap}; + use hex_literal::{hex, hex_impl}; fn check_equivalent(input: &Vec<(&[u8], &[u8])>) { { diff --git a/core/trie/src/node_codec.rs b/core/trie/src/node_codec.rs index 7cc888be7c9c7d5ce9e15cf269b057df36a0eba8..b73519e87f4b7688a0f3fd3ec205c660b3015f67 100644 --- a/core/trie/src/node_codec.rs +++ b/core/trie/src/node_codec.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ use std::marker::PhantomData; use codec::{Encode, Decode, Compact}; use hash_db::Hasher; use trie_db::{self, DBValue, NibbleSlice, node::Node, ChildReference}; -use error::Error; +use crate::error::Error; use super::{EMPTY_TRIE, LEAF_NODE_OFFSET, LEAF_NODE_BIG, EXTENSION_NODE_OFFSET, EXTENSION_NODE_BIG, take, partial_to_key, node_header::NodeHeader, branch_node}; @@ -95,14 +95,14 @@ impl trie_db::NodeCodec for NodeCodec { vec![EMPTY_TRIE] } - // TODO: refactor this so that `partial` isn't already encoded with HPE. Should just be an `impl Iterator`. + // FIXME: refactor this so that `partial` isn't already encoded with HPE. Should just be an `impl Iterator`. fn leaf_node(partial: &[u8], value: &[u8]) -> Vec { let mut output = partial_to_key(partial, LEAF_NODE_OFFSET, LEAF_NODE_BIG); value.encode_to(&mut output); output } - // TODO: refactor this so that `partial` isn't already encoded with HPE. Should just be an `impl Iterator`. + // FIXME: refactor this so that `partial` isn't already encoded with HPE. Should just be an `impl Iterator`. fn ext_node(partial: &[u8], child: ChildReference) -> Vec { let mut output = partial_to_key(partial, EXTENSION_NODE_OFFSET, EXTENSION_NODE_BIG); match child { diff --git a/core/trie/src/node_header.rs b/core/trie/src/node_header.rs index e337661bfdc1dfdf9e568132922e576ad9733330..4f7617c0684bb881d970c177d940559d0760d9a9 100644 --- a/core/trie/src/node_header.rs +++ b/core/trie/src/node_header.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -34,10 +34,10 @@ impl Encode for NodeHeader { fn encode_to(&self, output: &mut T) { match self { NodeHeader::Null => output.push_byte(EMPTY_TRIE), - + NodeHeader::Branch(true) => output.push_byte(BRANCH_NODE_WITH_VALUE), NodeHeader::Branch(false) => output.push_byte(BRANCH_NODE_NO_VALUE), - + NodeHeader::Leaf(nibble_count) if *nibble_count < LEAF_NODE_THRESHOLD as usize => output.push_byte(LEAF_NODE_OFFSET + *nibble_count as u8), NodeHeader::Leaf(nibble_count) => { @@ -72,8 +72,6 @@ impl Decode for NodeHeader { BRANCH_NODE_NO_VALUE => NodeHeader::Branch(false), // 254 BRANCH_NODE_WITH_VALUE => NodeHeader::Branch(true), // 255 - - _ => unreachable!(), }) } } diff --git a/core/trie/src/trie_stream.rs b/core/trie/src/trie_stream.rs index 3c8291389cca38fdeb6bf0bf8bfd0fd6c85cd271..e97516103d7157356d7bef117512028499074366 100644 --- a/core/trie/src/trie_stream.rs +++ b/core/trie/src/trie_stream.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// Copyright 2015-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -67,34 +67,25 @@ impl trie_root::TrieStream for TrieStream { fn append_leaf(&mut self, key: &[u8], value: &[u8]) { self.buffer.extend(fuse_nibbles_node(key, true)); - // OPTIMISATION: I'd like to do `hpe.encode_to(&mut self.buffer);` here; need an `impl<'a> Encode for impl Iterator + 'a`? value.encode_to(&mut self.buffer); } fn begin_branch(&mut self, maybe_value: Option<&[u8]>, has_children: impl Iterator) { -// println!("[begin_branch] pushing BRANCH_NODE"); self.buffer.extend(&branch_node(maybe_value.is_some(), has_children)); // Push the value if one exists. if let Some(value) = maybe_value { value.encode_to(&mut self.buffer); } -// println!("[begin_branch] buffer so far: {:#x?}", self.buffer); } fn append_extension(&mut self, key: &[u8]) { self.buffer.extend(fuse_nibbles_node(key, false)); } fn append_substream(&mut self, other: Self) { let data = other.out(); -// println!("[append_substream] START own buffer: {:x?}", self.buffer); -// println!("[append_substream] START other buffer: {:x?}", data); match data.len() { 0...31 => { -// println!("[append_substream] appending data, because data.len() = {}", data.len()); data.encode_to(&mut self.buffer) }, _ => { -// println!("[append_substream] would have hashed, because data.len() = {}", data.len()); -// data.encode_to(&mut self.buffer) - // TODO: re-enable hashing before merging H::hash(&data).as_ref().encode_to(&mut self.buffer) } } diff --git a/core/util/fork-tree/Cargo.toml b/core/util/fork-tree/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4098fb80fad283d1eeab59f4b87ea8a8d704f63b --- /dev/null +++ b/core/util/fork-tree/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "fork-tree" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +parity-codec = { version = "3.2", features = ["derive"] } diff --git a/core/util/fork-tree/src/lib.rs b/core/util/fork-tree/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..71c83f57ca48791dcf44770886e881daeadb0246 --- /dev/null +++ b/core/util/fork-tree/src/lib.rs @@ -0,0 +1,791 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utility library for managing tree-like ordered data with logic for pruning +//! the tree while finalizing nodes. + +#![warn(missing_docs)] + +use std::fmt; +use parity_codec::{Decode, Encode}; + +/// Error occured when interating 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 fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use std::error::Error; + write!(f, "{}", self.description()) + } +} + +impl std::error::Error for Error { + fn description(&self) -> &str { + match *self { + Error::Duplicate => "Hash already exists in Tree", + Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first", + Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node", + Error::Client(ref err) => err.description(), + } + } + + fn cause(&self) -> Option<&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, +} + +/// 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 ForkTree where + H: PartialEq, + N: Ord, +{ + /// Create a new empty tree. + pub fn new() -> ForkTree { + ForkTree { + roots: Vec::new(), + best_finalized_number: None, + } + } + + /// 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. + pub fn import( + &mut self, + mut hash: H, + mut number: N, + mut data: V, + is_descendent_of: &F, + ) -> Result> + 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); + } + } + + for root in self.roots.iter_mut() { + if root.hash == hash { + return Err(Error::Duplicate); + } + + match root.import(hash, number, data, is_descendent_of)? { + Some((h, n, d)) => { + hash = h; + number = n; + data = d; + }, + None => return Ok(false), + } + } + + self.roots.push(Node { + data, + hash: hash, + number: number, + children: Vec::new(), + }); + + Ok(true) + } + + /// 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)) + } + + fn node_iter(&self) -> impl Iterator> { + ForkTreeIterator { stack: self.roots.iter().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)) + } + + /// 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 { + if let Some(position) = self.roots.iter().position(|node| node.hash == *hash) { + let node = self.roots.swap_remove(position); + self.roots = node.children; + self.best_finalized_number = Some(node.number); + return Some(node.data); + } + + None + } + + /// Finalize a node in the tree. This method will make sure that the node + /// being finalized is either an existing root (an 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; + self.roots.retain(|root| { + let retain = root.number > number && is_descendent_of(hash, &root.hash).unwrap_or(false); + + if !retain { + changed = true; + } + + retain + }); + + self.best_finalized_number = Some(number); + + if changed { + Ok(FinalizationResult::Changed(None)) + } else { + Ok(FinalizationResult::Unchanged) + } + } + + /// Checks if any node in the tree is finalized by either finalizing the + /// node itself or a child node that's not in the tree, guaranteeing that + /// the node being finalized isn't a descendent of any of the node's + /// 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 finalizes_any_with_descendent_if( + &self, + hash: &H, + number: N, + is_descendent_of: &F, + predicate: P, + ) -> Result> + 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 node.hash == *hash || is_descendent_of(&node.hash, hash)? { + if predicate(&node.data) { + for node in node.children.iter() { + if node.number <= number && is_descendent_of(&node.hash, &hash)? { + return Err(Error::UnfinalizedAncestor); + } + } + + return Ok(true); + } + } + } + + Ok(false) + } + + /// Finalize a root in the tree by either finalizing the node itself or a + /// child node that's not in the tree, guaranteeing that the node being + /// finalized isn't a descendent of any of the 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 root.hash == *hash || is_descendent_of(&root.hash, hash)? { + if predicate(&root.data) { + for node in root.children.iter() { + if node.number <= number && is_descendent_of(&node.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 + }); + + // if the block being finalized is earlier than a given root, then it + // must be its ancestor, otherwise we can prune the root. if there's a + // root at the same height then the hashes must match. otherwise the + // node being finalized is higher than the root so it must be its + // descendent (in this case the node wasn't finalized earlier presumably + // because the predicate didn't pass). + let mut changed = false; + self.roots.retain(|root| { + let retain = + root.number > number && is_descendent_of(hash, &root.hash).unwrap_or(false) || + root.number == number && root.hash == *hash || + is_descendent_of(&root.hash, hash).unwrap_or(false); + + if !retain { + changed = true; + } + + retain + }); + + 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), + } + } +} + +// Workaround for: https://github.com/rust-lang/rust/issues/34537 +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 { + pub fn import( + &mut self, + mut hash: H, + mut number: N, + mut data: V, + is_descendent_of: &F, + ) -> Result, Error> + where E: fmt::Debug, + F: Fn(&H, &H) -> Result, + { + if self.hash == hash { + return Err(Error::Duplicate); + }; + + if number <= self.number { return Ok(Some((hash, number, data))); } + + for node in self.children.iter_mut() { + match node.import(hash, number, data, is_descendent_of)? { + Some((h, n, d)) => { + hash = h; + number = n; + data = d; + }, + None => return Ok(None), + } + } + + if is_descendent_of(&self.hash, &hash)? { + self.children.push(Node { + data, + hash: hash, + number: number, + children: Vec::new(), + }); + + Ok(None) + } else { + Ok(Some((hash, number, data))) + } + } + } +} + +// Workaround for: https://github.com/rust-lang/rust/issues/34537 +use node_implementation::Node; + +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| { + self.stack.extend(node.children.iter()); + node + }) + } +} + +#[cfg(test)] +mod test { + use super::{FinalizationResult, ForkTree, Error}; + + #[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(); + + // + // - B - C - D - E + // / + // / - G + // / / + // A - F - H - I + // \ + // — J - K + // + let is_descendent_of = |base: &&str, block: &&str| -> Result { + let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + 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"), + ("G", _) => Ok(false), + ("H", b) => Ok(b == "I"), + ("I", _) => Ok(false), + ("J", b) => Ok(b == "K"), + ("K", _) => 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("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.clone(), n.clone())).collect::>(), + vec![("A", 1)], + ); + + // finalizing "A" opens up three possible forks + tree.finalize_root(&"A"); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).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.clone(), n.clone())).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.clone(), n.clone())).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.clone(), n.clone())).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.clone(), n.clone())).collect::>(), + vec![("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_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 == "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), + } + }; + + tree.import("A0", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); + tree.import("A1", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); + tree.import("D", 10, Change { effective: 10 }, &is_descendent_of).unwrap(); + tree.import("E", 15, Change { effective: 50 }, &is_descendent_of).unwrap(); + + (tree, is_descendent_of) + }; + + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"B", + 2, + &is_descendent_of, + |c| c.effective <= 2, + ), + Ok(false), + ); + + // 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.clone(), n.clone())).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(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.clone(), n.clone())).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(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.clone(), n.clone())).collect::>(), + vec![ + ("A", 1), + ("J", 2), ("K", 3), + ("F", 2), ("H", 3), ("I", 4), + ("G", 3), + ("B", 2), ("C", 3), ("D", 4), ("E", 5), + ], + ); + } +} diff --git a/license_header.txt b/license_header.txt index c357cc10ed409fad4f845affd912fe93a0b983f6..15b778660733f3b2b5415f3044df5e7a0d9e04d7 100644 --- a/license_header.txt +++ b/license_header.txt @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b66fe0e7deef63855f4254cb56c5b689f05727d5 --- /dev/null +++ b/node-template/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "node-template" +version = "0.9.0" +authors = ["Parity Technologies "] +build = "build.rs" +edition = "2018" + +[[bin]] +name = "template-node" +path = "src/main.rs" + +[dependencies] +error-chain = "0.12" +futures = "0.1" +ctrlc = { version = "3.0", features = ["termination"] } +log = "0.4" +tokio = "0.1" +exit-future = "0.1" +parking_lot = "0.7.1" +hex-literal = "0.1" +parity-codec = "3.2" +trie-root = "0.11.0" +sr-io = { path = "../core/sr-io" } +substrate-cli = { path = "../core/cli" } +primitives = { package = "substrate-primitives", path = "../core/primitives" } +substrate-executor = { path = "../core/executor" } +substrate-service = { path = "../core/service" } +inherents = { package = "substrate-inherents", path = "../core/inherents" } +transaction-pool = { package = "substrate-transaction-pool", path = "../core/transaction-pool" } +network = { package = "substrate-network", path = "../core/network" } +consensus = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } +substrate-client = { path = "../core/client" } +basic-authorship = { package = "substrate-basic-authorship", path = "../core/basic-authorship" } +node-template-runtime = { path = "runtime" } +node-executor = { path = "../node/executor" } + +[build-dependencies] +vergen = "3" diff --git a/node-template/LICENSE b/node-template/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..cf1ab25da0349f84a3fdd40032f0ce99db813b8b --- /dev/null +++ b/node-template/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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 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. + +For more information, please refer to diff --git a/node-template/README.md b/node-template/README.md new file mode 100644 index 0000000000000000000000000000000000000000..26c6924294be48bfd4d3013014013b19ff353f2c --- /dev/null +++ b/node-template/README.md @@ -0,0 +1,3 @@ +# Template Node + +A new SRML-based Substrate node, ready for hacking. diff --git a/node-template/build.rs b/node-template/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..afc39d3b63c5eab92b362d436f3f2b4786088ed0 --- /dev/null +++ b/node-template/build.rs @@ -0,0 +1,8 @@ +use vergen::{ConstantsFlags, generate_cargo_keys}; + +const ERROR_MSG: &str = "Failed to generate metadata files"; + +fn main() { + generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); + println!("cargo:rerun-if-changed=.git/HEAD"); +} diff --git a/node-template/build.sh b/node-template/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..edbcba835c13c8fed43400cab2e5a24be04a21b2 --- /dev/null +++ b/node-template/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +export CARGO_INCREMENTAL=0 + +bold=$(tput bold) +normal=$(tput sgr0) + +# Save current directory. +pushd . >/dev/null + +for SRC in runtime/wasm +do + echo "${bold}Building webassembly binary in $SRC...${normal}" + cd "$PROJECT_ROOT/$SRC" + + ./build.sh + + cd - >> /dev/null +done + +# Restore initial directory. +popd >/dev/null diff --git a/node-template/init.sh b/node-template/init.sh new file mode 100755 index 0000000000000000000000000000000000000000..5dde6d42418b58844640bd41214948ef329065aa --- /dev/null +++ b/node-template/init.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -e + +echo "*** Initialising WASM build environment" + +if [ -z $CI_PROJECT_NAME ] ; then + rustup update nightly + rustup update stable +fi + +rustup target add wasm32-unknown-unknown --toolchain nightly + +# Install wasm-gc. It's useful for stripping slimming down wasm binaries. +command -v wasm-gc || \ + cargo +nightly install --git https://github.com/alexcrichton/wasm-gc --force diff --git a/node-template/runtime/Cargo.toml b/node-template/runtime/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..d6cb7ea7f21fbb9f61282b4087ea2768f84de138 --- /dev/null +++ b/node-template/runtime/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "node-template-runtime" +version = "0.9.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } +safe-mix = { version = "1.0", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default_features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default_features = false } +version = { package = "sr-version", path = "../../core/sr-version", default_features = false } +support = { package = "srml-support", path = "../../srml/support", default_features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default_features = false } +balances = { package = "srml-balances", path = "../../srml/balances", default_features = false } +fees = { package = "srml-fees", path = "../../srml/fees", default_features = false } +consensus = { package = "srml-consensus", path = "../../srml/consensus", default_features = false } +aura = { package = "srml-aura", path = "../../srml/aura", default_features = false } +executive = { package = "srml-executive", path = "../../srml/executive", default_features = false } +indices = { package = "srml-indices", path = "../../srml/indices", default_features = false } +system = { package = "srml-system", path = "../../srml/system", default_features = false } +timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default_features = false } +sudo = { package = "srml-sudo", path = "../../srml/sudo", default_features = false } +runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default_features = false } +client = { package = "substrate-client", path = "../../core/client", default_features = false } +consensus-aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } + +[features] +default = ["std"] +std = [ + "parity-codec/std", + "primitives/std", + "client/std", + "rstd/std", + "runtime-io/std", + "support/std", + "balances/std", + "fees/std", + "executive/std", + "aura/std", + "indices/std", + "primitives/std", + "system/std", + "timestamp/std", + "sudo/std", + "version/std", + "serde_derive", + "serde", + "safe-mix/std", + "consensus-aura/std", +] diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..f46f8df249b6d23ea396296176991bf4fb340358 --- /dev/null +++ b/node-template/runtime/src/lib.rs @@ -0,0 +1,285 @@ +//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc))] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit="256"] + +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; +use parity_codec::{Encode, Decode}; +use rstd::prelude::*; +#[cfg(feature = "std")] +use primitives::bytes; +use primitives::{ed25519, OpaqueMetadata}; +use runtime_primitives::{ + ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, + traits::{self, BlakeTwo256, Block as BlockT, StaticLookup, Verify} +}; +use client::{ + block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, + runtime_api, impl_runtime_apis +}; +use version::RuntimeVersion; +#[cfg(feature = "std")] +use version::NativeVersion; + +// A few exports that help ease life for downstream crates. +#[cfg(any(feature = "std", test))] +pub use runtime_primitives::BuildStorage; +pub use consensus::Call as ConsensusCall; +pub use timestamp::Call as TimestampCall; +pub use balances::Call as BalancesCall; +pub use runtime_primitives::{Permill, Perbill}; +pub use timestamp::BlockPeriod; +pub use support::{StorageValue, construct_runtime}; + +/// The type that is used for identifying authorities. +pub type AuthorityId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AuthoritySignature = ed25519::Signature; + +/// Alias to pubkey that identifies an account on the chain. +pub type AccountId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AccountSignature = ed25519::Signature; + +/// A hash of some data used by the chain. +pub type Hash = primitives::H256; + +/// Index of a block number in the chain. +pub type BlockNumber = u64; + +/// Index of an account's extrinsic in the chain. +pub type Nonce = u64; + +/// Used for the module template in `./template.rs` +mod template; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the 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 datastructures. +pub mod opaque { + use super::*; + + /// Opaque, encoded, unchecked extrinsic. + #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] + pub struct UncheckedExtrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); + impl traits::Extrinsic for UncheckedExtrinsic { + fn is_signed(&self) -> Option { + None + } + } + /// Opaque block header type. + pub type Header = generic::Header>; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + /// Opaque session key type. + pub type SessionKey = AuthorityId; +} + +/// This runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("template-node"), + impl_name: create_runtime_str!("template-node"), + authoring_version: 3, + spec_version: 3, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, +}; + +/// The version infromation used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +impl system::Trait for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = Indices; + /// The index type for storing how many extrinsics an account has signed. + type Index = Nonce; + /// 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 digest type. + type Digest = generic::Digest; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous log type. + type Log = Log; + /// The ubiquitous origin type. + type Origin = Origin; +} + +impl aura::Trait for Runtime { + type HandleReport = (); +} + +impl consensus::Trait for Runtime { + /// The identifier we use to refer to authorities. + type SessionKey = AuthorityId; + // The aura module handles offline-reports internally + // rather than using an explicit report system. + type InherentOfflineReport = (); + /// The ubiquitous log type. + type Log = Log; +} + +impl indices::Trait for Runtime { + /// The type for recording indexing into the account enumeration. If this ever overflows, there + /// will be problems! + type AccountIndex = u32; + /// Use the standard means of resolving an index hint from an id. + type ResolveHint = indices::SimpleResolveHint; + /// Determine whether an account is dead. + type IsDeadAccount = Balances; + /// The uniquitous event type. + type Event = Event; +} + +impl timestamp::Trait for Runtime { + /// A timestamp: seconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; +} + +impl balances::Trait for Runtime { + /// The type for recording an account's balance. + type Balance = u128; + /// What to do if an account's free balance gets zeroed. + type OnFreeBalanceZero = (); + /// What to do if a new account is created. + type OnNewAccount = Indices; + /// The uniquitous event type. + type Event = Event; +} + +impl fees::Trait for Runtime { + type TransferAsset = Balances; + type Event = Event; +} + +impl sudo::Trait for Runtime { + /// The uniquitous event type. + type Event = Event; + type Proposal = Call; +} + +/// Used for the module template in `./template.rs` +impl template::Trait for Runtime { + type Event = Event; +} + +construct_runtime!( + pub enum Runtime with Log(InternalLog: DigestItem) where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{default, Log(ChangesTrieRoot)}, + Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, + Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, + Aura: aura::{Module}, + Indices: indices, + Balances: balances, + Sudo: sudo, + Fees: fees::{Module, Storage, Config, Event}, + // Used for the module template in `./template.rs` + TemplateModule: template::{Module, Call, Storage, Event}, + } +); + +/// The type used as a helper for interpreting the sender of transactions. +type Context = system::ChainContext; +/// The address format for describing accounts. +type Address = ::Source; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = executive::Executive; + +// Implement our runtime API endpoints. This is just a bunch of proxying. +impl_runtime_apis! { + impl runtime_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn authorities() -> Vec { + Consensus::authorities() + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialise_block(header: &::Header) { + Executive::initialise_block(header) + } + } + + impl runtime_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl block_builder_api::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalise_block() -> ::Header { + Executive::finalise_block() + } + + fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { + data.check_extrinsics(&block) + } + + fn random_seed() -> ::Hash { + System::random_seed() + } + } + + impl runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { + Aura::slot_duration() + } + } +} diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs new file mode 100644 index 0000000000000000000000000000000000000000..300b48af114c7b47f028c419dc23743b5086ad2b --- /dev/null +++ b/node-template/runtime/src/template.rs @@ -0,0 +1,124 @@ +/// A runtime module template with necessary imports + +/// Feel free to remove or edit this file as needed. +/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs +/// If you remove this file, you can remove those references + + +/// For more guidance on Substrate modules, see the example module +/// https://github.com/paritytech/substrate/blob/gav-template/srml/example/src/lib.rs + +use support::{decl_module, decl_storage, decl_event, StorageValue, dispatch::Result}; +use system::ensure_signed; + +/// The module's configuration trait. +pub trait Trait: system::Trait { + // TODO: Add other types and constants required configure this module. + + /// The overarching event type. + type Event: From> + Into<::Event>; +} + +/// This module's storage items. +decl_storage! { + trait Store for Module as TemplateModule { + // Just a dummy storage item. + // Here we are declaring a StorageValue, `Something` as a Option + // `get(something)` is the default getter which returns either the stored `u32` or `None` if nothing stored + Something get(something): Option; + } +} + +decl_module! { + /// The module declaration. + pub struct Module for enum Call where origin: T::Origin { + // Initializing events + // this is needed only if you are using events in your module + fn deposit_event() = default; + + // Just a dummy entry point. + // function that can be called by the external world as an extrinsics call + // takes a parameter of the type `AccountId`, stores it and emits an event + pub fn do_something(origin, something: u32) -> Result { + // TODO: You only need this if you want to check it was signed. + let who = ensure_signed(origin)?; + + // TODO: Code to execute when something calls this. + // For example: the following line stores the passed in u32 in the storage + >::put(something); + + // here we are raising the Something event + Self::deposit_event(RawEvent::SomethingStored(something, who)); + Ok(()) + } + } +} + +decl_event!( + /// An event in this module. + pub enum Event where AccountId = ::AccountId { + // Just a dummy event. + // Event `Something` is declared with a parameter of the type `u32` and `AccountId` + // To emit this event, we call the deposit funtion, from our runtime funtions + SomethingStored(u32, AccountId), + } +); + +/// tests for this module +#[cfg(test)] +mod tests { + use super::*; + + use runtime_io::with_externalities; + use primitives::{H256, Blake2Hasher}; + use support::{impl_outer_origin, assert_ok}; + use runtime_primitives::{ + BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, + testing::{Digest, DigestItem, Header} + }; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type Log = DigestItem; + } + impl Trait for Test { + type Event = (); + } + type TemplateModule = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> runtime_io::TestExternalities { + system::GenesisConfig::::default().build_storage().unwrap().0.into() + } + + #[test] + fn it_works_for_default_value() { + with_externalities(&mut new_test_ext(), || { + // Just a dummy test for the dummy funtion `do_something` + // calling the `do_something` function with a value 42 + assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); + // asserting that the stored value is equal to what we stored + assert_eq!(TemplateModule::something(), Some(42)); + }); + } +} diff --git a/node-template/runtime/wasm/Cargo.lock b/node-template/runtime/wasm/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..dfd1c90fee33660997b17e27c5f50cb44dfb62ab --- /dev/null +++ b/node-template/runtime/wasm/Cargo.lock @@ -0,0 +1,2520 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chrono" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crossbeam" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crunchy" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crunchy" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crypto-mac" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "elastic-array" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "environmental" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "error-chain" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fixed-hash" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hash-db" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hash256-std-hasher" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hex-literal" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex-literal-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +dependencies = [ + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", +] + +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libsecp256k1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memory-db" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memory_units" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "merlin" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-extras" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "node-template-runtime" +version = "0.9.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "srml-aura 0.1.0", + "srml-balances 0.1.0", + "srml-consensus 0.1.0", + "srml-executive 0.1.0", + "srml-fees 0.1.0", + "srml-indices 0.1.0", + "srml-sudo 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "srml-timestamp 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "node-template-runtime-wasm" +version = "0.9.0" +dependencies = [ + "node-template-runtime 0.9.0", +] + +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl" +version = "0.10.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-sys" +version = "0.9.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-bytes" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" + +[[package]] +name = "parity-codec" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-codec-derive" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-wasm" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "primitive-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack-impl" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ring" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-hex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "safe-mix" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#0a0de4294b475ef6abdeebb50067f213ca79b3c7" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sha2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha3" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slog" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slog-async" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slog-json" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slog-scope" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sr-api-macros" +version = "0.1.0" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-io" +version = "0.1.0" +dependencies = [ + "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 0.1.0", + "substrate-primitives 0.1.0", + "substrate-state-machine 0.1.0", + "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-primitives" +version = "0.1.0" +dependencies = [ + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-std 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "sr-std" +version = "0.1.0" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-version" +version = "0.1.0" +dependencies = [ + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + +[[package]] +name = "srml-aura" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-session 0.1.0", + "srml-staking 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "srml-timestamp 0.1.0", + "substrate-inherents 0.1.0", +] + +[[package]] +name = "srml-balances" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", +] + +[[package]] +name = "srml-consensus" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-executive" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", +] + +[[package]] +name = "srml-fees" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-indices" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-metadata" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-session" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-consensus 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "srml-timestamp 0.1.0", +] + +[[package]] +name = "srml-staking" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-consensus 0.1.0", + "srml-session 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", +] + +[[package]] +name = "srml-sudo" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-support-procedural 0.1.0", + "srml-system 0.1.0", +] + +[[package]] +name = "srml-support" +version = "0.1.0" +dependencies = [ + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-metadata 0.1.0", + "srml-support-procedural 0.1.0", + "substrate-inherents 0.1.0", +] + +[[package]] +name = "srml-support-procedural" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", + "srml-support-procedural-tools 0.1.0", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-support-procedural-tools" +version = "0.1.0" +dependencies = [ + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "srml-support-procedural-tools-derive 0.1.0", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-support-procedural-tools-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-system" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-timestamp" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-inherents 0.1.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "static_assertions" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-client" +version = "0.1.0" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "sr-version 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", + "substrate-state-machine 0.1.0", + "substrate-telemetry 0.3.1", + "substrate-trie 0.4.0", +] + +[[package]] +name = "substrate-consensus-aura-primitives" +version = "0.1.0" +dependencies = [ + "substrate-client 0.1.0", +] + +[[package]] +name = "substrate-consensus-common" +version = "0.1.0" +dependencies = [ + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-version 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-executor" +version = "0.1.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", + "substrate-primitives 0.1.0", + "substrate-serializer 0.1.0", + "substrate-state-machine 0.1.0", + "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-inherents" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + +[[package]] +name = "substrate-keyring" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-primitives" +version = "0.1.0" +dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-serializer" +version = "0.1.0" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-state-machine" +version = "0.1.0" +dependencies = [ + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", + "substrate-primitives 0.1.0", + "substrate-trie 0.4.0", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-telemetry" +version = "0.3.1" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-trie" +version = "0.4.0" +dependencies = [ + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.15.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-db" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-root" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twox-hash" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "uint" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "untrusted" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vcpkg" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ws" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +"checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" +"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" +"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" +"checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" +"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" +"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" +"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" +"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" +"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" +"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" +"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" +"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" +"checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" +"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" +"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" +"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" +"checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" +"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/node-template/runtime/wasm/Cargo.toml b/node-template/runtime/wasm/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..dbb935c6befbc758caee7235cb7c70ff8f1703ba --- /dev/null +++ b/node-template/runtime/wasm/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "node-template-runtime-wasm" +version = "0.9.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +node-template-runtime = { path = "..", default-features = false } + +[features] +default = [] +std = [ + "node-template-runtime/std", +] + +[profile.release] +panic = "abort" +lto = true + +[workspace] +members = [] diff --git a/node-template/runtime/wasm/build.sh b/node-template/runtime/wasm/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..0be6e7a11c75464ce42a8ad0ddb8a7ccd8d630fc --- /dev/null +++ b/node-template/runtime/wasm/build.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +if cargo --version | grep -q "nightly"; then + CARGO_CMD="cargo" +else + CARGO_CMD="cargo +nightly" +fi +$CARGO_CMD build --target=wasm32-unknown-unknown --release +for i in node_template_runtime_wasm +do + wasm-gc target/wasm32-unknown-unknown/release/$i.wasm target/wasm32-unknown-unknown/release/$i.compact.wasm +done diff --git a/node-template/runtime/wasm/src/lib.rs b/node-template/runtime/wasm/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..224f854812b9fd9f7a875770bc4421b4d8fa277d --- /dev/null +++ b/node-template/runtime/wasm/src/lib.rs @@ -0,0 +1,5 @@ +//! The Substrate node template runtime reexported for WebAssembly compile. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use node_template_runtime::*; diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs new file mode 100644 index 0000000000000000000000000000000000000000..780d33be65ac382566b31a41fc86b0de3cee3296 --- /dev/null +++ b/node-template/src/chain_spec.rs @@ -0,0 +1,121 @@ +use primitives::{ed25519, Pair}; +use node_template_runtime::{ + AccountId, GenesisConfig, ConsensusConfig, TimestampConfig, BalancesConfig, + SudoConfig, IndicesConfig, FeesConfig, +}; +use substrate_service; + +use ed25519::Public as AuthorityId; + +// Note this is the URL for the telemetry server +//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Specialised `ChainSpec`. This is a specialisation of the general Substrate ChainSpec type. +pub type ChainSpec = substrate_service::ChainSpec; + +/// The chain specification option. This is expected to come in from the CLI and +/// is little more than one of a number of alternatives which can easily be converted +/// from a string (`--chain=...`) into a `ChainSpec`. +#[derive(Clone, Debug)] +pub enum Alternative { + /// Whatever the current runtime is, with just Alice as an auth. + Development, + /// Whatever the current runtime is, with simple Alice/Bob auths. + LocalTestnet, +} + +fn authority_key(s: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("//{}", s), None) + .expect("static values are valid; qed") + .public() +} + +fn account_key(s: &str) -> AccountId { + ed25519::Pair::from_string(&format!("//{}", s), None) + .expect("static values are valid; qed") + .public() +} + +impl Alternative { + /// Get an actual chain config from one of the alternatives. + pub(crate) fn load(self) -> Result { + Ok(match self { + Alternative::Development => ChainSpec::from_genesis( + "Development", + "dev", + || testnet_genesis(vec![ + authority_key("Alice") + ], vec![ + account_key("Alice") + ], + account_key("Alice") + ), + vec![], + None, + None, + None, + None + ), + Alternative::LocalTestnet => ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + || testnet_genesis(vec![ + authority_key("Alice"), + authority_key("Bob"), + ], vec![ + account_key("Alice"), + account_key("Bob"), + account_key("Charlie"), + account_key("Dave"), + account_key("Eve"), + account_key("Ferdie"), + ], + account_key("Alice"), + ), + vec![], + None, + None, + None, + None + ), + }) + } + + pub(crate) fn from(s: &str) -> Option { + match s { + "dev" => Some(Alternative::Development), + "" | "local" => Some(Alternative::LocalTestnet), + _ => None, + } + } +} + +fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { + GenesisConfig { + consensus: Some(ConsensusConfig { + code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(), + authorities: initial_authorities.clone(), + }), + system: None, + timestamp: Some(TimestampConfig { + period: 5, // 5 second block time. + }), + indices: Some(IndicesConfig { + ids: endowed_accounts.clone(), + }), + balances: Some(BalancesConfig { + existential_deposit: 500, + transfer_fee: 0, + creation_fee: 0, + balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), + vesting: vec![], + }), + sudo: Some(SudoConfig { + key: root_key, + }), + fees: Some(FeesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, + }) + } +} diff --git a/node-template/src/cli.rs b/node-template/src/cli.rs new file mode 100644 index 0000000000000000000000000000000000000000..258d2194a66c682d2c917bd8855a2ddf075826d4 --- /dev/null +++ b/node-template/src/cli.rs @@ -0,0 +1,94 @@ +use crate::service; +use futures::{future, Future, sync::oneshot}; +use std::cell::RefCell; +use tokio::runtime::Runtime; +pub use substrate_cli::{VersionInfo, IntoExit, error}; +use substrate_cli::{informant, parse_and_execute, NoCustom}; +use substrate_service::{ServiceFactory, Roles as ServiceRoles}; +use crate::chain_spec; +use std::ops::Deref; +use log::info; + +/// Parse command line arguments into service configuration. +pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> where + I: IntoIterator, + T: Into + Clone, + E: IntoExit, +{ + parse_and_execute::( + load_spec, &version, "substrate-node", args, exit, + |exit, _custom_args, config| { + info!("{}", version.name); + info!(" version {}", config.full_version()); + info!(" by {}, 2017, 2018", version.author); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {:?}", config.roles); + let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?; + let executor = runtime.executor(); + match config.roles { + ServiceRoles::LIGHT => run_until_exit( + runtime, + service::Factory::new_light(config, executor).map_err(|e| format!("{:?}", e))?, + exit + ), + _ => run_until_exit( + runtime, + service::Factory::new_full(config, executor).map_err(|e| format!("{:?}", e))?, + exit + ), + }.map_err(|e| format!("{:?}", e)) + } + ).map_err(Into::into).map(|_| ()) +} + +fn load_spec(id: &str) -> Result, String> { + Ok(match chain_spec::Alternative::from(id) { + Some(spec) => Some(spec.load()?), + None => None, + }) +} + +fn run_until_exit( + mut runtime: Runtime, + service: T, + e: E, +) -> error::Result<()> + where + T: Deref>, + C: substrate_service::Components, + E: IntoExit, +{ + let (exit_send, exit) = exit_future::signal(); + + let executor = runtime.executor(); + informant::start(&service, exit.clone(), executor.clone()); + + let _ = runtime.block_on(e.into_exit()); + exit_send.fire(); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + drop(service); + Ok(()) +} + +// handles ctrl-c +pub struct Exit; +impl IntoExit for Exit { + type Exit = future::MapErr, fn(oneshot::Canceled) -> ()>; + fn into_exit(self) -> Self::Exit { + // can't use signal directly here because CtrlC takes only `Fn`. + let (exit_send, exit) = oneshot::channel(); + + let exit_send_cell = RefCell::new(Some(exit_send)); + ctrlc::set_handler(move || { + if let Some(exit_send) = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take() { + exit_send.send(()).expect("Error sending exit notification"); + } + }).expect("Error setting Ctrl-C handler"); + + exit.map_err(drop) + } +} diff --git a/node-template/src/error.rs b/node-template/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..a8aa94bf3285f928b79468ed5317a28eeaa8b635 --- /dev/null +++ b/node-template/src/error.rs @@ -0,0 +1,13 @@ +//! Initialization errors. + +use client; + +error_chain! { + foreign_links { + Io(::std::io::Error) #[doc="IO error"]; + Cli(::clap::Error) #[doc="CLI error"]; + } + links { + Client(client::error::Error, client::error::ErrorKind) #[doc="Client error"]; + } +} diff --git a/node-template/src/main.rs b/node-template/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..7d8c3076c626187ad85c27ef9a72baf6c60e1807 --- /dev/null +++ b/node-template/src/main.rs @@ -0,0 +1,25 @@ +//! Substrate Node Template CLI library. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +mod chain_spec; +mod service; +mod cli; + +pub use substrate_cli::{VersionInfo, IntoExit, error}; + +fn run() -> cli::error::Result<()> { + let version = VersionInfo { + name: "Substrate Node", + commit: env!("VERGEN_SHA_SHORT"), + version: env!("CARGO_PKG_VERSION"), + executable_name: "template-node", + author: "Anonymous", + description: "Template Node", + support_url: "support.anonymous.an", + }; + cli::run(::std::env::args(), cli::Exit, version) +} + +error_chain::quick_main!(run); diff --git a/node-template/src/service.rs b/node-template/src/service.rs new file mode 100644 index 0000000000000000000000000000000000000000..1bb97256aea700da90acc0195d9aaa46f1111957 --- /dev/null +++ b/node-template/src/service.rs @@ -0,0 +1,112 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over Substrate service. + +#![warn(unused_extern_crates)] + +use std::sync::Arc; +use log::info; +use transaction_pool::{self, txpool::{Pool as TransactionPool}}; +use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; +use substrate_service::{ + FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, + FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, + TaskExecutor, +}; +use basic_authorship::ProposerFactory; +use node_executor; +use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; +use substrate_client as client; +use primitives::{ed25519::Pair, Pair as _Pair}; +use inherents::InherentDataProviders; +use network::construct_simple_protocol; +use substrate_executor::native_executor_instance; +use substrate_service::construct_service_factory; + +pub use substrate_executor::NativeExecutor; +// Our native executor instance. +native_executor_instance!( + pub Executor, + node_template_runtime::api::dispatch, + node_template_runtime::native_version, + include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm") +); + +#[derive(Default)] +pub struct NodeConfig { + inherent_data_providers: InherentDataProviders, +} + +construct_simple_protocol! { + /// Demo protocol attachment for substrate. + pub struct NodeProtocol where Block = Block { } +} + +construct_service_factory! { + struct Factory { + Block = Block, + RuntimeApi = RuntimeApi, + NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) }, + RuntimeDispatch = node_executor::Executor, + FullTransactionPoolApi = transaction_pool::ChainApi, FullExecutor, Block, RuntimeApi>, Block> + { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, + LightTransactionPoolApi = transaction_pool::ChainApi, LightExecutor, Block, RuntimeApi>, Block> + { |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) }, + Genesis = GenesisConfig, + Configuration = NodeConfig, + FullService = FullComponents + { |config: FactoryFullConfiguration, executor: TaskExecutor| + FullComponents::::new(config, executor) + }, + AuthoritySetup = { + |service: Self::FullService, executor: TaskExecutor, key: Option>| { + if let Some(key) = key { + info!("Using authority key {}", key.public()); + let proposer = Arc::new(ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }); + let client = service.client(); + executor.spawn(start_aura( + SlotDuration::get_or_compute(&*client)?, + key.clone(), + client.clone(), + client, + proposer, + service.network(), + service.on_exit(), + service.config.custom.inherent_data_providers.clone(), + )?); + } + + Ok(service) + } + }, + LightService = LightComponents + { |config, executor| >::new(config, executor) }, + FullImportQueue = AuraImportQueue< + Self::Block, + > + { |config: &mut FactoryFullConfiguration , client: Arc>| + import_queue( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + ).map_err(Into::into) + }, + LightImportQueue = AuraImportQueue< + Self::Block, + > + { |config: &mut FactoryFullConfiguration, client: Arc>| + import_queue( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + ).map_err(Into::into) + }, + } +} diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index 438d72173dcd36c87b2df64b06ee3f00c9466323..28fb297e5731a7b0a617bd568c62e20010e2dc23 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -4,35 +4,36 @@ version = "0.1.0" authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." build = "build.rs" +edition = "2018" [dependencies] log = "0.4" tokio = "0.1.7" futures = "0.1" exit-future = "0.1" -substrate-cli = { path = "../../core/cli" } -parity-codec = { version = "2.1" } -slog = "^2" +cli = { package = "substrate-cli", path = "../../core/cli" } +parity-codec = { version = "3.2" } sr-io = { path = "../../core/sr-io" } -substrate-client = { path = "../../core/client" } -substrate-primitives = { path = "../../core/primitives" } +client = { package = "substrate-client", path = "../../core/client" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +inherents = { package = "substrate-inherents", path = "../../core/inherents" } node-runtime = { path = "../runtime" } node-primitives = { path = "../primitives" } hex-literal = "0.1" +substrate-basic-authorship = { path = "../../core/basic-authorship" } substrate-service = { path = "../../core/service" } -substrate-transaction-pool = { path = "../../core/transaction-pool" } -substrate-network = { path = "../../core/network" } -substrate-consensus-aura = { path = "../../core/consensus/aura" } -substrate-finality-grandpa = { path = "../../core/finality-grandpa" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } +network = { package = "substrate-network", path = "../../core/network" } +consensus = { package = "substrate-consensus-aura", path = "../../core/consensus/aura" } +grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } sr-primitives = { path = "../../core/sr-primitives" } node-executor = { path = "../executor" } -structopt = "0.2.13" substrate-keystore = { path = "../../core/keystore" } +substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" } [dev-dependencies] -substrate-service-test = { path = "../../core/service/test" } +service-test = { package = "substrate-service-test", path = "../../core/service/test" } [build-dependencies] -substrate-cli = { path = "../../core/cli" } -structopt = "0.2.13" -clap = "~2.32" +cli = { package = "substrate-cli", path = "../../core/cli" } +structopt = "0.2" diff --git a/node/cli/build.rs b/node/cli/build.rs index 74472bff06c1e40ae0570dcff492679fa182c2e4..e7a7b271f15034498ad00dbf17827a96a7a0a127 100644 --- a/node/cli/build.rs +++ b/node/cli/build.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,16 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -extern crate clap; -extern crate substrate_cli as cli; -extern crate structopt; +use cli::{NoCustom, CoreParams}; -use std::fs; -use std::env; -use clap::Shell; -use std::path::Path; +use std::{fs, env, path::Path}; -include!("src/params.rs"); +use structopt::{StructOpt, clap::Shell}; fn main() { build_shell_completion(); @@ -32,30 +27,24 @@ fn main() { /// Build shell completion scripts for all known shells /// Full list in https://github.com/kbknapp/clap-rs/blob/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9/src/app/parser.rs#L123 fn build_shell_completion() { - let shells = [Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish, Shell::PowerShell]; - for shell in shells.iter() { - build_completion(shell); + for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::Elvish, Shell::PowerShell] { + build_completion(shell); } } /// Build the shell auto-completion for a given Shell fn build_completion(shell: &Shell) { - let outdir = match env::var_os("OUT_DIR") { - None => return, - Some(dir) => dir, - }; - let path = Path::new(&outdir) - .parent().unwrap() - .parent().unwrap() - .parent().unwrap() - .join("completion-scripts"); - - fs::create_dir(&path).ok(); - - let mut app = Params::clap(); - app.gen_completions( - "substrate-node", - *shell, - &path); + None => return, + Some(dir) => dir, + }; + let path = Path::new(&outdir) + .parent().unwrap() + .parent().unwrap() + .parent().unwrap() + .join("completion-scripts"); + + fs::create_dir(&path).ok(); + + CoreParams::::clap().gen_completions("substrate-node", *shell, &path); } diff --git a/node/cli/res/charred-cherry.json b/node/cli/res/charred-cherry.json deleted file mode 100644 index 0321a5717a8a15f0d8d35b7f2c816f2bf3271472..0000000000000000000000000000000000000000 --- a/node/cli/res/charred-cherry.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "Charred Cherry", - "id": "charred-cherry", - "properties": { - "tokenSymbol": "CHR" - }, - "telemetryUrl": "wss://telemetry.polkadot.io/submit/", - "protocolId": null, - "bootNodes": [ - "/ip4/104.211.54.233/tcp/30333/p2p/QmWxNqJeKEBWjJXeX8s882ZdphuVPgUV43THfGAJn7UBWB", - "/ip4/104.211.48.51/tcp/30333/p2p/QmXd7MQAuXkQK1r3ejSbaXKgjXmT2FvbJ3yNfLZpsQ2t8S", - "/ip4/104.211.48.247/tcp/30333/p2p/QmV2zjgFRfxbgYZQC9qFr4aHsQt7tDBJRAdgqqxqTq1Kta", - "/ip4/40.114.120.164/tcp/30333/p2p/QmQbPCeurXuKhzCw6Ar6ovizNKATMTnkkqFJKgZzbF2MJs" - ], - "genesis": { - "raw": { - "0xfbb77d814ac81cfe0ef7030e8bd686f0": "0xe803000000000000", - "0xa902f1f0ef97177b8df9f9fd413768e7": "0x00000000", - "0x27b3872d47181b4a2dc15f0da43e7026": "0xe803000000000000", - "0x5278a9149ec1adfa8090a8ad336c881e": "0x0300000000000000", - "0x52b963fbdb3d6e1b03808fc20071f07f": "0x0027060000000000", - "0xfc2dc4b8bb0b9ca8f01a73a726f7c7f5": "0x00e1000000000000", - "0x3a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", - "0x93940e78496482b15b64783020bbdfa0": "0x6400000000000000", - "0xb8f48a8c01f629d6dc877f64892bed49": "0x0000000000000000", - "0xcf9a75deea0508104cd993c82daf57d3": "0x8096980000000000", - "0xd9c94b41dc87728ebf0a966d2e9ad9c0": "0x3200000000000000", - "0x0e0cdac0d4de97c54f3ae216b003fa81": "0x5802000000000000", - "0x3a6772616e6470613a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e70100000000000000", - "0x3b7d32346a3315a351084927a27d06a7": "0x0010a5d4e80000000000000000000000", - "0x34de7fc8c73e4252b9e09a9e3bf602f8": "0x6400000000000000", - "0x24586f4898a5a637b755b658ec163d00": "0x00407a10f35a00000000000000000000", - "0x8366297e853b97a38cca0f62019a717b": "0x00000000000000000000000000000000", - "0x3a6772616e6470613a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca50100000000000000", - "0x3a636f6465": "0x0061736d0100000001f5012260037f7f7f017f60017f0060027f7f017f60057f7f7f7f7f0060037f7f7f0060047f7f7f7f0060017f017f60057f7f7f7f7f017f60027f7f0060017e0060047f7f7f7f017f60067f7f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f60047f7f7e7f017f60000060027e7f0060017f017e60027e7f017f60027f7e0060037e7e7f0060057f7e7e7e7e0060037f7e7e0060037f7f7e0060047f7f7e7e0060027f7f017e60037e7f7f00600a7f7f7f7f7e7e7f7f7f7f00600a7f7f7f7e7e7f7f7f7f7f0060057f7e7f7f7e0060037f7e7e017f60087f7f7f7f7f7e7e7f0060047f7f7f7f017e60047f7e7e7f0060067f7e7e7e7e7f0002cc041703656e760a6578745f6d616c6c6f63000603656e76086578745f66726565000103656e760c6578745f74776f785f313238000403656e760f6578745f7365745f73746f72616765000503656e76146578745f6765745f73746f726167655f696e746f000703656e76236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74000503656e760e6578745f7072696e745f75746638000803656e760d6578745f7072696e745f6e756d000903656e76116578745f636c6561725f73746f72616765000803656e760d6578745f7072696e745f686578000803656e76106578745f73746f726167655f726f6f74000103656e76166578745f73616e64626f785f6d656d6f72795f676574000a03656e76166578745f73616e64626f785f6d656d6f72795f736574000a03656e760e6578745f626c616b65325f323536000403656e76126578745f6578697374735f73746f72616765000203656e76126578745f656432353531395f766572696679000a03656e76166578745f73616e64626f785f6d656d6f72795f6e6577000203656e761b6578745f73616e64626f785f6d656d6f72795f74656172646f776e000103656e76176578745f73616e64626f785f696e7374616e7469617465000b03656e76126578745f73616e64626f785f696e766f6b65000c03656e761d6578745f73616e64626f785f696e7374616e63655f74656172646f776e000103656e76106578745f636c6561725f707265666978000803656e76186578745f73746f726167655f6368616e6765735f726f6f74000d03ec02ea02080e080808080808080808080f08040408010101080e08040801010101080808080808080808080808080408080404040804080408020804010808040808080804020104020604040408020104040808080808080401000e02020801000202080b1002081100050202060202020201040212080101010404010108080808080808080813020f0201010108080808080808140815160108170808040802010101010108020201010101010f150502010401080808080108010801080108010105080802080802010204050502181818191208040e090118181801181818180818080210010818081801180505050e0503051a051b050505050505081c08120801080106010108080101010101040401040204040808080804080101010404040404040408080808040304081d0408040e080408080804040806040417151708080808080101010101080115091e0c1f0101010108080101010408010101080101000000001414142020210405017001535305030100110619037f01418080c0000b7f0041d0b0c3000b7f0041d0b0c3000b07d70312066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000b5f5f686561705f6261736503010a5f5f646174615f656e6403020c436f72655f76657273696f6e00e30110436f72655f617574686f72697469657300e40112436f72655f657865637574655f626c6f636b00e50115436f72655f696e697469616c6973655f626c6f636b00ed01114d657461646174615f6d6574616461746100ee011c426c6f636b4275696c6465725f6170706c795f65787472696e73696300ef011b426c6f636b4275696c6465725f66696e616c6973655f626c6f636b00f10120426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637300f2011c426c6f636b4275696c6465725f636865636b5f696e686572656e747300f30118426c6f636b4275696c6465725f72616e646f6d5f7365656400f4012b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00f601214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e676500fc011e4772616e6470614170695f6772616e6470615f617574686f72697469657300fe0115417572614170695f736c6f745f6475726174696f6e008002099d01010041010b52704c5882016f7e7f810187019b019d01bb01ba018401618301810282028502870289028b028c028d028e028f029002e502727374759f0178bf02c302be02c10262f602dd01bf019b02ee02de029001b202c0018f01be01e702f202db02da02e902e802f502f302d501d401b601ac019a029802ed02ec02dd02dc028c018b01b102b002b801b7018a01bd01bc01e6028602c802c502c7020a8c8a23ea02e50203087f017e017f024002400240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b220641d8006d22074f0d00200320076a22082003490d0420024101742203200820082003491b2209ad42d8007e220a422088a70d04200aa722034100480d042002450d012000280200210b200310002208450d052008200b2003200241d8006c2202200220034b1b10f8021a200b10010c020b200028020021080c020b200310002208450d030b20002008360200200041046a2009360200200041086a28020021030b2008200341d8006c6a2005200610f8021a200141086a22022004360200200041086a2200200028020020076a36020041002100024003402000450d012002200441d8006a2203360200200041a87f6a210020042d000021082003210420084102470d000b0b02402001280204450d00200128020010010b0f0b1018000b200341081019000b0a0041b890c200104f000b0d0041ad8ec0004122100600000ba00601087f230041206b2202240020024100360218200242013703102000280200210320002802082200200241106a101b024002400240024002402000450d00200041d8006c2104200241186a2105034020052802002100200228021421060240024002400240024002400240024002402003280200410d470d0020062000470d01200041016a22062000490d0b20004101742207200620062007491b22074100480d0b2000450d0320022802102108200710002206450d0c2006200820072000200020074b1b10f8021a200810010c040b20062000470d01200041016a22062000490d0a20004101742207200620062007491b22074100480d0a2000450d0520022802102108200710002206450d0c2006200820072000200020074b1b10f8021a200810010c060b200228021021060c030b200228021021060c050b200710002206450d080b2002200736021420022006360210200528020021000b2005200041016a360200200620006a41003a0000200341d8006a2103200441a87f6a22040d030c040b200710002206450d060b2002200736021420022006360210200528020021000b2005200041016a360200200620006a41013a00002003200241106a101c200341d0006a2802002108024002400240024020022802142207200528020022006b41044f0d00200041046a22062000490d0620074101742200200620062000491b22004100480d062007450d0120022802102109200010002206450d092006200920002007200720004b1b10f8021a200910010c020b200228021021060c020b200010002206450d070b2002200036021420022006360210200528020021000b2005200041046a360200200620006a2008360000200341d8006a2103200441a87f6a22040d000b0b200241106a41086a2200280200210520022802142104200228021021032001280204210620012802002107200042003703002002420037031020072006200241106a1002200241086a2000290300370300200220022903103703002002411020032005100302402004450d00200310010b200241206a24000f0b1018000b200741011019000b200741011019000b200041011019000b960501047f02402000413f4b0d002001200041027410240f0b0240024002400240024002400240024002400240024002400240024002400240024002402000418080014f0d00200141046a2802002202200141086a28020022036b41024f0d01200341026a22042003490d0e20024101742203200420042003491b22034100480d0e2002450d0520012802002105200310002204450d0f2004200520032002200220034b1b10f8021a200510010c060b20004180808080044f0d01200141046a2802002202200141086a28020022036b41044f0d02200341046a22042003490d0d20024101742203200420042003491b22034100480d0d2002450d0720012802002105200310002204450d0f2004200520032002200220034b1b10f8021a200510010c080b200128020021040c050b200141031024200141046a2802002202200141086a28020022036b41044f0d01200341046a22042003490d0b20024101742203200420042003491b22034100480d0b2002450d0820012802002105200310002204450d0e2004200520032002200220034b1b10f8021a200510010c090b200128020021040c060b200128020021040c080b200310002204450d090b20012004360200200141046a2003360200200141086a28020021030b200141086a200341026a360200200420036a20004102744101723b00000f0b200310002204450d070b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20004102744102723600000f0b200310002204450d050b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20003600000f0b1018000b200341011019000b200341011019000b200341011019000bf42302057f017e02400240024020002802002202450d004101210320024101470d020c010b2001410010240240200041086a220229030022074202520d00200141001024200041106a2903002001109c01200229030021070b024002402007a722024101460d002002450d0141012103200028020022024101460d020c030b41a881c300104f000b41a881c300104f000b200120031024200041086a200110c402200028020021020b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020024102470d002001410210240240024002400240200041086a220328020022024102460d0020024103460d010c020b2001410010242000410c6a200110a401200041306a290300200041386a2903002001109a01200328020022024103470d010b2001410110242000410c6a200110a401200041306a290300200041386a2903002001109a01200041c0006a290300200041c8006a2903002001109a01200041086a28020022024101470d010c030b20024101460d020b2002450d08200028020021020b20024103470d06200141031024200041086a22032d000022024102470d05200141001024200141046a2802002204200141086a28020022026b41204f0d01200241206a22052002490d2420044101742202200520052002491b22024100480d242004450d0220012802002106200210002205450d0e2005200620022004200420024b1b10f8021a200610010c030b41c4aec300104f000b200128020021050c020b200210002205450d0b0b20012005360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200520026a220241186a200341196a290000370000200241106a200341116a290000370000200241086a200341096a2900003700002002200329000137000020032d000021020b0240200241ff01714103470d00200141011024200041106a2903002001109c01200041086a2d000021020b0240200241ff01714104470d002001410210240240024002400240200141046a280200200141086a2802002202470d00200241016a22052002490d2320024101742204200520052004491b22044100480d232002450d0120012802002106200410002205450d0e2005200620042002200220044b1b10f8021a200610010c020b200128020021050c020b200410002205450d0c0b20012005360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200520026a200341016a2d00003a000020032d000021020b200241ff017122024101460d022002450d03200028020021020b024020024104470d0020014104102402400240200041086a22032d00002202410f714103460d0020024102470d012001410010240c010b2001410110242000410c6a2802002001101b20032d000021020b0240200241ff01714104470d002001410210242000410c6a200110a401200041086a2d000021020b0240200241ff01714105470d002001410310242000410c6a2802002001101b200041086a2d000021020b0240200241ff01714106470d002001410410242000410c6a2802002001101b200041206a2802002001101b200041106a290300200041186a2903002001109a01200041086a2d000021020b0240200241ff01714107470d00200141051024200041106a2903002001109c01200041086a2d000021020b0240200241ff01714108470d00200141061024200041106a2903002001109c01200041086a2d000021020b0240200241ff01714109470d002001410710242000410c6a2802002001101b200041086a2d000021020b0240200241ff0171410a470d002001410810240240024002400240200141046a280200200141086a2802002202470d00200241016a22032002490d2320024101742205200320032005491b22054100480d232002450d0120012802002104200510002203450d0f2003200420052002200220054b1b10f8021a200410010c020b200128020021030c020b200510002203450d0d0b20012003360200200141046a2005360200200141086a28020021020b200141086a200241016a360200200320026a200041096a2d00003a0000200041086a2d000021020b0240200241ff0171410b470d002001410910242000410c6a2802002001101b200041086a2d000021020b2002410f7122024101460d042002450d05200028020021020b024020024105470d002001410510240240200041086a22032d000022024102470d002001410010242000410c6a2802002001101c200041106a290300200041186a2903002001109a0120032d000021020b0240200241ff01714103470d002001410110242000410c6a2802002001101b200041086a2d000021020b0240200241ff01714104470d002001410210242000410c6a2802002001101b0240024002400240200141046a280200200141086a2802002202470d00200241016a22032002490d2320024101742205200320032005491b22054100480d232002450d0120012802002104200510002203450d102003200420052002200220054b1b10f8021a200410010c020b200128020021030c020b200510002203450d0e0b20012003360200200141046a2005360200200141086a28020021020b200141086a200241016a360200200320026a200041096a2d00003a0000200041086a2d000021020b0240200241ff01714105470d002001410310242000410c6a2802002001101c024002400240200041096a2d000022024101460d0020024102470d012001410210240c020b2001410110240c010b2001410010240b200041106a29030020011023200041086a2d000021020b0240200241ff01714106470d002001410410242000410c6a2802002001101b200041086a2d000021020b0240200241ff01714107470d00200141051024200041106a290300200110232000410c6a2802002001108901200041086a2d000021020b200241077122024101460d062002450d07200028020021020b20024106470d1c20014106102402400240200041086a220328020022024102460d0020024103460d010c0d0b2001410010242000410c6a280200200041146a2802002001108d01200041186a2802002001101b200328020022024103470d0c0b2001410110242000410c6a2802002001101b200041106a200110a401200041346a2802002001101b200041386a2802002001101b200041086a28020022024104470d0c0c0d0b41c4aec300104f000b41acd5c200104f000b41acd5c200104f000b41a8ccc200104f000b41a8ccc200104f000b41a8e6c200104f000b41a8e6c200104f000b200241011019000b200441011019000b200541011019000b200541011019000b20024104460d010b20024105460d010c020b2001410210242000410c6a2802002001101b200041086a28020022024105470d010b2001410310242000410c6a2802002001101b200041086a28020022024106470d010c020b20024106460d010b20024107460d010c020b2001410410242000410c6a200110a401200041386a290300200041c0006a2903002001109a01200041306a2802002001101b200041086a28020022024107470d010b2001410510242000410c6a2802002001101b41082103200041086a28020022024108470d010c020b4108210320024108460d010b20024109460d010c020b2001410610242000410c6a200110a401200020036a28020022024109470d010b200141071024200041106a2903002001109c01200041086a2802002202410a470d010c020b2002410a460d010b20024101460d010c020b200141081024200041106a2903002001109c01200041086a28020022024101470d010b41d09fc300104f000b2002450d02200028020021020b024020024107470d002001410710240240200041086a22032d000022024102470d002001410010242000410c6a2802002001101c20032d000021020b0240200241ff01714103470d00200141011024200341016a2001101e0240024002400240200141046a280200200141086a2802002202470d00200241016a22052002490d0620024101742204200520052004491b22044100480d062002450d0120012802002106200410002205450d0d2005200620042002200220044b1b10f8021a200610010c020b200128020021050c020b200410002205450d0b0b20012005360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200520026a200341216a2d00003a000020032d000021020b0240200241ff01714104470d00200141021024200341016a2001101e20032d000021020b0240200241ff01714105470d00200141031024200041106a2903002001109c01200041086a2d000021020b0240200241ff01714106470d00200141041024200041106a2903002001109c01200041086a2d000021020b200241ff017122024101460d032002450d04200028020021020b024020024108470d00200141081024024020002d000422024102470d00200141001024200041086a2802002001101b2000410c6a2802002001101c20002d000421020b0240200241ff01714103470d00200141011024200041046a220341016a2001101e200041286a2802002001101b0240024002400240200141046a280200200141086a2802002202470d00200241016a22052002490d0620024101742204200520052004491b22044100480d062002450d0120012802002106200410002205450d0e2005200620042002200220044b1b10f8021a200610010c020b200128020021050c020b200410002205450d0c0b20012005360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200520026a200341216a2d00003a000020032d000021020b200241037122024101460d052002450d06200028020021020b024020024109470d0020014109102402400240200028020422024102460d002002450d0920024101470d014180e8c200104f000b200141001024200041086a280200200041106a2802002001108e010b200028020021020b2002410a470d122001410a102402400240200041086a220328020022024102460d0020024103460d010c0b0b200141001024200041306a290300200041386a2903002001109a012000410c6a200110a401200328020022024103470d0a0b200141011024200041106a290300200041186a2903002001109a01200041086a28020022024104470d0a0c0b0b1018000b41d09fc300104f000b41c081c300104f000b41c081c300104f000b418cabc200104f000b418cabc200104f000b4180e8c200104f000b200441011019000b200441011019000b20024104460d010b20024105460d010c020b2001410210242000410c6a2802002001108901200041186a290300200041206a2903002001109a01200041286a2903002001109c01200041106a2802002001108901200041086a28020022024105470d010b2001410310242000410c6a2802002001101b200041086a28020022024106470d010c020b20024106460d010b20024101460d010c020b2001410410242000410c6a2802002001101b200041086a28020022024101470d010b41c0ccc200104f000b2002450d01200028020021020b02402002410b470d002001410b10240240200041086a22032d000022024102470d00200141001024200341016a2001101e200041386a290300200041c0006a2903002001109a01200041c8006a2903002001109c012000412c6a280200200041346a2802002001108e0120032d000021020b0240200241ff01714103470d00200141011024200041286a290300200041306a2903002001109a01200041386a2903002001109c012000410c6a280200200041146a2802002001108e01200041186a280200200041206a2802002001108e01200041086a2d000021020b200241037122024101460d022002450d03200028020021020b02402002410c470d002001410c1024024020002d000422024102470d00200141001024200041086a280200200041106a2802002001108e010f0b024020024103470d00200141011024200041046a220041016a2001101e20002d000021020b200241037122014101460d042001450d050b0f0b41c0ccc200104f000b4188a8c200104f000b4188a8c200104f000b41d8ccc200104f000b41d8ccc200104f000bb00301087f230041206b2202240020024100360218200242013703102000280200210320002802082200200241106a101b0240024002402000450d00200041f8006c2104200241186a21050340200341d0006a2802002106024002400240024020022802142207200528020022006b41044f0d00200041046a22082000490d0620074101742200200820082000491b22004100480d062007450d0120022802102109200010002208450d072008200920002007200720004b1b10f8021a200910010c020b200228021021080c020b200010002208450d050b2002200036021420022008360210200528020021000b2005200041046a360200200820006a20063600002003200241106a101c200341d4006a200241106a101e200341f8006a2103200441887f6a22040d000b0b200241106a41086a2203280200210820022802142107200228021021002001280204210520012802002104200342003703002002420037031020042005200241106a1002200241086a2003290300370300200220022903103703002002411020002008100302402007450d00200010010b200241206a24000f0b1018000b200041011019000b830201047f024002400240024002400240200141046a2802002202200141086a28020022036b41204f0d00200341206a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d030b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000f0b1018000b200341011019000bb602010a7f230041106b2202240020012802002103200128020822012000101b0240024002402001450d00200141286c2104200041046a2105034020022003102020022802002106024002400240024020052802002207200041086a220828020022016b200241086a28020022094f0d00200120096a220a2001490d0620074101742201200a200a2001491b22014100480d062007450d012000280200210b20011000220a450d07200a200b20012007200720014b1b10f8021a200b10010c020b2000280200210a0c020b20011000220a450d050b2000200a36020020052001360200200828020021010b2008200120096a360200200a20016a2006200910f8021a02402002280204450d00200610010b200341286a2103200441586a22040d000b0b200241106a24000f0b1018000b200141011019000be20302037f017e230041e0006b22022400024002400240024020012d000022034101460d0020030d0241012103200141016a21010c010b2001410c6a2802002104200141046a2802002101410021030b200241086a200436020020022001360204200220033602002000200210ca020c010b2002410036020820024201370300024002400240410110002204450d00200441023a0000200242818080801037020420022004360200410210002203450d01200320042d00003a000020041001200341003a0001200242828080802037020420022003360200200141086a2903002105410a10002204450d02200420032f00003b000020031001200420053700022002428a808080a001370204200220043602002002200141106a1022200241d0006a41086a2201200241086a280200360200200220022903003703502002410c6a2001280200360200200241033a00002002200229035037020420024103360250200220024104723602542000200241d0006a10ca0220022d00002201417f6a4102490d03024020010d00200241086a280200450d0420022802041001200241e0006a24000f0b200241086a280200450d0320022802041001200241e0006a24000f0b410141011019000b410241011019000b410a41011019000b200241e0006a24000bce0101047f024002400240024002400240200041046a2802002202200041086a28020022036b41024f0d00200341026a22042003490d0420024101742203200420042003491b22034100480d042002450d0120002802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200028020021040c020b200310002204450d030b20002004360200200041046a2003360200200041086a28020021030b200041086a200341026a360200200420036a20013b00000f0b1018000b200341011019000bc10201077f20012802002102200128020822012000101b0240024002402001450d002002200141286c6a2103200041086a2104200041046a21050340024002400240024020052802002206200428020022016b41204f0d00200141206a22072001490d0620064101742201200720072001491b22014100480d062006450d0120002802002108200110002207450d072007200820012006200620014b1b10f8021a200810010c020b200028020021070c020b200110002207450d050b2000200736020020052001360200200428020021010b2004200141206a360200200720016a220141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a29000037000020012002290000370000200241206a290300200010232003200241286a2202470d000b0b0f0b1018000b200141011019000bce0101047f024002400240024002400240200141046a2802002202200141086a28020022036b41084f0d00200341086a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d030b20012004360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200420036a20003700000f0b1018000b200341011019000bc90101047f024002400240024002400240200041046a280200200041086a2802002202470d00200241016a22032002490d0420024101742204200320032004491b22044100480d042002450d0120002802002105200410002203450d052003200520042002200220044b1b10f8021a200510010c020b200028020021030c020b200410002203450d030b20002003360200200041046a2004360200200041086a28020021020b200041086a200241016a360200200320026a20013a00000f0b1018000b200441011019000bd10101047f024002400240024002400240200041046a2802002203200041086a28020022046b20024f0d00200420026a22052004490d0420034101742204200520052004491b22044100480d042003450d0120002802002106200410002205450d052005200620042003200320044b1b10f8021a200610010c020b200028020021050c020b200410002205450d030b20002005360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200520046a2001200210f8021a0f0b1018000b200441011019000bf10103047f017e017f024002400240024002400240200041046a2802002203200041086a28020022046b20024f0d00200420026a22052004490d0420034101742204200520052004491b2206ad4204862207422088a70d042007a722044100480d042003450d0120002802002108200410002205450d0520052008200420034104742203200320044b1b10f8021a200810010c020b200028020021050c020b200410002205450d030b20002005360200200041046a2006360200200041086a28020021040b200041086a200420026a360200200520044104746a2001200241047410f8021a0f0b1018000b200441081019000bf40201067f02400240024002400240024002400240024002400240200041086a280200220220014f0d00200041046a280200220320026b200120026b22044f0d01200220046a22012002490d0620034101742202200120012002491b22014100480d062003450d0320002802002105200110002202450d072002200520012003200320014b1b10f8021a200510010c040b200220014d0d012002210303402003417f6a2103200141016a22012002490d000c0a0b0b2000280200200222036a21054102210620044102490d030c060b200041086a20023602000f0b200110002202450d030b20002002360200200041046a20013602002002200041086a28020022036a210541022106200441024f0d030b2004450d040c030b1018000b200141011019000b410021010340200520016a41003a0000200120066a2102200141016a2207210120022004490d000b200320076a2103200520076a21050b200541003a0000200341016a21030b200041086a20033602000b840301017f0240024002400240024002400240024002400240024020002802002201410b4b0d0020010e0c0a010a0a0a02030405060a070a0b20002d00044102470d092000410c6a280200450d09200041086a28020010010f0b200041086a10290f0b200041086a2d000022014105460d0520014102470d072000410c6a22002802001028200028020010010f0b200041086a2802004102470d06200041106a280200450d062000410c6a28020010010f0b200041086a2d00004102470d052000410c6a22002802001028200028020010010f0b20002d00044102470d042000410c6a22002802001028200028020010010f0b20002802044102490d032000410c6a280200450d03200041086a28020010010f0b200041086a2d000022014102490d0220014102470d01200041306a280200450d022000412c6a28020010010f0b2000410c6a22002802001028200028020010010f0b0240200041106a280200450d002000410c6a28020010010b2000411c6a280200450d00200041186a28020010010f0b0bd80101027f024002400240024002402000280200220141064b0d0020010e0704040104020403040b02402000410c6a2802002202450d0020002802042101200241186c210203400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141186a2101200241686a22020d000b0b200041086a280200450d03200041046a28020010010f0b200041086a280200450d02200028020410010f0b200041086a280200450d01200028020410010f0b200041086a280200450d00200028020410010f0b0bf60d01067f0240024002400240024002400240024002400240024002400240024020002d00002201410d4b0d00024020010e0e0002030405060708090e0a0b0c0d000b200041086a280200450d0d200041046a28020010010f0b0240200041086a280200450d00200041046a28020010010b0240200041146a2802002201450d00200041186a280200450d00200110010b200041246a280200450d0c200041206a28020010010f0b0240200041086a280200450d00200041046a28020010010b200041146a280200450d0b200041106a28020010010f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d00200128020010010b200141106a2101200241706a22020d000b0b200041086a280200450d0a200041046a28020010010f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101200241586a22020d000b0b200041086a280200450d09200041046a28020010010f0b200041086a280200450d08200041046a28020010010f0b200041086a280200450d07200041046a28020010010f0b200041086a280200450d06200041046a28020010010f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d00200328020010010b2001210320012004470d000b0b200041086a280200450d05200041046a28020010010f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d00200128020010010b200141146a21012002416c6a22020d000b0b200041086a280200450d04200041046a28020010010f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a2104034002402003410c6a2802002202450d0020032802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200241706a22020d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b2001210320012004470d000b0b200041086a280200450d03200041046a28020010010f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d00200328020010010b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d002003410c6a28020010010b2001210320012004470d000b0b200041086a280200450d02200041046a28020010010f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a2104034002402003410c6a2802002202450d0020032802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200241706a22020d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b2001210320012004470d000b0b200041086a280200450d01200041046a28020010010f0b024002400240200041046a2d000022014102460d0020014101460d0120010d022000410c6a280200450d03200041086a28020010010f0b0240200041146a2802002201450d002000410c6a280200220520014104746a210603402005220441106a2105024020042802042201450d0002402004410c6a2802002202450d002002410c6c21020340024020012802002203450d00200141046a280200450d00200310010b2001410c6a2101200241746a22020d000b0b200441086a280200450d00200441046a28020010010b20052006470d000b0b200041106a280200450d022000410c6a28020010010c020b0240200041146a2802002202450d002000410c6a28020021012002410c6c21020340024020012802002203450d00200141046a280200450d00200310010b2001410c6a2101200241746a22020d000b0b200041106a280200450d012000410c6a28020010010f0b2000410c6a280200450d00200041086a28020010010f0b0b5c01027f024020012802082202417f4c0d0020012802002101024002402002450d002002100022030d01200241011019000b410121030b20032001200210f80221012000200236020820002002360204200020013602000f0b102c000b05001018000b8a0303027f017e067f230041106b2202240002400240024020012802082203ad2204421e88a70d002004420286a72205417f4c0d0020012802002101024002402005450d002005100022060d01200541041019000b410421060b200241086a2001200120034102746a102e024002400240024002402003200228020c2207200228020822016b41027622054f0d0020034101742208200520052008491b2209ad4202862204422088a70d062004a722054100480d062003450d0120051000220a450d07200a2006200520034102742203200320054b1b10f8021a200610014100210620012007470d020c030b200321092006210a4100210620012007470d010c020b20051000220a450d054100210620012007460d010b200a210303402001280200220528020041016a220841014d0d022005200836020020032005360200200641016a2106200341046a21032007200141046a2201470d000b0b20002006360208200020093602042000200a360200200241106a24000f0b00000b102c000b1018000b200541041019000b100020002002360204200020013602000b7103017f017e027f024020012802082202ad42287e2203422088a70d002003a72204417f4c0d0020012802002101024002402004450d002004100022050d01200441081019000b410821050b20052001200410f80221042000200236020820002002360204200020043602000f0b102c000be00101077f024020002802082201200028020c460d000340200041086a22022001411c6a36020020012802042203450d01200141146a2802002104200141086a28020021052001280210210602402001410c6a2802002201450d0020014104742107200321010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200741706a22070d000b0b02402005450d00200310010b02402004450d00200610010b200228020022012000410c6a280200470d000b0b02402000280204450d00200028020010010b0be10101077f024020002802082201200028020c460d00200041086a21022000410c6a210303402002200141186a36020020012802002204450d01200141146a2802002105200141106a2802002106200128020c210702402001280204450d00200410010b02402005450d0020054104742105200721010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b02402006450d00200710010b200228020022012003280200470d000b0b02402000280204450d00200028020010010b0bc60101067f024020002802082201200028020c2202460d00200041086a210303402003200141106a2204360200024020012802042205450d002001280208210602402001410c6a2802002201450d002001410c6c2104200521010340024020012802002202450d00200141046a280200450d00200210010b2001410c6a2101200441746a22040d000b0b02402006450d00200510010b2000410c6a2802002102200328020021040b2004210120042002470d000b0b02402000280204450d00200028020010010b0bcd0101067f024020002802082201200028020c460d00200041086a21022000410c6a210303402002200141106a3602002001410d6a2d00004102460d012001280204210420012802002105024020012802082201450d0020014104742106200521010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200641706a22060d000b0b02402004450d00200510010b200228020022012003280200470d000b0b02402000280204450d00200028020010010b0bba0705027f017e0c7f027e037f230041f0006b22022400200241086a2001103502400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421b88a70d032004420586a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241f0006a24000f0b4101210620030d030b410021054100210c0c030b102c000b200541011019000b200241d0006a41186a2107200241d0006a41106a2108200141046a21094100210a4100210b410021052003210c03402007420037030020084200370300200241d0006a41086a220d420037030020024200370350200141086a220e410020012802002009280200200241d0006a4120200e2802001004220f200f417f461b220f4120200f4120491b200e2802006a360200200f411f4d0d02200241306a41186a220e2007290300370300200241306a41106a220f2008290300370300200241306a41086a2210200d290300370300200220022903503703302007200e29030022043703002008200f2903002211370300200d20102903002212370300200241106a41086a22132012370300200241106a41106a22142011370300200241106a41186a2215200437030020022002290330220437031020022004370350200720152903002204370300200820142903002211370300200d2013290300221237030020102012370300200f2011370300200e20043703002002200229031022043703302002200437035002402005200c470d00200b200541016a220d200d200b491b220cad4205862204422088a70d042004a7220d4100480d0402402005450d00200d10002213450d0620132006200d200a200a200d4b1b10f802210d20061001200d21060c010b200d10002206450d050b2006200a6a220d2002290330370000200d41186a200e290300370000200d41106a200f290300370000200d41086a2010290300370000200a41206a210a200b41026a210b200541016a22052003490d000b0b2000200c36020420002006360200200041086a2005360200200241f0006a24000f0b200241d0006a41186a2205200241306a41186a290000370300200241d0006a41106a2207200241306a41106a290000370300200241d0006a41086a2208200241306a41086a290000370300200220022900303703502005200241106a41186a2900003703002007200241106a41106a2900003703002008200241106a41086a29000037030020022002290010370350200041003602000240200c450d00200610010b200241f0006a24000f0b1018000b200d41011019000bcc0301057f230041106b2202240041002103200241003a000f200128020020012802042002410f6a410120012802081004210420012001280208200441016a220441014b6a220536020802400240024020044102490d0002400240024020022d000f22064103712204450d0020044101460d0120044102470d0220024100360208200220063a000841012103200141086a220441002001280200200141046a280200200241086a41017241032005100422012001417f461b22014103200141034922011b20042802006a36020020010d04200228020841027621040c050b20064102762104410121030c040b41002103200241003b0106200220063a00062001280200200141046a280200200241066a4101724101200510042104200141086a22012001280200200441016a220141014b6a36020020014102490d0120022f01064102762104410121030c030b200641044f0d02200141046a28020021044100210320024100360200200141086a2206410020012802002004200241042005100422012001417f461b22014104200141044922011b20062802006a36020020010d0020022802002104410121030c020b0c010b410021030b2000200436020420002003360200200241106a24000bae0605027f017e0c7f027e017f230041f0006b22022400200241086a2001103502400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421b88a70d032004420586a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241f0006a24000f0b4101210620030d030b410021054100210c0c030b102c000b200541011019000b200241d0006a41186a2107200241d0006a41106a2108200141046a21094100210a4100210b410021052003210c03402007420037030020084200370300200241d0006a41086a220d420037030020024200370350200141086a220e410020012802002009280200200241d0006a4120200e2802001004220f200f417f461b220f4120200f4120491b200e2802006a360200200f411f4d0d02200241306a41186a220e2007290300370300200241306a41106a220f2008290300370300200241306a41086a2210200d290300370300200220022903503703302007200e29030022043703002008200f2903002211370300200d20102903002212370300200241106a41086a220f2012370300200241106a41106a220d2011370300200241106a41186a221020043703002002200229033022043703102002200437035002402005200c470d00200b200541016a220e200e200b491b220cad4205862204422088a70d042004a7220e4100480d0402402005450d00200e10002213450d0620132006200e200a200a200e4b1b10f802210e20061001200e21060c010b200e10002206450d050b2006200a6a220e2002290310370000200e41186a2010290300370000200e41106a200d290300370000200e41086a200f290300370000200a41206a210a200b41026a210b200541016a22052003490d000b0b2000200c36020420002006360200200041086a2005360200200241f0006a24000f0b200241d0006a41186a200241306a41186a290000370300200241d0006a41106a200241306a41106a290000370300200241d0006a41086a200241306a41086a29000037030020022002290030370350200041003602000240200c450d00200610010b200241f0006a24000f0b1018000b200e41011019000bf50803027f017e107f230041e0026b22022400200241086a200110350240024002400240024002400240024002400240024002402002280208450d00200228020c2203ad42f8007e2204422088a70d032004a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241e0026a24000f0b4108210620030d030b4100210c4100210d0c030b102c000b200541081019000b200241a0016a4104722107200141086a2108200241c0026a41186a2109200241c0026a41106a210a4100210b410021054100210c2003210d0340200141046a220e280200210f20082802002110200241003602f001200841002001280200200f200241f0016a410420101004220f200f417f461b220f4104200f4104491b20082802006a360200200f41034d0d0320022802f0012111200241f0016a2001103820022802f001410d460d03200241a0016a200241f0016a41d00010f8021a20094200370300200a4200370300200241c0026a41086a220f4200370300200242003703c002200841002001280200200e280200200241c0026a41202008280200100422102010417f461b2210412020104120491b20082802006a3602002010411f4d0d02200241306a41186a220e2009290300370300200241306a41106a2212200a290300370300200241306a41086a2213200f290300370300200220022903c00237033020022802a0012110200241d4006a200741cc0010f8021a200241f0016a200241d4006a41cc0010f8021a2009200e290300370300200a2012290300370300200f2013290300370300200220022903303703c0022010410d460d04200241a0016a200241f0016a41cc0010f8021a200241106a41186a220e2009290300370300200241106a41106a2212200a290300370300200241106a41086a2213200f290300370300200220022903c0023703100240200c200d470d00200b200c41016a220f200f200b491b220dad42f8007e2204422088a70d062004a7220f4100480d060240200c450d00200f10002214450d0820142006200f20052005200f4b1b10f802210f20061001200f21060c010b200f10002206450d070b200620056a220f2010360200200f41046a200241a0016a41cc0010f8021a200f41d0006a2011360200200f41ec006a200e290300370200200f41e4006a2012290300370200200f41dc006a2013290300370200200f41d4006a2002290310370200200b41026a210b200541f8006a2105200c41016a220c2003490d000b0b2000200d36020420002006360200200041086a200c360200200241e0026a24000f0b200241a0016a10280b200241f0016a200241d4006a41cc0010f8021a200241c0026a41186a200241306a41186a290300370300200241c0026a41106a200241306a41106a290300370300200241c0026a41086a200241306a41086a290300370300200220022903303703c0020b200041003602000240200c450d002006210f0340200f1028200f41f8006a210f200541887f6a22050d000b0b0240200d450d00200610010b200241e0026a24000f0b1018000b200f41081019000ba55b05037f037e057f047e077f230041b0076b22022400200241003a0090062001280200200128020420024190066a410120012802081004210320012001280208200341016a220341014b6a22043602080240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d0090062203410c4b0d0a024020030e0d00090607030a0c080e050d0204000b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a36020020034102490d9a0120022d009006450d0f0c9a010b2000410d360200200241b0076a24000f0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d7f20022d0090062203450d0e20034101470d7f20024198056a2001109801200228029805450d7f200241a8056a290300210520022903a005210620024188056a2001109901200228028805450d7f200229039005210720024180056a20011035200228028005450d7f2002280284052203417f4c0d81012003450d6d200310002204450d8f0120044100200310f7021a0c6e0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a22083602004102210420034102490d5320022d009006220941094b0d53024020090e0a53004a4c484f504d5249530b20024198016a20011035200228029801450d53200228029c012203410876210a410321040c4d0b200241003a009006410421032001280200200141046a28020020024190066a4101200410042104200141086a22082008280200200441016a220441014b6a220836020020044102490d1820022d0090062204450d0d20044101470d18200241a8066a4200370300200241a0066a420037030020024190066a41086a4200370300200242003703900641042103200141086a220441002001280200200141046a28020020024190066a41202008100422012001417f461b22014120200141204922011b20042802006a36020020010d17200220022f0091063b01be0520022d009006210820022800930621042002290097062107200229009f06210520022800a706210b20022800ab06210920022d00af06210c200220022f01be0522013b019006200220013b01bc05200220013b01ba05410321030c93010b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a36020020034102490d940120022d009006450d090c94010b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a36020020034102490d0e20022d0090062203450d0c20034101470d0e20024190066a200110a30120022d00900622034102460d0e20022d009306210420022f00910621092002419c066a2902002107200241ac066a2902002105200241a8066a2802002108200241a4066a280200210b2002290294062106200241f0006a20011098012002280270450d0e200241f0006a41106a290300210d2002290378210e200241d8006a20011098012002280258450d0e20092004411074722101200241e8006a290300210f41032104200229036021100c0d0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d3420022d0090062203450d1120034101460d1020034102470d34200241003a009006410421032001280200200141046a28020020024190066a4101200410042104200141086a22012001280200200441016a220141014b6a36020020014102490d3420022d00900621010c120b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d1b20022d009006220341044b0d1b024020030e05001d171916000b20024190066a200110382002280290062101200241e0066a20024190066a41047241cc0010f8021a2001410d460d1b200241c0056a200241e0066a41cc0010f8021a41d00010002204450d830120042001360200200441046a200241c0056a41cc0010f8021a410221030c1a0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d7320022d009006220841054b0d734103210b024020080e0600662829262c000b200241106a200110352002280210450d7320022802142204417f4c0d7a2004450d61200410002203450d850120034100200410f7021a0c620b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d4e20022d009006220341054b0d4e024020030e06002c292a262d000b20024190066a200110382002280290062104200241e0066a20024190066a41047241cc0010f8021a2004410d460d4e200241c0056a200241e0066a41cc0010f8021a41d00010002203450d820120032004360200200341046a200241c0056a41cc0010f8021a20024180026a2001109801200229038002a7450d4d20024190026a29030021052002290388022107410221040c2d0b2000410d360200200241b0076a24000f0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a36020020034102490d6620022d009006220341084b0d66024020030e090037343533383a363b000b20024190066a2001103d2002280290062203450d662002290294062107200241b0026a2001103520022802b002450d6520022802b40221012007420888210d2003410876210c2007a72104410221110c3c0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d2020022d009006220341044b0d20024020030e05001e1c1d13000b200241e0036a200110980120022802e003450d20200241f0036a290300210720022903e803210520024190066a200110a3014102210420022d00900622034102460d20200241ac066a2902002106200241a4066a290200210d20022f009106210120022d0093062108200229029406210e20022002419c066a2902003703e8062002200e3703e0062002200d3703f006200120084110747221010c1f0b200241003a0090062001280200200141046a28020020024190066a4101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d0820022d0090062203450d0720034101470d08200241a8066a4200370300200241a0066a420037030020024190066a41086a4200370300200242003703900641042103200141086a220841002001280200200141046a28020020024190066a41202004100422042004417f461b22044120200441204922041b20082802006a36020020040d17200220022f0091063b01e00620022d009006210c2002280093062104200229009f06210720022800a706211120022800ab06211220022d00af0621132002290097062105200220022f01e00622083b019006200220083b01bc05200241d0036a2001103520022802d003450d1820022802d4032108200241003a009006410421032001280200200141046a28020020024190066a4101200141086a22012802001004210b20012001280200200b41016a220b41014b6a360200200b4102490d182005422088a7210b2005a7210120022d0090062109200220022f01bc053b01be05410321030c190b200241d8036a2001103520022802d803450d8a0120022802dc032203417f4c0d742003450d4a200310002204450d7920044100200310f7021a0c4b0b200220011099012002290300a7450d8a012002290308210720004100360200200041106a2007370300200041086a4202370300200241b0076a24000f0b200241a8066a420037030020024190066a41106a420037030020024190066a41086a4200370300200242003703900641042108200141086a220341002001280200200141046a28020020024190066a41202004100422042004417f461b22044120200441204922041b20032802006a36020020040d09200220022f0091063b01e00620022d009006210b2002280093062104200229009706210f200229009f06211020022800a706210920022800ab06210c20022d00af062111200220022f01e00622033b019006200220033b01bc05200241e0046a200110980120022802e004450d64200241e0046a41106a290300210d20022903e8042107200241d0046a200110990120022802d004450d6420022903d804210e200241c8046a2001103520022802c804450d6420022802cc042203417f4c0d722003450d62200310002212450d810120124100200310f7021a0c630b200241b0056a2001103520022802b005450d2720022802b4052208417f4c0d712008450d4c200810002211450d7720114100200810f7021a0c4d0b20024190066a200110a3014102210420022d00900622034102460d0120022d009306210920022f009106210c2002419c066a2902002107200241ac066a2902002105200241a8066a2802002108200241a4066a280200210b2002290294062106200241c0006a20011098012002280240450d01200c2009411074722101200241c0006a41106a290300210d2002290348210e0b200020013b000d200041023602002000410f6a20014110763a0000200041c8006a200f370200200041c0006a2010370200200041386a200d370200200041306a200e370200200041186a2007370000200041106a2006370000200041286a2005370000200041246a2008360000200041206a200b3600002000410c6a20033a0000200041086a2004360200200241b0076a24000f0b2000410d360200200241b0076a24000f0b200241c8036a2001103520022802c803450d0020022802cc03210420024190066a200110382002280290062103200241e0066a20024190066a41047241cc0010f8021a2003410d470d260b200220022f01be053b0190060c81010b20024188016a2001109901200229038801a7450d232002290390012207422088a721092007a7210c410321030c010b200241a8066a4200370300200241a0066a420037030020024190066a41086a42003703002002420037039006200141086a220341002001280200200141046a28020020024190066a41202004100422012001417f461b22014120200141204922011b20032802006a36020020010d21200220022f0091063b01e00620022d00900621012002280093062111200229009f06210720022800a706210b20022800ab06210420022d00af0621082002290097062105200220022f01e00622033b019006200220033b01bc05200220033b01be05200220022f01be0522033b01c005200220033b01ba052005422088a721092005a7210c410221030b200220022f01ba0522123b019006200220123b01b805200020013a0009200041086a20033a000020004103360200200041286a20083a0000200041246a2004360200200041206a200b360200200041186a2007370200200041146a2009360200200041106a200c3602002000410c6a2011360200200020022f01b8053b000a200241b0076a24000f0b200220022f01e0063b0190060c660b200220022f01be053b0190060b0c790b200241b8036a200110990120022903b803a7450d0520022903c0032207422088a721012007a72108410621030c030b200241a8066a4200370300200241a0066a420037030020024190066a41086a4200370300200242003703900641042103200141086a220841002001280200200141046a28020020024190066a41202004100422012001417f461b22014120200141204922011b20082802006a36020020010d3c200220022f0091063b01e00620022d009006210b2002280093062104200229009f06210720022800a706210920022800ab06210c20022d00af0621112002290097062105200220022f01e00622013b019006200220013b01bc05200220013b01be052005422088a721012005a721080c420b200241c0046a2001103520022802c004450d0d20022802c40422034108762101410621040c0b0b200241a8036a200110990120022903a803a7450d0220022903b0032207422088a721012007a72108410521030b0b200220022f01be053b0190060c400b200220022f01be053b0190060c710b200241a8066a4200370300200241a0066a420037030020024190066a41086a42003703002002420037039006200141086a220341002001280200200141046a220828020020024190066a41202004100422042004417f461b22044120200441204922041b20032802006a221236020020040d37200220022f0091063b01e00620022d009006210b20022800930621042002290097062105200229009f06210720022800a706210920022800ab06210c20022d00af062111200220022f01e00622133b019006200220133b01c005200241003a0090062001280200200828020020024190066a410120121004210120032003280200200141016a41014b22016a3602002001450d3b20022d0090062112200220022f01c0053b01be052005422088a721012005a72108410321030c3d0b200220022f01e0063b0190060b0b200220022f01be053b01900620034104460d700c150b200141046a28020021032002410036029006200141086a220841002001280200200320024190066a41042004100422032003417f461b22034104200341044922031b20082802006a36020020030d042002280290062103200241a0046a200110980120022802a004450d04200241b0046a290300210720022903a804210520024190046a2001109901200228029004450d04200229039804210641042104200141046a280200210b200141086a220828020021092002410036029006200841002001280200200b20024190066a41042009100422012001417f461b22014104200141044922011b20082802006a36020020010d042002280290062101200241f0066a2007370300200220053703e806200220013602e006200341087621010c030b200241b8046a2001103520022802b804450d0320022802bc0422034108762101410521040c010b200241f8036a200110980120022903f803a7450d0220024188046a290300210720022002290380043703e006200220073703e806410321040b0b20024190066a41106a200241e0066a41106a290300220d37030020024190066a41086a200241e0066a41086a290300220e370300200241c0056a41086a2208200e370300200241c0056a41106a220b200d370300200220022903e006220d3703c0052002200d37039006200041386a2007370200200041306a20053702002000410c6a2001410874200341ff017172360200200041086a20043602002000410a360200200041286a2006370200200041106a20022903c005370200200041186a2008290300370200200041206a200b290300370200200241b0076a24000f0b20024190066a41106a200241e0066a41106a29030037030020024190066a41086a200241e0066a41086a290300370300200220022903e006370390062000410d360200200241b0076a24000f0b200241206a200110352002280220450d4d20022802242204417f4c0d542004450d37200410002203450d6020034100200410f7021a0c380b200241a8026a2001103520022802a802450d284106210420022802ac0221030c070b200241186a200110352002280218450d4b200228021c2204417f4c0d522004450d37200410002203450d5f20034100200410f7021a0c380b2002420037039006200141086a220341002001280200200141046a28020020024190066a41082004100422012001417f461b22014108200141084922011b20032802006a36020020010d4a20022903900621074105210b0c3c0b200241a0026a2001103520022802a002450d2520022802a4022103200241003a009006410421042001280200200141046a28020020024190066a4101200141086a22012802001004210820012001280200200841016a41014b22086a3602002008450d2520022d00900621080c050b20024190066a200110382002280290062104200241e0066a20024190066a41047241cc0010f8021a2004410d460d24200241c0056a200241e0066a41cc0010f8021a41d00010002203450d5920032004360200200341046a200241c0056a41cc0010f8021a200241003a0090062001280200200141046a28020020024190066a4101200141086a22042802001004210820042004280200200841016a220841014b6a220b36020020084102490d2320022d009006220841034f0d23420021052002420037039006200141086a220441002001280200200141046a28020020024190066a4108200b100422012001417f461b22014108200141084922011b20042802006a36020020010d232002290390062107410521040c040b200241386a200110352002280238450d47200228023c2213ad220742187e2205422088a70d4e2005a72204417f4c0d4e2004450d372004100022030d38200441041019000b20024198026a20011035200228029802450d2241032104200228029c0221030c010b2002420037039006200141086a220341002001280200200141046a220828020020024190066a41082004100422042004417f461b22044108200441084922041b20032802006a220b36020020040d212002290390062107200828020021042002410036029006200341002001280200200420024190066a4104200b100422012001417f461b2201410420014104491b20032802006a360200200141034d0d21200228029006210342002105410721040b0b200220022f01be0522013b019006200220013b01bc05200041186a2005370200200041106a2007370200200020083a0009200041086a20043a0000200041053602002000410c6a2003360200200020022f01bc053b000a200241b0076a24000f0b410021040c2b0b200220022f01e0063b019006200220022f01be053b01c0050b200220022f01ba053b0190062000410d360200200241b0076a24000f0b200241c0056a200241e0066a41cc0010f8021a41d00010002201450d4d20012003360200200141046a200241c0056a41cc0010f8021a200220022f01be053b019006410221030b200220022f0190063b01ba052000200c3a0005200020033a000420004108360200200041286a2008360200200020093a0025200041246a20133a0000200041206a20123602002000411c6a2011360200200041146a2007370200200041106a200b3602002000410c6a2001360200200041086a2004360200200020022f01ba053b0006200241b0076a24000f0b20024190066a200110a30120022d00900622034102460d3320022d009306210420022f00910621092002419c066a290200210d200241ac066a2902002107200241a8066a2802002108200241a4066a280200210b200229029406210e200241e8026a200110980120022802e802450d33200241e8026a41106a290300210620022903f0022105200241e0026a2001103520022802e002450d332009200441107472210c200d422088a72113200da7210120022802e4022112200e420888210d200ea72104410621110c0a0b200241d0026a2001103520022802d002450d3220022802d4022203410876210c410421110c040b200241d8026a2001103520022802d802450d3120022802dc022203410876210c410521110c030b20024188036a2001109901200229038803a7450d302002290390032207420888210d2007a72104410921110c050b200241c8026a2001103520022802c802450d2f20022802cc02210320024190066a200110a30120022d00900622044102460d2f2002419c066a2902002107200241ac066a2902002105200241a4066a2802002108200220022902940622063700e306200241eb066a2007370000200220022d0093063a00e206200220022f0091063b01e0062002200241a8066a2802003602c005200220053702c405200241c0026a2001103520022802c002450d2f20022802c4022109200241b8026a2001103520022802b802450d2f2005422088a721122006422088a721012007422088a7210b2007a721132003410876210c20023502e00620023301e40620023100e6064210868442208684210d20022903c005210720022802bc02ad210542002106410321110c060b20024180036a20011035200228028003450d2e2002280284032203410876210c410721110b0c030b20024190066a200110a30120022d00900622034102460d2c2002290294062205420888210d20022f00910620022d00930641107472210c2002419c066a2902002206422088a72113200241a4066a280200210b200241a8066a2802002108200241ac066a29020021072005a721042006a72101410821110c030b20024198036a2001109901200229039803a7450d2b20022903a0032207420888210d2007a72104410a21110b0b0b20004106360200200041c0006a2006370200200041386a2005370200200041346a2009360200200041306a2012360200200041286a2007370200200041246a2008360200200041206a200b3602002000411c6a2013360200200041186a2001360200200041086a20113602002000410c6a200c410874200341ff017172360200200041106a200d4208862004ad42ff018384370200200241b0076a24000f0b200241c8016a2001103520022802c801450d0b20022802cc012103200241c0016a2001103520022802c001450d0b20022802c401210b200241a8016a200110980120022903a801a7450d0b200241b8016a29030021072003410876210a20022903b0012205a72114410621040c020b200241f8016a2001103520022802f801450d0a20022802fc012203410876210a410b21040c040b20024190066a200110a30120022d00900622034102460d092002419c066a290200210720022f00910620022d00930641107472210a200241ac066a2902002205422088a721132005421088a721122005420888a72115200241a4066a280200210b200241a8066a280200210c2005a721112002290294062205a72114410421040b2005422088a721160c070b200241a0016a2001103520022802a001450d0720022802a4012203410876210a410521040c010b200241f0016a2001103520022802f001450d0620022802f4012203410876210a410921040b0c040b200241d0016a200110990120022903d001a7450d0420022903d8012207422088a721162007a72114410721040c010b200241e0016a200110990120022903e001a7450d0320022903e8012207422088a721162007a72114410821040b0c010b200241003a0090062001280200200141046a28020020024190066a4101200810042103200141086a22012001280200200341016a220141014b6a36020020014102490d0120022d0090062117410a21040b200220022f01e00622013b019006200220013b01c005200020173a0009200041086a20043a0000200041043602002000412c6a2013360200200020123b012a200020153a0029200041286a20113a0000200041246a200c360200200041206a200b360200200041186a2007370200200041146a2016360200200041106a20143602002000410c6a200a410874200341ff017172360200200020022f01c0053b000a200241b0076a24000f0b200220022f01e0063b0190062000410d360200200241b0076a24000f0b200310a001200310010b200220022f01be053b0190062000410d360200200241b0076a24000f0b410121040b200141086a2208200341002001280200200141046a280200200420032008280200100422012001417f461b2201200120034b1b20082802006a3602000240200320014d0d00200410010c3f0b2004450d3e20004289808080203703002000410c6a2003ad2207422086200784370200200041086a2004360200200241b0076a24000f0b200220022f01e0063b0190060c010b200220022f01e0063b0190060b410721030c040b410121110b41002104200141086a220b200841002001280200200141046a28020020112008200b280200100422012001417f461b2201200120084b1b200b2802006a3602002008ad220742208620078421070240200820014d0d00201110010c060b2011450d0441022103201121040c360b410721030b0b200220022f01be053b01900620034107460d320b200220022f0190063b01ba052000200b3a0009200041086a20033a000020004107360200200020123a0029200041286a20113a0000200041246a200c360200200041206a2009360200200041186a2007370200200041146a2001360200200041106a20083602002000410c6a2004360200200020022f01ba053b000a200241b0076a24000f0b201121040b0c300b410121030b200141086a2208200441002001280200200141046a280200200320042008280200100422012001417f461b2201200120044b1b20082802006a360200200420014b0d132003450d142004ad220742208620078421074106210b0c060b410121030b4104210b200141086a2208200441002001280200200141046a280200200320042008280200100422012001417f461b2201200120044b1b20082802006a360200200420014b0d112003450d122004ad220742208620078421070c040b410121030b200141086a2208200441002001280200200141046a280200200320042008280200100422012001417f461b2201200120044b1b20082802006a360200200420014b0d0f2003450d102004ad220742208620078421074102210b0c020b410421030b02402013450d00200141086a2108200141046a2111410021120340200241306a200110352002280230450d0e20022802342204417f4c0d17024002402004450d0020041000220b450d1b200b4100200410f7021a0c010b4101210b0b20082004410020012802002011280200200b20042008280200100422092009417f461b2209200920044b1b20082802006a360200200420094b0d0d200b450d0e2004ad22054220862005842105200241286a200110352002280228450d0c200228022c2204417f4c0d17024002402004450d00200410002209450d1c20094100200410f7021a0c010b410121090b200820044100200128020020112802002009200420082802001004220c200c417f461b220c200c20044b1b20082802006a3602002004200c4b0d0b2009450d0c02402007422088a7220c2007a7470d00200c41016a2215200c490d19200c410174220a20152015200a491bad220642187e220d422088a70d19200da722154100480d1902400240200c450d0020151000220a450d1e200a20032015200c41186c220c200c20154b1b10f802210c20031001200c21030c010b201510002203450d1d0b20074280808080708320068421070b20032007422088a741186c6a220c200936020c200c2005370204200c200b360200200c41106a2004ad220542208620058437020020074280808080107c2107201241016a22122013490d000b0b2003450d0e4107210b0b20004101360200200041106a20073702002000410c6a2003360200200041086a200b360200200241b0076a24000f0b410121040b200141086a2208200341002001280200200141046a2802002004200320082802001004220b200b417f461b220b200b20034b1b20082802006a3602002003200b4b0d0f2004450d102003ad220d422086200d84210f200241f8046a2001103520022802f804450d0e20022802fc042203417f4c0d122003450d0c200310002208450d2220084100200310f7021a0c0d0b2007a7450d00200310010b2000410d360200200241b0076a24000f0b410121120b41042108200141086a2213200341002001280200200141046a280200201220032013280200100422012001417f461b2201200120034b1b20132802006a3602000240200320014d0d00201210010c010b2012450d00200220022f01bc053b01c0052003ad2205422086200584220542088842088620054238862012ad4218868422064238888421052011ad42ff01832006420886842106410221080c010b0b200220022f01c0053b01900620084104460d0b0c1d0b200910010b2005a7450d010b200b10010b02402007422088a72201450d00200141186c21042003210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141186a2101200441686a22040d000b0b2007a7450d010b200310010b2000410d360200200241b0076a24000f0b410121080b200141086a220b200341002001280200200141046a28020020082003200b280200100422012001417f461b2201200120034b1b200b2802006a3602000240200320014d0d00200810010c010b2008450d00200220022f01c0053b0190062003ad220d422086200d84220d4220862008ad842110200d422088a72109410321080c150b200fa7450d010b200410010b200220022f01c0053b0190060b2000410d360200200241b0076a24000f0b102c000b1018000b200441011019000b200441011019000b201541041019000b200341011019000b200841011019000b41d00041081019000b41d00041081019000b41d00041081019000b41d00041081019000b200441011019000b200441011019000b200441011019000b200341011019000b200341011019000b200341011019000b200220022f0190063b01be05200041c0006a200d370000200041386a2007370000200041306a2005370000200041286a20063700002000200b3a0009200041086a20083a00002000410b360200200041c8006a200e370000200041246a200c360000200041206a2009360000200041186a2010370000200041106a200f3700002000410c6a2004360000200020022f01be053b000a200241b0076a24000f0b2000410d360200200241b0076a24000f0b0b20024190066a41026a2201200241e0066a41026a2d00003a0000200220022f01ba053b01be05200220022f00e0063b019006024020034104470d002000410d360200200241b0076a24000f0b200241c0056a41026a221120012d00003a0000200220022f01be053b01b805200220022f0190063b01c005200020083a0005200020033a00042000410c360200200041246a200c3a0000200041206a20093600002000411c6a200b360000200041146a20053700002000410c6a2007370000200041086a2004360000200020022f01b8053b0006200020022f01c0053b0025200041276a20112d00003a0000200241b0076a24000f0b2000410d360200200241b0076a24000f0b2000410d360200200241b0076a24000f0b2000410d360200200241b0076a24000bb50705027f017e0c7f027e037f230041f0006b22022400200241086a2001103a02400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421b88a70d032004420586a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241f0006a24000f0b4101210620030d030b410021054100210d0c030b102c000b200541011019000b200241d0006a41186a2107200241d0006a41106a2108200241d0006a41086a2109200141046a210a4100210b4100210c410021052003210d034020074200370300200842003703002009420037030020024200370350200241d0006a2001280200220e200a280200220f4120200f4120491b221010f8021a200a200f20106b3602002001200e20106a360200200f411f4d0d02200241306a41186a220f2007290300370300200241306a41106a22102008290300370300200241306a41086a220e2009290300370300200220022903503703302007200f29030022043703002008201029030022113703002009200e2903002212370300200241106a41086a22132012370300200241106a41106a22142011370300200241106a41186a2215200437030020022002290330220437031020022004370350200720152903002204370300200820142903002211370300200920132903002212370300200e201237030020102011370300200f20043703002002200229031022043703302002200437035002402005200d470d00200c200541016a22132013200c491b220dad4205862204422088a70d042004a722134100480d0402402005450d00201310002214450d06201420062013200b200b20134b1b10f802211320061001201321060c010b201310002206450d050b2006200b6a22132002290330370000201341186a200f290300370000201341106a2010290300370000201341086a200e290300370000200b41206a210b200c41026a210c200541016a22052003490d000b0b2000200d36020420002006360200200041086a2005360200200241f0006a24000f0b200241d0006a41186a2205200241306a41186a290000370300200241d0006a41106a220f200241306a41106a290000370300200241d0006a41086a2207200241306a41086a290000370300200220022900303703502005200241106a41186a290000370300200f200241106a41106a2900003703002007200241106a41086a29000037030020022002290010370350200041003602000240200d450d00200610010b200241f0006a24000f0b1018000b201341011019000bcb0301077f230041106b22022400200241003a0003200241036a2001280200220320012802042204410047220510f8021a0240024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002402004450d000240024020022d000322034103712204450d00024020044101460d0020044102470d0241002104200241003a000e200241003b010c2002410c6a200520064103200641034922071b220810f8021a200141046a200620086b3602002001200520086a36020020070d0520022f010c20022d000e411074724108742003724102762101410121040c050b200241003a000b2002410b6a20052006410047220410f8021a20062004490d06200141046a200620046b3602002001200520046a3602002006450d0220022d000b4108742003724102762101410121040c040b20034102762101410121040c030b200341044f0d004100210420024100360204200241046a200520064104200641044922081b220310f8021a200141046a200620036b3602002001200520036a36020020080d0120022802042101410121040c020b410021040b0b2000200136020420002004360200200241106a24000f0b20052004107a000b20042006107a000bdb0303027f017e097f230041106b2202240020022001103502400240024002400240024002400240024002402002280200450d0020022802042203ad2204421e88a70d032004420286a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241106a24000f0b4104210620030d030b410021054100210a0c030b102c000b200541041019000b200141086a21074100210841002109410021052003210a0340200141046a280200210b2007280200210c2002410036020c200741002001280200200b2002410c6a4104200c1004220b200b417f461b220b4104200b410449220b1b20072802006a360200200b0d02200228020c210b02402005200a470d002009200541016a220c200c2009491b220aad4202862204422088a70d042004a7220c4100480d0402402005450d00200c1000220d450d06200d2006200c20082008200c4b1b10f802210c20061001200c21060c010b200c10002206450d050b200620086a200b360200200841046a2108200941026a2109200541016a22052003490d000b0b2000200a36020420002006360200200041086a2005360200200241106a24000f0b200041003602000240200a450d00200610010b200241106a24000f0b1018000b200c41041019000bf50705027f017e0e7f027e017f23004190016b22022400200241086a20011035024002400240024002400240024002400240024002402002280208450d00200228020c2203ad42287e2204422088a70d032004a72205417f4c0d032005450d01200510002206450d042003450d020c050b2000410036020020024190016a24000f0b4108210620030d030b4100210c4100210d0c030b102c000b200541081019000b200241f0006a41186a2107200241f0006a41106a2108200141046a21094100210a4100210b4100210c2003210d03402007420037030020084200370300200241f0006a41086a220e420037030020024200370370200141086a2205410020012802002009280200200241f0006a412020052802001004220f200f417f461b220f4120200f4120491b20052802006a2210360200200f411f4d0d02200241d0006a41186a220f2007290300370300200241d0006a41106a22112008290300370300200241d0006a41086a2212200e290300370300200220022903703703502007200f2903002204370300200820112903002213370300200e20122903002214370300200241306a41086a22112014370300200241306a41106a22122013370300200241306a41186a2215200437030020022002290350220437033020022004370370200242003703702005410020012802002009280200200241f0006a410820101004220f200f417f461b220f4108200f4108491b20052802006a360200200f41074d0d0320022903702104200241106a41186a22052015290300370300200241106a41106a220f2012290300370300200241106a41086a2210201129030037030020022002290330370310200720052903003703002008200f290300370300200e2010290300370300200220022903103703700240200c200d470d00200a200c41016a22052005200a491b220dad42287e2213422088a70d052013a722054100480d050240200c450d0020051000220f450d07200f20062005200b200b20054b1b10f802210520061001200521060c010b200510002206450d060b2006200b6a22052002290370370300200541186a2007290300370300200541106a2008290300370300200541086a200e290300370300200541206a2004370300200a41026a210a200b41286a210b200c41016a220c2003490d000b0b2000200d36020420002006360200200041086a200c36020020024190016a24000f0b200241f0006a41186a200241d0006a41186a290000370300200241f0006a41106a200241d0006a41106a290000370300200241f0006a41086a200241d0006a41086a290000370300200220022900503703700b200041003602000240200d450d00200610010b20024190016a24000f0b1018000b200541081019000b9203010a7f230041106b22022400200220011035024002400240024002400240024002402002280200450d0020022802042203417f4c0d062003450d01200310002204450d07200141046a2105200141086a2106410021074100210820032109034020082108200241003a000f200128020020052802002002410f6a410120062802001004210a20062006280200200a41016a220a41014b6a360200200a4102490d0420022d000f210a024020082009470d002007200841016a220920092007491b22094100480d0602402008450d0020091000220b450d08200b200420092008200820094b1b10f802210b20041001200b21040c010b200910002204450d070b200420086a200a3a0000200741026a2107200841016a22082003490d000c030b0b20004100360200200241106a24000f0b4101210441002108410021090b2000200936020420002004360200200041086a2008360200200241106a24000f0b2000410036020002402009450d00200410010b200241106a24000f0b1018000b200941011019000b102c000b200341011019000b8d0606027f017e0b7f017e027f017e230041d0006b22022400200241086a200110350240024002400240024002400240024002402002280208450d00200228020c2203ad42307e2204422088a70d032004a72205417f4c0d032005450d01200510002206450d042003450d020c050b20004100360200200241d0006a24000f0b4108210620030d030b4100210c4100210d0c030b102c000b200541081019000b200141046a2107200141086a2108200241306a41186a21094100210a4100210b4100210c2003210d0240034020024200370338200242003703302008410020012802002007280200200241306a41102008280200100422052005417f461b2205411020054110491b20082802006a220e3602002005410f4d0d01200241306a41086a220f29030021042002290330211020094200370300200241306a41106a22114200370300200f4200370300200242003703302008410020012802002007280200200241306a4120200e100422052005417f461b2205412020054120491b20082802006a3602002005411f4d0d01200241106a41186a22052009290300370300200241106a41106a220e2011290300370300200241106a41086a2212200f29030037030020022002290330370310200920052903003703002011200e290300370300200f2012290300370300200220022903103703300240200c200d470d00200a200c41016a22052005200a491b220dad42307e2213422088a70d042013a722054100480d040240200c450d0020051000220e450d06200e20062005200b200b20054b1b10f802210520061001200521060c010b200510002206450d050b2006200b6a2205200437030820052010370300200541286a2009290300370300200541206a2011290300370300200541186a200f290300370300200541106a2002290330370300200a41026a210a200b41306a210b200c41016a220c2003490d000c020b0b200041003602000240200d450d00200610010b200241d0006a24000f0b2000200d36020420002006360200200041086a200c360200200241d0006a24000f0b1018000b200541081019000bc70201057f0240024002400240024002400240200041046a2802002202200028020822036b20012802042204200128020022056b22064f0d00200320066a22052003490d0420024101742203200520052003491b22034100480d042002450d0120002802002105200310002206450d052006200520032002200220034b1b10f8021a200510010c020b2000280200210620052004470d020c050b200310002206450d030b20002006360200200041046a2003360200200041086a280200210320012802002205200141046a280200460d030b2001200541016a36020020052d00002105200141046a210202400340200620036a20053a0000200128020022052002280200460d01200341016a21032001200541016a36020020052d000021050c000b0b200041086a200341016a3602000f0b1018000b200341011019000b200041086a20033602000bc20307017f017e047f017e037f027e027f230041c0006b2202240020012902002103410021040240024002400240024002400240200128020c2205200128020822066b2201450d0020014105752207ad42287e2208422088a70d022008a722094100480d0220091000220a450d0320062005470d010c040b4108210a4100210720062005460d030b200141606a410576210b200a21010340200641186a2900002108200641106a290000210c2006290000210d200241206a41086a2204200641086a290000370300200241206a41106a2209200c370300200241206a41186a220e2008370300200241086a220f2004290300370300200241106a22042009290300370300200241186a2209200e2903003703002002200d37032020022002290320370300200141186a2009290300370000200141106a2004290300370000200141086a200f29030037000020012002290300370000200141206a4201370300200141286a21012005200641206a2206470d000b200b41016a210420034280808080105a0d030c040b1018000b200941081019000b2003428080808010540d010b2003a710010b20002004360208200020073602042000200a360200200241c0006a24000ba90705037f017e0b7f027e037f230041e0006b22032400410021040240024002400240024002400240024020022001200220014b1b20016b2205450d002005ad42287e2206422088a70d062006a722074100480d06200710002208450d07200220014b0d010c020b4108210841002105200220014d0d010b200341c0006a41186a2109200341c0006a41106a210a200821042001210b03402003200b360200410e10002207450d042003420e37024420032007360240200341c0006a41d79bc100410e1025200341206a41086a220d200341c0006a41086a220728020036020020032003290340370320200341206a2003410410252003280224210c0240024002402003280220220e200d280200220f4188f0c100410041001004417f470d004200210620094200370300200a42003703002007420037030020034200370340200b41016a210b200c0d010c020b20094200370300200a42003703002007420037030020034200370340200e200f200341c0006a4120410010042210417f460d042010411f4d0d04200341206a41186a22102009290300370300200341206a41106a2211200a290300370300200d200729030037030020032003290340370320200920102903002206370300200a201129030022123703002007200d2903002213370300200341086a22142013370300200341106a22152012370300200341186a221620063703002003200329032022063703002003200637034020034200370340200e200f200341c0006a41084120100441016a41084d0d052003290340210620092016290300370300200a20152903003703002007201429030037030020032003290300370340201020092903003703002011200a290300370300200d20072903003703002003200329034037032020092010290300370300200a20112903003703002007200d29030037030020032003290320370340200b41016a210b200c450d010b200e10010b20042003290340370300200441186a2009290300370300200441106a200a290300370300200441086a2007290300370300200441206a2006370300200441286a21042002200b470d000b200220016b21040b200020043602082000200536020420002008360200200341e0006a24000f0b200341c0006a41186a200341206a41186a290000370300200341c0006a41106a200341206a41106a290000370300200341c0006a41086a200341206a41086a290000370300200320032900203703400b41eac4c10041331042000b410e41011019000b1018000b200741081019000b7201017f230041306b220224002002200136020c20022000360208200241246a41013602002002411c6a41013602002002410136022c200241e0c3c10036021820024101360214200241f89fc2003602102002200241086a3602282002200241286a360220200241106a4180a0c2001071000bed0104017e047f017e027f20012902002102410021030240024002400240024002400240200128020c2204200128020822016b2205450d0020054102752206ad4202862207422088a70d022007a722084100480d02200810002209450d0320012004470d010c040b410421094100210620012004460d030b2005417c6a410276210520092103034020032001280200360200200341046a21032004200141046a2201470d000b200541016a210320024280808080105a0d030c040b1018000b200841041019000b2002428080808010540d010b2002a710010b2000200336020820002006360204200020093602000bfc0102057f047e200220016b220341286e210441082105410021064100210702400240024020034128490d002004ad42287e2208422088a70d012008a722034100480d01200310002205450d02200421070b024020012002460d0041002106200521030340200141086a2903002108200141106a2903002109200141186a290300210a2001290300210b200341206a200141206a290300370300200341186a200a370300200341106a2009370300200341086a20083703002003200b370300200341286a2103200641016a21062002200141286a2201470d000b0b2000200636020820002007360204200020053602000f0b1018000b200341081019000bb20101057f200220016b2203410c6e21044104210541002106410021070240024002402003410c490d00200441037422034100480d01200310002205450d02200421070b024020012002460d004100210620052103034020012802002104200341046a200141086a28020036020020032004360200200341086a2103200641016a21062001410c6a22012002470d000b0b2000200636020820002007360204200020053602000f0b1018000b200341041019000bee0605037f017e0b7f027e027f230041e0006b2203240041002104024002400240024002400240024020022001200220014b1b20016b2205450d002005ad4205862206422088a70d052006a722074100480d05200710002208450d06200220014b0d010c020b4101210841002105200220014d0d010b200341206a41186a2109200341206a41106a210a200821042001210b03402003200b360200410610002207450d032003420637024420032007360240200341c0006a41bab6c10041061025200341206a41086a2207200341c0006a41086a220d28020036020020032003290340370320200341206a2003410410252003280224210c0240024002402003280220220e2007280200220f4188f0c100410041001004417f470d0020094200370300200a42003703002007420037030020034200370320200b41016a210b200c0d010c020b200341c0006a41186a22104200370300200341c0006a41106a22114200370300200d420037030020034200370340200e200f200341c0006a412041001004220f417f460d04200f411f4d0d0420092010290300370300200a20112903003703002007200d290300370300200320032903403703202010200929030022063703002011200a2903002212370300200d20072903002213370300200341086a220f2013370300200341106a22142012370300200341186a22152006370300200320032903202206370300200320063703402010201529030037030020112014290300370300200d200f29030037030020032003290300370340201520102903002206370300201420112903002212370300200f200d290300221337030020072013370300200a20123703002009200637030020032003290340220637030020032006370320200b41016a210b200c450d010b200e10010b20042003290320370000200441186a2009290300370000200441106a200a290300370000200441086a2007290300370000200441206a21042002200b470d000b200220016b21040b200020043602082000200536020420002008360200200341e0006a24000f0b200341c0006a41186a200341206a41186a290000370300200341c0006a41106a200341206a41106a290000370300200341c0006a41086a200341206a41086a2900003703002003200329002037034041eac4c10041331042000b410641011019000b1018000b200741011019000bf10903027f047e037f230041d0006b2102024002400240024002400240024002400240024020012d002022034101460d0020034102470d0120012802142203200141186a280200460d02200141146a200341206a360200200241286a41186a200341186a2900002204370300200241286a41106a200341106a2900002205370300200241286a41086a200341086a2900002206370300200020032900002207370308200041106a2006370300200041186a2005370300200041206a2004370300200041286a2001411c6a28020029030037030020022007370328200042013703000f0b20012802102208450d02200141106a4100360200024020012802082203200128020c2209460d002008417f73210a0340200141086a200341286a2208360200200241286a41206a200341206a290300370300200241286a41186a200341186a290300370300200241286a41106a200341106a290300370300200241286a41086a200341086a29030037030020022003290300370328200a41016a220a450d072008210320092008470d000b0b200042003703000f0b20012802102208450d02200141106a410036020020012802082203200128020c2209460d032008417f73210a0340200141086a200341286a2208360200200241286a41206a200341206a290300370300200241286a41186a200341186a290300370300200241286a41106a200341106a290300370300200241286a41086a200341086a29030037030020022003290300370328200a41016a220a450d062008210320092008470d000c040b0b200042003703000f0b20012802082202200128020c460d05200141086a200241286a360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a29030037030020002002290300370308200042013703000f0b20012802082203200128020c460d00200141086a200341286a360200200241206a200341206a290300370300200241186a200341186a290300370300200241106a200341106a290300370300200241086a200341086a290300370300200220032903003703000c030b200141206a41023a0000024020012802142203200141186a280200460d00200141146a200341206a360200200241286a41186a200341186a2900002204370300200241286a41106a200341106a2900002205370300200241286a41086a200341086a2900002206370300200020032900002207370308200041106a2006370300200041186a2005370300200041206a2004370300200041286a2001411c6a28020029030037030020022007370328200042013703000f0b200042003703000f0b2000200229032837030820004201370300200041286a200241286a41206a290300370300200041206a200241286a41186a290300370300200041186a200241286a41106a290300370300200041106a200241306a2903003703000f0b200241206a200241286a41206a290300370300200241186a200241286a41186a290300370300200241106a200241286a41106a290300370300200241086a200241286a41086a290300370300200220022903283703000b2000200229030037030820004201370300200041106a200241086a290300370300200041186a200241106a290300370300200041206a200241186a290300370300200041286a200241206a2903003703000f0b200042003703000b978501050a7f017e447f037e017f230022032104200341e0096b41607122032400024002400240024002400240024002400240024002400240024002400240024002400240411010002205450d00200541063a0000412010002206450d01200641063a001020064100360204200620032f00a0063b00012006412d3a0000200641036a200341a2066a2d00003a0000024020052d00004109470d00200528020841ffffffff0371450d00200528020410010b20051001200141086a2107200141106a2802002208412c6c21052001280208220941586a210a02400240024002400240024002400240024003402005450d01200541546a2105200a41286a210b200a412c6a220c210a200b2d00004107470d000b200320032f0190053b01a006200c41046a280200200c41086a2802002205470d01200541016a220a2005490d182005410174220b200a200a200b491b2208ad420486220d422088a70d18200da7220b4100480d182005450d05200c2802002109200b1000220a450d0f200a2009200b200541047422052005200b4b1b10f8021a200910010c060b41101000220a450d0c200a4180023b010c200a428280808020370204200a2006360200200a20032f0190053b010e2001410c6a2802002008470d03200841016a22052008490d172008410174220b20052005200b491b220bad422c7e220d422088a70d17200da722054100480d172008450d0120051000220c450d0d200c200920052008412c6c2206200620054b1b10f802210520091001200521090c020b200c280200210a0c050b200510002209450d0b0b2001410c6a200b360200200141086a20093602000b200141106a200841016a220e36020020092008412c6c6a220520032f00b0033b0001200541073a000020054281808080103700082005200a360004200520032902a006370210200541036a200341b2036a2d00003a0000200541186a200341a8066a290200370200200541206a200341a0066a41106a290200370200200541286a200341a0066a41186a2802003602004100210f0c030b200b1000220a450d090b200c200a360200200c41046a2008360200200c41086a28020021050b200a20054104746a22054180023b010c200542828080802037020420052006360200200520032f01a0063b010e200c41086a2205200528020041016a360200200341306a200c10492003280234417f6a210f200141106a280200210e200141086a28020021090b200e412c6c2105200941586a210a02400340410021082005450d01200541546a2105200a41286a210b200a412c6a220c210a200b2d00004103470d000b200c41086a2802002205450d00200541286c210a200c28020041186a2105410021080340200820052d0000456a2108200541286a2105200a41586a220a0d000b0b200e412c6c2105200941586a210a024003404100210b2005450d01200541546a2105200a41286a210c200a412c6a2206210a200c2d00004103470d000b200641086a2802002205450d00200541286c210a200628020041186a21054100210b0340200b20052d0000456a210b200541286a2105200a41586a220a0d000b0b200e412c6c2105200941606a210a0240024003402005450d01200541546a2105200a41206a210c200a412c6a2206210a200c2d00004104470d000b200628020021050c010b410021050b2005200b6a2210ad220d421e88a70d0e200d420286a72205417f4c0d0e02400240024002400240024002402005450d00200510002211450d0920114100200510f7021a20100d010c020b410421112010450d010b201120104102746a211241002113200141106a2114200141086a2115201121160340024020132008490d0020142802002217412c6c220b21052015280200221841586a220c210a02400340410021062005450d01200541546a2105200a41286a2109200a412c6a220e210a20092d00004103470d000b200e41086a2802002205450d00200541286c210a200e28020041186a2105410021060340200620052d0000456a2106200541286a2105200a41586a220a0d000b0b201320066b220620134b0d040340200b450d04200b41546a210b200c41286a2105200c412c6a220a210c20052d0000410b470d000b200a41086a28020020064d0d05200a280200200641186c6a280208210a200341a0066a20062001104a20032802a406210520032802a0064101460d0620162005200a6a3602000b201341016a2113201641046a22162012470d000b0b200141086a2802002118412c2119200141106a2802002217450d110c100b412c10002205450d06200541286a41002800e38140360000200541206a41002900db8140370000200541186a41002900d38140370000200541106a41002900cb8140370000200541086a41002900c38140370000200541002900bb81403700000c0c0b412c10002205450d09200541286a41002800b78140360000200541206a41002900af8140370000200541186a41002900a78140370000200541106a410029009f8140370000200541086a410029009781403700002005410029008f81403700000c0b0b411e10002205450d09200541166a41002900fd8140370000200541106a41002900f78140370000200541086a41002900ef8140370000200541002900e78140370000429e808080e003210d0c0b0b200341a8066a290300210d2011100120050d0b41002111412c211920170d0c0c0d0b411041081019000b412041081019000b200541041019000b412c41011019000b411041041019000b200541041019000b200b41041019000b412c41011019000b411e41011019000b42ac808080c005210d0b201110010b2000200536020420004101360200200041086a200d3702000c040b2018201720196c6a211a200341b0036a41146a210920034190086a211b200341a0066a410172211c20034184086a211d20034180086a211e200341f0076a211f200341e4076a2120200341e0076a2121200341d4076a2122200341d0076a2123200341c4076a2124200341c0076a2125200341b0076a2126200341a0076a212720034190076a212820034180076a2129200341f4066a212a200341f0066a212b200341e4066a212c200341e0066a212d200341d4066a212e200341d0066a212f200341a0066a41206a2130200341a0066a41106a2131200341b0036a41086a210b200341c8066a2132200341c4066a2133200341d8066a2134200341e8066a2135200341f8066a213620034188076a213720034184076a213820034198076a213920034194076a213a200341a8076a213b200341a4076a213c200341b8076a213d200341b4076a213e200341c8076a213f200341d8076a2140200341e8076a2141200341f8076a2142200341f4076a214320034188086a21440340024020182d0000410b470d00201828020c2205450d0020182802042245200541186c6a214603400240204541146a22082802002205450d002045410c6a21124100210603400240024002400240024002400240024002400240200620054f0d00024002400240024002402012280200200641047422146a22052d0000410b470d002003200541046a22053602a0022011450d062010200528020022054d0d04201120054102746a280200220a450d00201d200f360200201e41133a0000201f41d7003a00002020200a3602002021412d3a00002022200f360200202341123a0000202420053602002025410b3a0000202641063a0000202741003a000020284184083b0100202941373a0000202a2002360200202b412d3a0000202c200f360200202d41123a0000202e200f360200202f41133a0000203041d6003a0000200341a0066a41146a2247200a3602002031412d3a0000201c20032f00b0033b0000201c41026a200341b0036a41026a2d00003a0000200341123a00a0062003200f3602a40620082802002215200641016a2217490d072008200636020020122802002105200341b0036a41186a2216201b360200200341b0036a41106a22482012360200200b200520146a221341106a220e360200200320173602b003200341b0036a410c6a224920052017410474224a6a224b3602002009200341a0066a3602002003201520176b224c3602b403200e2105024020132d0000220c41ac01460d00410021050340201320056a210a0240200c41ff01714109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010010b2005450d03200b200a41206a360200200541106a2105200a41106a2d0000220c41ac01470d000b201320056a41106a21050b2005204b470d020c030b410121050c0c0b200a41106a2205204b460d010b0340200b2005220a41106a220536020002400240200a2d0000220c4109460d00200c41ac01470d010c030b200a41086a28020041ffffffff0371450d00200a41046a28020010010b200e2005470d000b0b02400240204c450d00201720452802142205470d01201b2214200341a0066a220a6b41047622050d080c070b20122009104b200b28020022052049280200220e470d090c080b2014200541047422056b210c201228020020056a2105200341a0066a220a201b460d044100214d0c0a0b200341a0066a41146a4101360200200341a0066a410c6a4101360200200341a0066a41086a41e0c3c1003602002003410236029405203120034190056a360200200341013602a406200341908ec2003602a0062003200341a0026a36029005200341b0036a200341a0066a104d20032802b0032205450d0b20032902b403210d2000200536020420004101360200200041086a200d3702002011450d122010450d12201110010c120b41808ec20020062005104e000b41c380c00041cc001042000b41d08ec200104f000b4104214d0c050b410f214d0c040b4106214d0c030b4121214d0c020b411e214d0c010b4135214d0b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240204d0e6a020506030407080f12131517181416191a212425262728292a2b2e2f30313233363738393a3b3e4144474a4d505356595c5f626568696667636460615d5e5a5b5758545551524e4f4b4c4849454642433f403c3d34352c2d01001b1c1d1e1f202322090a0b0c0d0e1110100b200e2205200e470d85010c84010b200a41106a2205200e470d82010c81010b2009200a41106a3602000c6c0b200541106a2105200c41706a210c2009280200220a2016280200470d6a4104214d0cb2010b4100210a4101214d0cb1010b20034190056a200a105020032d00900541ac01460d6a4102214d0cb0010b2005200329039005370300200541086a20034190056a41086a2903003703002008200828020041016a360200200c0d6a4105214d0caf010b201628020022142009280200220a6b4104762205450d6a4106214d0cae010b2048280200220e41046a224b280200221320156b20054f0d6a41e200214d0cad010b201520056a220c2015490db40141e300214d0cac010b20134101742215200c200c2015491b224ead420486220d422088a70db30141e400214d0cab010b200da722154100480db20141e500214d0caa010b2013450da70141e600214d0ca9010b200e280200214f20151000220c450d5c41e700214d0ca8010b200c204f201520134104742213201320154b1b10f8021a204f10010ca6010b200e280200210c0c640b20151000220c450d5941e800214d0ca5010b200e200c360200204b204e3602004108214d0ca4010b200c201720056a22134104746a200c204a6a204c41047410f9021a200320133602b0032013200e280208220c460d624109214d0ca3010b200620056a410474200c41047422056b210c200e28020020056a2105200a2014470d630c620b200541106a2105200c41706a210c2009280200220a2016280200460d57410a214d0ca1010b2009200a41106a3602000c570b4100210a410b214d0c9f010b20034190056a200a105020032d00900541ac01460d60410c214d0c9e010b2005200329039005370300200541086a20034190056a41086a290300370300200e41086a220a200a28020041016a360200200c0d60410f214d0c9d010b20034190056a41086a22054100360200200342083703900520034190056a2009104b20032802900522152005280200220a41047422136a210e200328029405214b20152105200a450d604110214d0c9c010b2048280200221441046a224a280200221620032802b403221720032802b003220a6a22056b2013410475220c4f0d6041da00214d0c9b010b2005200c6a224c2005490da20141db00214d0c9a010b20164101742205204c204c2005491b224ead420486220d422088a70da10141dc00214d0c99010b200da7224c4100480da00141dd00214d0c98010b2016450d930141de00214d0c97010b2014280200214f204c10002205450d4b41df00214d0c96010b2005204f204c201641047422162016204c4b1b10f8021a204f10010c92010b201428020021050c5a0b204c10002205450d4841e000214d0c93010b20142005360200204a204e3602004112214d0c92010b2005200a200c6a220c41047422166a2005200a4104746a201741047410f9021a2003200c3602b00320152105200c2014280208220a460d584113214d0c91010b2014280200220520166a214c2005200a4104746a210c2015210a4114214d0c90010b2013450d584115214d0c8f010b20034190056a41026a2205200a41036a2d00003a00002003200a2f00013b019005200a2d0000221641ac01460d584116214d0c8e010b200a41046a290200210d200a410c6a2802002117200c20163a0000200c410c6a2017360200200c41046a200d37020020032f0190052116200c41036a20052d00003a0000200c41016a20163b0000201441086a2205200528020041016a360200201341706a2113200a41106a2205210a200c41106a220c204c470d554117214d0c8d010b2005200e460d584118214d0c8c010b20052d0000220a4109460d5c4119214d0c8b010b200a41ac01470d5d0c5c0b200541086a28020041ffffffff0371450d5d41d700214d0c89010b200541046a2802001001411a214d0c88010b200541106a2205200e470d52411b214d0c87010b204b450d5b411c214d0c86010b20151001411d214d0c85010b200b28020022052049280200220e460d5b411e214d0c84010b200b2005220a41106a2205360200200a2d0000220c4109460d5b411f214d0c83010b200c41ac01470d5c0c5b0b200a41086a28020041ffffffff0371450d5c41d500214d0c81010b200a41046a28020010014120214d0c80010b200e2005470d554121214d0c7f0b20032802b4032205450d5a4122214d0c7e0b20032802b003220e2048280200221341086a220c280200220a460d5a4123214d0c7d0b20132802002213200a4104746a2013200e4104746a200541047410f9021a4124214d0c7c0b200c2005200a6a3602004125214d0c7b0b20032d00a0064109470d5841d200214d0c7a0b200341a0066a41086a28020041ffffffff0371450d5841d300214d0c790b20032802a40610014126214d0c780b20312d00004109470d5741d000214d0c770b200341a0066a41186a28020041ffffffff0371450d5741d100214d0c760b204728020010014127214d0c750b20302d00004109470d5641ce00214d0c740b203228020041ffffffff0371450d5641cf00214d0c730b203328020010014128214d0c720b202f2d00004109470d5541cc00214d0c710b203428020041ffffffff0371450d5541cd00214d0c700b202e28020010014129214d0c6f0b202d2d00004109470d5441ca00214d0c6e0b203528020041ffffffff0371450d5441cb00214d0c6d0b202c2802001001412a214d0c6c0b202b2d00004109470d5341c800214d0c6b0b203628020041ffffffff0371450d5341c900214d0c6a0b202a2802001001412b214d0c690b20292d00004109470d5241c600214d0c680b203728020041ffffffff0371450d5241c700214d0c670b20382802001001412c214d0c660b20282d00004109470d5141c400214d0c650b203928020041ffffffff0371450d5141c500214d0c640b203a2802001001412d214d0c630b20272d00004109470d5041c200214d0c620b203b28020041ffffffff0371450d5041c300214d0c610b203c2802001001412e214d0c600b20262d00004109470d4f41c000214d0c5f0b203d28020041ffffffff0371450d4f41c100214d0c5e0b203e2802001001412f214d0c5d0b20252d00004109470d4e413e214d0c5c0b203f28020041ffffffff0371450d4e413f214d0c5b0b202428020010014130214d0c5a0b20232d00004109470d4d413c214d0c590b204028020041ffffffff0371450d4d413d214d0c580b202228020010014131214d0c570b20212d00004109470d4c413a214d0c560b204128020041ffffffff0371450d4c413b214d0c550b202028020010014132214d0c540b201f2d00004109470d4b4138214d0c530b204228020041ffffffff0371450d4b4139214d0c520b204328020010014133214d0c510b201e2d00004109470d4a4136214d0c500b204428020041ffffffff0371450d4a4137214d0c4f0b201d28020010014134214d0c4e0b410f21054135214d0c4d0b200520066a220620082802002205490d4d0c4e0b201541081019000b204c41081019000b410e214d0c490b410b214d0c480b4100214d0c470b4101214d0c460b411d214d0c450b4103214d0c440b410f214d0c430b4107214d0c420b4108214d0c410b410f214d0c400b410e214d0c3f0b410a214d0c3e0b411d214d0c3d0b410d214d0c3c0b4117214d0c3b0b4111214d0c3a0b4112214d0c390b4117214d0c380b4114214d0c370b41d900214d0c360b41d800214d0c350b4118214d0c340b411b214d0c330b411b214d0c320b4118214d0c310b411b214d0c300b4118214d0c2f0b41d600214d0c2e0b411b214d0c2d0b411a214d0c2c0b411a214d0c2b0b411d214d0c2a0b411e214d0c290b4121214d0c280b41d400214d0c270b4121214d0c260b4120214d0c250b4120214d0c240b4125214d0c230b4124214d0c220b4126214d0c210b4126214d0c200b4127214d0c1f0b4127214d0c1e0b4128214d0c1d0b4128214d0c1c0b4129214d0c1b0b4129214d0c1a0b412a214d0c190b412a214d0c180b412b214d0c170b412b214d0c160b412c214d0c150b412c214d0c140b412d214d0c130b412d214d0c120b412e214d0c110b412e214d0c100b412f214d0c0f0b412f214d0c0e0b4130214d0c0d0b4130214d0c0c0b4131214d0c0b0b4131214d0c0a0b4132214d0c090b4132214d0c080b4133214d0c070b4133214d0c060b4134214d0c050b4134214d0c040b41e100214d0c030b41e000214d0c020b41e900214d0c010b41e800214d0c000b0b0b204541186a22452046470d000b0b201820196a2218201a470d000b0b200341386a41106a2205200141106a280200360200200341386a41086a222d200141086a290200370300200320012902003703382005280200222520196c2105202d280200222341586a210a0240024003402005450d01200541546a2105200a41286a210b200a20196a220c210a200b2d00004108470d000b200341286a200c104920032802282105200328022c210a0c010b410021050b200a410020051b21082025412c6c210a202341586a210b20054188f0c10020051b2105024002400340200a450d01200a41546a210a200b41286a210c200b412c6a2206210b200c2d0000410a470d000b200341206a200610492003280220210a2003280224210b0c010b4100210a0b2003420037028405200341e8bdc00036028005200a4188f0c100200a1b2214200b4100200a1b411c6c6a212b2005200841146c6a210b200341a0066a410c6a2130200341a0066a41086a211c410021272005210a4100211e410021154100210e4100215041042148410421294104215141042117034002400240024002400240024002400240024002400240024002400240024002400240024002400240201541ff0171220c4102460d000240200c4101470d000340200b200a460d09200a410c6a210c200a41146a2205210a200c2802000d000b410121152005210a20032005417c6a280200220c36025c20110d070c0f0b0340200b2005460d022005410c6a210c200541146a220a2105200c2802000d000b41002115200a21052003200a417c6a280200220c36025c20110d060c0e0b2031210c201e4101470d01200c201f460d010c040b2031210c20274101470d01200c201f460d010c020b03402014202b460d05200341186a201410512003280218220c450d052014411c6a211441012127200c200c200328021c4102746a221f470d030c000b0b03402014202b460d04200341106a201410512003280210220c450d042014411c6a2114200c200c20032802144102746a221f460d000b0b200c450d02200c41046a21314102211541012127200b2105200b210a4101211e2003200c280200220c36025c20110d010c090b200c450d01200c41046a2131410221154101211e2003200c280200220c36025c2011450d080b2010200c4d0d092011200c4102746a2802002206450d0d02402050200e470d00200e41016a2208200e490d10200e4101742209200820082009491b2250ad420286220d422088a70d10200da722084100480d1002400240200e450d00200810002248450d04204820292008200e4102742209200920084b1b10f8021a202910010c010b200810002248450d030b2048212920482151204821170b2017200e4102746a200c360200200341a0066a200328025c2213200341386a1052201c280200212820032802a406211220032802a00622264101460d082012280208220c417f4c0d0e2012280200210920122d000c211602400240200c450d00200c100022080d010c080b410121080b20082009200c10f80221082012410d6a2d000021092003200636029c012003200328025c360298012003410036029001200320093a008d01200320163a008c012003200c360288012003200c36028401200320083602800102400240200328028005220c41e8bdc000460d00200328028405214c0c010b4194031000220c450d064100214c200c41003b0106200c4100360200200c41086a200341a0066a418c0310f8021a20034100360284052003200c360280050b200e41016a210e024002400340200c41086a2109200c2f010622214102742108417f210602400240024003402008450d01200641016a21064100417f41012009280200221620134b1b20162013461b2216450d052008417c6a2108200941046a210920164101460d000b204c0d010c020b20212106204c450d010b204c417f6a214c200c20064102746a4194036a280200210c0c010b0b20034180056a41086a2208200828020041016a360200200329039801210d200329039001215220032903880121532003290380012154200c2f01062208410b4f0d01200c41086a2209200641016a22164102746a200920064102746a2209200820066b41027410f9021a20092013360200200c41346a220820164105746a200820064105746a2208200c41066a220c2f010020066b41057410f9021a200841186a200d370200200820523702102008205337020820082054370200200c200c2f010041016a3b01000c0d0b200c20064105746a220c41cc006a220629000021522006200329039801370000200c41c4006a2206290000210d2006200329039001370000200c413c6a220629000021532006200329038801370000200c41346a220c2900002154200c20032903800137000020032054370360200320523703782003200d370370200320533703680240200da74102460d002003280264450d00200328026010010b2026450d0e0c0d0b4194031000221b450d04201b41003b0106201b4100360200201b41086a200341a0066a418c0310f8022109200341a0066a41186a2221200c418c026a290200370300200341a0066a41106a222f200c4184026a290200370300201c200c41fc016a2902003703002003200c2902f4013703a006200c280220212e2009200c41246a200c41066a22162f010041796a220841027410f8022109201b41346a200c4194026a200841057410f802214c201641063b0100201b20083b0106200341b0036a41186a22472021290300370300200341b0036a41106a224a202f290300370300200341b0036a41086a2232201c290300370300200320032903a0063703b00302400240200641064b0d00200c41086a2208200641016a22094102746a200820064102746a2216200c41066a22082f010020066b41027410f9021a20162013360200200c41346a221320094105746a201320064105746a220920082f010020066b41057410f9021a200941186a200d3702002009205237021020092053370208200920543702000c010b20092006417a6a22494102746a2009200641796a22164102746a2206200841ffff037120166b41027410f9021a20062013360200204c20494105746a204c20164105746a2206201b41066a22082f010020166b41057410f9021a200641186a200d3702002006205237021020062053370208200620543702000b200820082f010041016a3b010020034190056a41186a221d204729030037030020034190056a41106a2220204a29030037030020034190056a41086a22222032290300370300200320032903b00337039005200341a0026a41186a2224201d290300370300200341a0026a41106a222a2020290300370300200341a0026a41086a222c202229030037030020032003290390053703a00202400240200c2802002216450d00200c2f010421490340201d20242903003703002020202a2903003703002022202c290300370300200320032903a00237039005204941ffff0371211320162f0106220c410a4d0d0241c40310002209450d06200941003b010620094100360200200941086a200341a0066a41bc0310f80221062016280220213420212016418c026a290200370300202f20164184026a290200370300201c201641fc016a290200370300200320162902f4013703a0062006201641246a201641066a224b2f0100220841796a220c41027410f8022135200941346a20164194026a200c41057410f802213620094194036a201641b0036a2008417a6a224c41027410f8022145204b41063b01002009200c3b01060240204c450d004100210c20452106034020062802002208200c3b010420082009360200200641046a2106204c200c41016a220c470d000b0b20472021290300370300204a202f2903003703002032201c290300370300200320032903a0063703b00320212047290300370300202f204a290300370300201c2032290300370300200320032903b0033703a00602400240204941ffff0371220641064b0d00201641086a220c201341016a224c41027422086a200c201341027422496a220c204b2f0100224520136b223541027410f9021a200c202e360200201641346a220c204c4105746a200c20134105746a220c203541057410f9021a200c41186a201d290300370200200c41106a2020290300370200200c41086a2022290300370200200c200329039005370200204b204541016a220c3b010020164194036a224b20496a41086a204b20086a224b200c41ffff03712208204c6b41027410f9021a204b201b360200200620084f0d01201620496a4198036a210c0340200c2802002206201341016a22133b010420062016360200200c41046a210c20082013470d000c020b0b20352013417a6a220841027422496a2035201341796a220c4102746a2206200941066a224c2f0100200c6b41027410f9021a2006202e360200203620084105746a2036200c4105746a2206204c2f0100200c6b41057410f9021a200641186a201d290300370200200641106a2020290300370200200641086a20222903003702002006200329039005370200204c204c2f010041016a22063b010020452013410274224b6a416c6a204520496a224c200641ffff0371221320086b41027410f9021a204c201b360200200820134b0d002009204b6a41fc026a2106034020062802002208200c41016a220c3b010420082009360200200641046a21062013200c470d000b0b20242021290300370300202a202f290300370300202c201c290300370300200320032903a0063703a00202402016280200220c450d0020162f01042149200c21162034212e2009211b0c010b0b2009211b2034212e0b41c4031000220c450d03200c41003b0106200c4100360200200c41086a200341a0066a41bc0310f8022109200c200328028005220636029403200320032802840541016a36028405200641003b01042003200c360280052006200c360200200c200c2f010622084105746a220641cc006a2024290300370200200641c4006a202a2903003702002006413c6a202c290300370200200641346a20032903a002370200200920084102746a202e360200200c4194036a200841016a22064102746a201b360200200c20063b0106201b20063b0104201b200c3602002003410236027020260d0d0c0e0b201641086a2206201341016a220841027422096a20062013410274224c6a2206200c20136b222141027410f9021a2006202e360200201641346a220620084105746a200620134105746a2206202141057410f9021a200641186a201d290300370200200641106a2020290300370200200641086a20222903003702002006200329039005370200201641066a200c41016a220c3b010020164194036a2206204c6a41086a200620096a2206200c41ffff0371220920086b41027410f9021a2006201b360200201320094f0d0b20162008417f6a220c4102746a4198036a2106034020062802002208200c41016a220c3b010420082016360200200641046a21062009200c470d000c0c0b0b200341d0006a41086a20034180056a41086a28020036020020032003290380053703502025412c6c2105202341586a210a024003404100210b2005450d01200541546a2105200a41286a210c200a412c6a2206210a200c2d00004103470d000b200641086a2802002205450d00200541286c210a200628020041186a21054100210b0340200b20052d0000456a210b200541286a2105200a41586a220a0d000b0b2025412c6c2105202341606a210a0240024003402005450d01200541546a2105200a41206a210c200a412c6a2206210a200c2d00004104470d000b200628020021050c010b410021050b200341a0066a41106a2231200341386a41106a280200360200200341a0066a41086a2233200341386a41086a290300370300200320032903383703a00620034180016a200341a0066a1053024002400240024002400240024002400240200e450d002017200e4102746a21372005200b6a2114200341e9046a211c200341b0036a4194016a2115200341ec046a214c20034190086a211320034184086a212c20034180086a211e200341f0076a211f200341a0066a41c4016a212e200341a0066a41c0016a2121200341a0066a41b4016a2147200341a0066a41b0016a2123200341a0066a41a4016a214a200341a0066a41a0016a2125200341a0066a4190016a2126200341a0076a212720034190076a212820034180076a2129200341f4066a2132200341f0066a212b200341e4066a2134200341e0066a212d200341d0066a212f200341a0066a41206a2130200341a0066a41146a2135200341b7036a2139200341b0036a41b8016a2149200341dc046a214b200341b0036a41a8016a213b200341b0036a41c8016a213d20034190056a410c6a213f200341cc026a2140200341a0026a41286a2141200341a0026a41246a2142200341bc026a2144200341b8066a2138200341d8066a213a200341e8066a213c200341f8066a213e20034188076a214320034184076a211920034198076a214e20034194076a211a200341a8076a214f200341a4076a2107200341b8076a2146200341f8076a2118200341f4076a215520034188086a210103402017220541046a21172005280200210c200341d0006a210520032802542109024002400240024002400240024003402005280200220641086a210b20062f0106220e410274210a417f21050240024002400340200a450d01200541016a21054100417f4101200b2802002208200c4b1b2008200c461b2208450d03200a417c6a210a200b41046a210b20084101460d000b20090d010c040b200e21052009450d030b2009417f6a2109200620054102746a4194036a21050c010b0b200641346a20054105746a2216450d002016280218210a201628021c2105202c200f360200201e41133a0000201f41d7003a0000202e20053602002021412d3a00002047200f360200202341123a0000204a200a3602002025410b3a0000202641063a0000202741003a000020284184083b0100202941373a000020322002360200202b412d3a00002034200f360200202d41123a0000200341a0066a41346a2236200f360200202f41133a0000203041d6003a0000203520053602002031412d3a00002003200f3602a406200341123a00a0062016280208220641106a220aad220d421c88a70d1e200d420486a72205417f4c0d1e201641086a2148024002402005450d0020051000220e450d0320482802002206450d010c040b4108210e20060d030b4100210b200a41006b410f490d030c040b41b88ac0004180011042000b200541081019000b4100210c41002105034002402005200a470d00200a41016a220b200a490d1e200a4101742208200b200b2008491b2208ad420486220d422088a70d1e200da7220b4100480d1e02400240200a450d00200b10002209450d0a2009200e200b200a410474220a200a200b4b1b10f802210a200e1001200a210e0c010b200b1000220e450d090b2008210a0b200e200c6a220b410f3a0000200b41046a2005360200200b41036a20034190056a41026a2d00003a0000200b41016a20032f0190053b0000200c41106a210c200541016a220b21052006200b470d000b200a200b6b410f4f0d010b200b410f6a2205200b490d1b200a410174220c20052005200c491b2212ad420486220d422088a70d1b200da722054100480d1b200a450d0120051000220c450d0b200c200e2005200a410474220a200a20054b1b10f8022105200e10012005210e0c020b200a21120c010b20051000220e450d090b200e200b4104746a2105200341a0066a210a0340200b21080240024002400240200a2d00002206417e6a2209412e4b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020090e2f291c202d2d121d162d1b082d2d0b0a1a2417091319211f0f0e2526031807060d2214230211041e050100152827100c290b200a2d0001210c412b21060c2c0b200a41046a280200210b200a350208210d412a21060c2a0b200a41046a280200210b200a350208210d412521060c290b200a41046a280200210b200a350208210d411d21060c280b200a41046a280200210b200a350208210d412721060c270b200a41046a280200210b200a350208210d412921060c260b200a41046a280200210b200a350208210d412021060c250b200a41046a280200210b200a350208210d411f21060c240b200a41046a280200210b200a2d0001210c410c21060c240b200a41046a280200210b200a350208210d411421060c220b200a41046a280200210b411021060c210b200a41046a280200210b410f21060c200b200a290308210d413021060c1e0b200a41046a280200210b200a350208210d412121060c1e0b200a41046a280200210b200a350208210d411a21060c1d0b200a41046a280200210b200a350208210d411921060c1c0b200a41046a280200210b412f21060c1b0b200a41046a280200210b200a350208210d412621060c1a0b200a41046a280200210b410721060c190b200a41046a280200210b200a350208210d411521060c180b200a41046a280200210b200a350208210d412321060c170b200a2d0001210c412c21060c170b200a2802082206ad220d421e88a70d2f200d420286a7220c417f4c0d2f4104210b0240200c450d00200c1000220b450d1c0b02402006450d00200a41046a280200210c20064102742109200b210603402006200c280200360200200641046a2106200c41046a210c2009417c6a22090d000b0b200a410c6a350200422086200d84210d410921060c150b200a41046a280200210b411321060c140b200a41046a280200210b200a350208210d411e21060c130b200a41046a280200210b200a350208210d411621060c120b200a41046a280200210b411121060c110b200a41046a280200210b410b21060c100b200a2d0001210c410321060c100b200a41046a280200210b410821060c0e0b200a41046a280200210b200a350208210d412821060c0d0b200a41046a280200210b200a350208210d411821060c0c0b200a2d0001210c410421060c0c0b200a41046a280200210b200a350208210d411721060c0a0b200a41046a280200210b200a350208210d412221060c090b200a41046a280200210b200a350208210d412421060c080b200a41046a280200210b411221060c070b200a41046a280200210b200a350208210d411b21060c060b200a41046a280200210b200a350208210d411c21060c050b200a290308210d412e21060c030b200a41046a280200210b412d21060c030b200a2d0001210c410221060c030b0b0b0b2005200c3a0001200520063a0000200541086a200d370300200541046a200b360200200841016a210b200541106a2105200a41106a220a2013470d000b0240024002402012200b470d00201241016a22052012490d1b2012410174220a20052005200a491b220cad420486220d422088a70d1b200da722054100480d1b2012450d0120051000220a450d0c200a200e20052012410474220b200b20054b1b10f8022105200e10012005210e0c020b2012210c200b21120c010b20051000220e450d0a0b200e20124104746a220541063a0000200541086a2039290000370000200520032900b00337000120034190056a20034180016a418c0110f8021a411010002205450d05200541063a000020034180056a41086a220a200341a0026a41086a2206280200360200200341fc046a41026a220b200341dc006a41026a2d00003a0000200320032902a00237038005200320032f005c3b01fc04200341b0036a20034190056a418c0110f8021a204941003a0000200341b0036a41b0016a2209428180808010370300204b2005360200203b4100360200200341b0036a41a0016a22124204370300203d41e0083b0100200341b0036a41c4016a221b4100360200204c4201370200200341b0036a418c016a224542003702002015200329038005370200201541086a200a280200360200201c20032f01fc043b0000201c41026a200b2d00003a000020482802002205417f4c0d172016280200210a024002402005450d0020051000220b0d010c090b4101210b0b203f200b200a200510f802220a20056a36020020034190056a41086a200a36020020032005360294052003200a36029005204c20034190056a105420034190056a200341b0036a418c0110f8021a200341b0036a41c0016a2802002148204c280200211d20492802002120200341b0036a41b4016a280200210a20092802002109204b280200210b200341b0036a41a4016a28020021222012280200212420152802002112200341b0036a4190016a280200212a20452802002105201b290200210d201631000d2152200341a0026a20034190056a418c0110f8021a200341b0036a200341a0026a418c0110f8021a02402005450d002012450d00202a10010b20034190056a200341b0036a418c0110f8021a411010002205450d06200541063a000020051001200341a0026a20034190056a418c0110f8021a200341b0036a200341a0026a418c0110f8021a02402022450d00202410010b200d42ffffffffff9f4083210d205242288621520240200a450d00200a410474210a200b21050340024020052d00004109470d00200541086a28020041ffffffff0371450d00200541046a28020010010b200541106a2105200a41706a220a0d000b0b200841026a2105200d205284210d02402009450d00200b10010b20034190056a200341b0036a418c0110f8021a200341b0036a20034190056a418c0110f8021a20402020360200204120053602002042200c360200200341a0026a41206a200e36020020444100360200200341a0026a41146a4204370200200341a0026a410c6a200d370200200620483602002003201d3602a402200341013602a002200341b0036a200341a0026a105520034180016a200341b0036a418c0110f8021a2016410136021020162014360214024020032d00a0064109470d00203328020041ffffffff0371450d0020032802a40610010b024020312d00004109470d00203828020041ffffffff0371450d00203528020010010b024020302d00004109470d00200341a0066a41286a28020041ffffffff0371450d00200341a0066a41246a28020010010b0240202f2d00004109470d00203a28020041ffffffff0371450d00203628020010010b0240202d2d00004109470d00203c28020041ffffffff0371450d00203428020010010b0240202b2d00004109470d00203e28020041ffffffff0371450d00203228020010010b024020292d00004109470d00204328020041ffffffff0371450d00201928020010010b024020282d00004109470d00204e28020041ffffffff0371450d00201a28020010010b024020272d00004109470d00204f28020041ffffffff0371450d00200728020010010b024020262d00004109470d00204628020041ffffffff0371450d00200341a0066a4194016a28020010010b024020252d00004109470d00200341a0066a41a8016a28020041ffffffff0371450d00204a28020010010b024020232d00004109470d00200341a0066a41b8016a28020041ffffffff0371450d00204728020010010b024020212d00004109470d00200341a0066a41c8016a28020041ffffffff0371450d00202e28020010010b0240201f2d00004109470d00201828020041ffffffff0371450d00205528020010010b0240201e2d00004109470d00200128020041ffffffff0371450d00202c28020010010b201441016a211420172037470d000b0b02402050450d00205110010b200341a0066a20034180016a418c0110f8021a200341b0036a200341a0066a105602400240200341b0036a41106a2802002205450d0020032802b80322142005412c6c6a211503400240024020142d00002205410a460d0020054108470d01201428020c2205450d012014280204220a200541146c6a211303400240200a28020c0d00200a2802102106200341d0006a21052003280254210e03402005280200220841086a210c20082f01062216410274210b417f21050240024002400340200b450d01200541016a21054100417f4101200c280200220920064b1b20092006461b2209450d03200b417c6a210b200c41046a210c20094101460d000b200e0d010c040b20162105200e450d030b200e417f6a210e200820054102746a4194036a21050c010b0b200841346a20054105746a2205450d002005280210450d09200a41106a20052802143602000b200a41146a220a2013470d000c020b0b201428020c2205450d002014280204220f2005411c6c6a211703400240200f2802182205450d00200f280210220e20054102746a21120340200e221341046a210e2013280200210c200341d0006a210520032802542109024003402005280200220641086a210b20062f01062216410274210a417f21050240024002400340200a450d01200541016a21054100417f4101200b2802002208200c4b1b2008200c461b2208450d03200a417c6a210a200b41046a210b20084101460d000b20090d010c040b201621052009450d030b2009417f6a2109200620054102746a4194036a21050c010b0b200641346a20054105746a2205450d002005280210450d07201320052802143602000b200e2012470d000b0b200f411c6a220f2017470d000b0b2014412c6a22142015470d000b0b200341bc036a290200210d20032802b003210520032902b40321522003280250200328025420032802581057200041106a200d370200200041086a205237020020002005360204200041003602002011450d192010450d1920111001200424000f0b41b88bc00041351042000b200b41081019000b200c41041019000b41b88bc00041351042000b411041081019000b411041081019000b200541011019000b200541081019000b200541081019000b200841041019000b41c40341041019000b41c40341041019000b41940341041019000b41940341041019000b200c41011019000b41c380c00041cc001042000b203028020021050c010b200341b4066a4101360200200341ac066a4101360200200341a8066a41e0c3c1003602002003410336029405200341b0066a20034190056a360200200341023602a406200341a08fc2003602a0062003200341dc006a36029005200341b0036a200341a0066a104d20032902b403220d422088a7210520032802b0032112200da721280b20032802800520032802840520034188056a280200105702402050450d00204810010b202d10590240200341c4006a280200450d00202310010b2000201236020420004101360200200041086a2005ad4220862028ad843702002011450d062010450d0620111001200424000f0b200341023602702026450d010b2028450d00201210010c000b0b102c000b1018000b200710592001410c6a280200450d00200728020010010b200424000b160020002001280208360204200020012802003602000be539030f7f017e017f230041c0006b220324002002280208220441586a2105200241106a2802002206412c6c210702400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024003402007450d01200741546a2107200541286a21082005412c6a2209210520082d00004104470d000b2006412c6c2107200441586a210503402007450d02200741546a2107200541286a21082005412c6a220a210520082d0000410b470d000b2006412c6c2107200441586a210503402007450d03200741546a2107200541286a21082005412c6a2204210520082d00004102470d000b200341106a20091049200328021420014d0d03200328021020014102746a2207450d03200341086a20041049200328020c200728020022074d0d04200328020820074104746a2207450d04200a41086a28020020014d0d05200a2802002109200341186a41086a420037030020034280808080c00037031820072d000d2108200341306a41026a220a2003412d6a41026a2d00003a0000200320032f002d3b0130411010002207450d3f200341206a220b4101360200200341186a410c6a220528020021062003200736021c200720064104746a220741003a000c2007410036020820072008410447220c3602042007200c360200200720032f01303b000d2007410f6a200a2d00003a00002005200528020041016a3602004100210802402009200141186c6a22072802142205450d002007410c6a2106200741146a210a200341306a410472210d4100210841002107034002402003280218220920084d0d00200341306a200341186a4100105e20032802304101460d0920082003280218220920032802342d000c1b2108200a28020021050b200720054f0d3e02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402006280200220120074104746a2d0000220541ab014b0d00024020050eac01141e0707071e13120c181915110e0d0b17160f1004040404040404040404040404040505050505050505050a1a06060606080000000000000000000008000000000000000000000000000000000000000000000303030101010101010101010101010101010303030101010101010101010101010101010303030303030301010101010101030303030303030101010101010102020202020202020202020202020202020202020202020202140b200341306a200341186a4102105f20032802300d2a2003280218220541016a22092005490d2b20032009360218200741016a2207200a2802002205490d1f0c200b200341306a200341186a4102105f20032802300d272003280218220541016a22092005490d2820032009360218200741016a2207200a2802002205490d1e0c1f0b200341306a200341186a4101105f20032802300d2a2003280218220541016a22092005490d2b20032009360218200741016a2207200a2802002205490d1d0c1e0b200341306a200341186a4101105f20032802300d2b2003280218220541016a22092005490d2c20032009360218200741016a2207200a2802002205490d1c0c1d0b200341306a200341186a4101105f20032802300d2c2003280218220541016a22092005490d2d20032009360218200741016a2207200a2802002205490d1b0c1c0b200341306a200341186a4102105f2003280230450d180c2f0b200941016a22052009490d2f20032005360218200741016a2207200a2802002205490d190c1a0b200120074104746a2d0001210e200341306a41026a2003412d6a41026a2d00003a0000200320032f002d3b0130200341246a2802002201200341206a280200470d01200141016a220f2001490d5b20014101742210200f200f2010491b2211ad4204862212422088a70d5b2012a722104100480d5b2001450d13200328021c211320101000220f450d5c200f2013201020014104742201200120104b1b10f8021a201310010c140b200341306a200341186a4101105f20032802300d2e2003280218220541016a22092005490d3020032009360218200741016a2207200a2802002205490d170c180b200328021c210f0c130b200941016a22052009490d3d20032005360218200741016a2207200a2802002205490d150c160b200941016a22052009490d3720032005360218200741016a2207200a2802002205490d140c150b200341306a200341186a200120074104746a41046a280200105e20032802304101460d2f200341306a200341186a20032802342802042205105f20032802300d41200341306a200341186a4101105f20032802300d4a2003280218220920056a22052009490d4b20032005360218200741016a2207200a2802002205490d130c140b200341306a200341186a4102105f20032802300d34200341306a200341186a4101105f20032802300d3e2003280218220541016a22092005490d4820032009360218200741016a2207200a2802002205490d120c130b200341306a200341186a4101105f2003280230450d0f0c300b200941016a22052009490d3720032005360218200741016a2207200a2802002205490d100c110b200341306a200341186a4101105f2003280230450d0d0c2f0b2003200410492003280204200120074104746a41046a28020022054d0d2b2003280200220920054104746a2201450d2b200341306a200341186a200920054104746a280208105f20032802300d3b2003280218220520012d000d4104476a22092005490d4320032009360218200741016a2207200a2802002205490d0e0c0f0b200341306a200341186a200120074104746a41046a280200105e20032802304101460d32200341306a200341186a2003280234280204105f20032802300d38200341246a2802002205417f6a220920054f0d41200920054b0d41200328021c20094104746a41013a000c200741016a2207200a2802002205490d0d0c0e0b200341246a22052802002209450d2420052009417f6a2209360200200328021c20094104746a22052d000c4102460d2420052802002109200320052802082205360218200520096a22092005490d3f20032009360218200741016a2207200a2802002205490d0c0c0d0b200341246a2802002205417f6a220920054f0d31200920054b0d31200328021c20094104746a41013a000c200741016a2207200a2802002205490d0b0c0c0b200341306a200120074104746a41046a2802002002105220032802304101460d25200341306a200341186a20032802342205280208105f20032802300d392003280218220920052d000d4104476a22052009490d3c20032005360218200741016a2207200a2802002205490d0a0c0b0b200341306a200341186a4101105f20032802300d2d2003280218220541016a22092005490d3920032009360218200741016a2207200a2802002205490d090c0a0b200341306a200341186a4101105f2003280230450d060c290b200341306a200341186a200120074104746a2209410c6a280200105e20032802304101460d2120032802342802042101200941086a2802004102742105200941046a280200210903402005450d07200341306a200341186a2009280200105e20032802304101460d1b2005417c6a2105200941046a210920032802342802042001460d000c1c0b0b200341306a200341186a200c105f20032802300d24200341246a2802002205417f6a220920054f0d30200920054b0d30200328021c20094104746a41013a000c200741016a2207200a2802002205490d060c070b200341306a200341186a4101105f20032802300d2e2003280218220541016a22092005490d3620032009360218200741016a2207200a2802002205490d050c060b20101000220f450d480b200341206a20113602002003200f36021c200341246a28020021010b200f20014104746a220141003a000c2001200936020820012005410347200e41044722057136020420012005360200200120032f01303b000d2001410f6a200341326a2d00003a0000200341246a2205200528020041016a3602000b200741016a2207200a2802002205490d010c020b200341306a200341186a2001105f20032802300d39200341246a2802002205417f6a220920054f0d3a200920054b0d3a200328021c20094104746a41013a000c200741016a2207200a2802002205490d000b0b2000410036020020002008360204200b280200450d5c200328021c1001200341c0006a24000f0b411310002207450d38200741126a41002d00c986403a0000200741106a41002f00c786403b0000200741086a41002900bf8640370000200741002900b78640370000200041086a4293808080b0023702002000200736020420004101360200200341c0006a24000f0b410f10002207450d38200741076a41002900d18640370000200741002900ca8640370000200041086a428f808080f0013702002000200736020420004101360200200341c0006a24000f0b410f10002207450d38200741076a41002900e08640370000200741002900d98640370000200041086a428f808080f0013702002000200736020420004101360200200341c0006a24000f0b412510002207450d392007411d6a41002900858740370000200741186a41002900808740370000200741106a41002900f88640370000200741086a41002900f08640370000200741002900e88640370000200041086a42a5808080d0043702002000200736020420004101360200200341c0006a24000f0b412510002207450d392007411d6a41002900858740370000200741186a41002900808740370000200741106a41002900f88640370000200741086a41002900f08640370000200741002900e88640370000200041086a42a5808080d0043702002000200736020420004101360200200341c0006a24000f0b412710002207450d3a2007411f6a41002900ac8740370000200741186a41002900a58740370000200741106a410029009d8740370000200741086a410029009587403700002007410029008d8740370000200041086a42a7808080f0043702002000200736020420004101360200200341c0006a24000f0b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a280200450d550c540b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d530c540b410e10002207450d3a200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d520c530b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d510c520b410e10002207450d39200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d500c510b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4f0c500b410e10002207450d38200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4e0c4f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4d0c4e0b410e10002207450d37200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4c0c4d0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4b0c4c0b410e10002207450d36200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4a0c4b0b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d490c4a0b412710002207450d352007411f6a41002900f88740370000200741186a41002900f18740370000200741106a41002900e98740370000200741086a41002900e18740370000200741002900d98740370000200041086a42a7808080f0043702002000200736020420004101360200200341206a2802000d480c490b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d470c480b410e10002207450d34200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d460c470b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d450c460b411710002207450d332007410f6a41002900c38740370000200741086a41002900bc8740370000200741002900b48740370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d440c450b410e10002207450d33200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d430c440b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d420c430b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d410c420b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d400c410b410e10002207450d30200741066a41002900868840370000200741002900808840370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d3f0c400b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3e0c3f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3d0c3e0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3c0c3d0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3b0c3c0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3a0c3b0b410e10002207450d2b200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d390c3a0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d380c390b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d370c380b411710002207450d292007410f6a41002900c38740370000200741086a41002900bc8740370000200741002900b48740370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d360c370b410e10002207450d29200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d350c360b410e10002207450d29200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d340c350b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d330c340b411710002207450d282007410f6a41002900c38740370000200741086a41002900bc8740370000200741002900b48740370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d320c330b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d310c320b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d300c310b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2f0c300b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2e0c2f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2d0c2e0b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2c0c2d0b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2b0c2c0b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2a0c2b0b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d290c2a0b411710002207450d232007410f6a41002900c38740370000200741086a41002900bc8740370000200741002900b48740370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d280c290b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d270c280b410e10002207450d23200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d260c270b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d250c260b410e10002207450d22200741066a41002900d18740370000200741002900cb8740370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d240c250b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d230c240b411710002207450d212007410f6a41002900c38740370000200741086a41002900bc8740370000200741002900b48740370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d220c230b411341011019000b410f41011019000b410f41011019000b41808fc20020072005104e000b412541011019000b412541011019000b411041041019000b412741011019000b1018000b201041041019000b410e41011019000b410e41011019000b410e41011019000b410e41011019000b410e41011019000b412741011019000b410e41011019000b411741011019000b410e41011019000b410e41011019000b410e41011019000b411741011019000b410e41011019000b410e41011019000b411741011019000b410e41011019000b410e41011019000b410e41011019000b410e41011019000b411741011019000b410e41011019000b410e41011019000b410e41011019000b411741011019000b200328021c10010b200341c0006a24000ba80302067f017e230041106b2202240002400240024002400240024002400240200041046a2802002203200028020822046b20012802042205200128020022066b41047622074f0d00200420076a22062004490d0420034101742204200620062004491b2204ad4204862208422088a70d042008a722064100480d042003450d0120002802002105200610002207450d0520072005200620034104742203200320064b1b10f8021a200510010c020b2000280200210720062005460d020c050b200610002207450d030b20002007360200200041046a2004360200200041086a280200210420012802002206200141046a280200470d030b410021060c030b1018000b200641081019000b2001200641106a3602000b200220061050024020022d000041ac01460d00200720044104746a2106034020062002290300370300200641086a200241086a2903003703000240024020012802002203200141046a280200460d002001200341106a3602000c010b410021030b200441016a2104200641106a210620022003105020022d000041ac01470d000b0b200041086a2004360200200241106a24000b0b002000280200200110580bfe0201067f230041306b22022400200128020021030240024002400240024002400240200128020422044103742205450d00200341046a2106410021070340200628020020076a2107200641086a2106200541786a22050d000b200141146a280200450d010c020b41002107200141146a2802000d010b200721060c010b2004450d02024002402007410f4b0d002003280204450d010b200720076a220620074f0d010b4101210541002106200241086a21070c010b2006417f4c0d02200241086a210702402006450d002006100022050d01200641011019000b41012105410021060b200241003602102002200636020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a290200370300200220012902003703180240200241146a41e090c200200241186a106d0d0020002007290200370200200041086a200741086a280200360200200241306a24000f0b106e000b41d090c20041004100104e000b102c000b860101017f230041306b220324002003200236020420032001360200200341206a410c6a41033602002003411c6a4102360200200341086a410c6a4102360200200341033602242003418489c2003602102003410236020c200341f890c200360208200320033602282003200341046a3602202003200341206a360218200341086a20001071000b6802017f037e230041306b22012400200029020821022000290210210320002902002104200141146a41003602002001200437031820014188f0c100360210200142013702042001200141186a36020020012003370328200120023703202001200141206a1071000bc80903037f017e017f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001450d0020012d00002202417e6a2203412e4b0d01024020030e2f001f233030152019301e0b30300e0d1d271a0c161c242212112829061b0a091025172605140721080403182b2a130f000b20012d00012104410221020c2f0b200041ac013a00000f0b0c2b0b20012d00012104412b21020c2c0b200141046a280200210620013502082105412a21020c2a0b200141046a280200210620013502082105412521020c290b200141046a280200210620013502082105411d21020c280b200141046a280200210620013502082105412721020c270b200141046a280200210620013502082105412921020c260b200141046a280200210620013502082105412021020c250b200141046a280200210620013502082105411f21020c240b200141046a280200210620012d00012104410c21020c240b200141046a280200210620013502082105411421020c220b200141046a2802002106411021020c210b200141046a2802002106410f21020c200b20012903082105413021020c1e0b200141046a280200210620013502082105412121020c1e0b200141046a280200210620013502082105411a21020c1d0b200141046a280200210620013502082105411921020c1c0b200141046a2802002106412f21020c1b0b200141046a280200210620013502082105412621020c1a0b200141046a2802002106410721020c190b200141046a280200210620013502082105411521020c180b200141046a280200210620013502082105412321020c170b20012d00012104412c21020c170b20012802082204ad2205421e88a70d122005420286a72202417f4c0d124104210602402002450d00200210002206450d140b02402004450d00200141046a28020021022004410274210320062104034020042002280200360200200441046a2104200241046a21022003417c6a22030d000b0b2001410c6a3502004220862005842105410921020c150b200141046a2802002106411321020c140b200141046a280200210620013502082105411e21020c130b200141046a280200210620013502082105411621020c120b200141046a2802002106411121020c110b200141046a2802002106410b21020c100b20012d00012104410321020c100b200141046a2802002106410821020c0e0b200141046a280200210620013502082105412821020c0d0b200141046a280200210620013502082105411821020c0c0b20012d00012104410421020c0c0b200141046a280200210620013502082105411721020c0a0b200141046a280200210620013502082105412221020c090b200141046a280200210620013502082105412421020c080b200141046a2802002106411221020c070b200141046a280200210620013502082105411b21020c060b200141046a280200210620013502082105411c21020c050b20012903082105412e21020c030b200141046a2802002106412d21020c030b102c000b200241041019000b0b0b200020043a0001200020023a0000200041086a2005370300200041046a20063602000b19002000200141186a280200360204200020012802103602000bf507020b7f017e230041e0006b22032400200320013602202002280208220441586a2105200241106a2802002206412c6c21020240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004102470d000b200341186a2008104920032802182107200328021c21020c010b410021070b2002410020071b21092006412c6c2102200441586a210520074188f0c10020071b210a0240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004104470d000b200341106a200810492003280210210b2003280214210c0c010b4100210b0b2006412c6c2102200441586a2105200b4188f0c100200b1b210d02400240024002400240024002400240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d012006412c6c2102200441586a210503402002450d06200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200341086a20081049200328020c220b41286c210520032802082204210703402005450d05200541586a2105200741186a2108200741286a2202210720082d00000d000b2001450d022004200b41286c6a210803402001417f6a2101034020082002460d06200241186a2105200241286a2207210220052d00000d000b2007210220010d000b200741586a21020c030b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a2202450d00200320022802002202360224200920024d0d060c050b200341cc006a4101360200200341c4006a41013602002003410336022c200341e0c3c1003602402003410236023c200341988ec2003602382003200341206a3602282003200341286a360248200341d0006a200341386a104d2003290254210e200328025021020c060b200241586a21020b20032002411c6a2802002202360224200920024b0d020c030b41d983c00041dd001042000b419783c00041c2001042000b200a20024104746a2202450d002000410036020020002002360204200341e0006a24000f0b200341d0006a410c6a4103360200200341cc006a4102360200200341386a410c6a4102360200200341033602542003418489c2003602402003410336023c200341a88ec2003602382003200341206a3602582003200341246a3602502003200341d0006a360248200341286a200341386a104d200329022c210e200328022821020b2000200236020420004101360200200041086a200e370200200341e0006a24000bee2801377f23004190016b2202240020024184016a4200370200200241fc006a4280808080c000370200200241ec006a4200370200200241e4006a4280808080c000370200200241d0006a4200370300200241c0006a4200370300200241386a4280808080c000370300200241286a4200370300200241206a4280808080c000370300200241106a4200370300200242043702742002420437025c20024204370348200242043703302002420437031820024280808080c000370308200242043703002001410c6a280200210320012802082104024002400240200141106a2802002205450d00410021064100210741002108410021094100210a4100210b4100210c4100210d4100210e4100210f41002101024002400340201121102001211220042005417f6a2205412c6c6a2201280024211320012800202114200128001821152001280014211620012800102117200128000c2118200128000821192001280004211a4101211b024002400240024002400240024002400240024020012d0000221c417e6a221d410d4b0d004101211e4101211f4101212041012121410121224101212341012101201a21110240024002400240024002400240024002400240201d0e0e00020304050106130708090f0f16000b0240200f450d0002402024450d0020244104742111200f210103400240200141046a280200450d00200128020010010b200141106a2101201141706a22110d000b0b2025450d00200f10010b4101211e4100211b2018212420192125201a210f0c0a0b0240200a450d0002402026450d00200a20264104746a2122200a211d03400240201d2802082211450d00201d2802002101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41106a21010240201d41046a280200450d00201d28020010010b2001211d20012022470d000b0b2027450d00200a10010b4100211f4101211b2018212620192127201a210a4101211e0c0a0b0240200e450d0002402028450d00202841286c2111200e210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101201141586a22110d000b0b2029450d00200e10010b4100211e4101211b2018212820192129201a210e0c080b0240202a450d00200d450d00200d10010b2012210120102111201a210d2019212a2018212b20050d100c110b0240202c450d00200c450d00200c10010b2012210120102111201a210c2019212c2018212d20050d0f0c100b0240202e450d00200b450d00200b10010b2012210120102111201a210b2019212e2018212f20050d0e0c0f0b02402009450d0002402030450d00203041146c21112009210103400240200141046a280200450d00200128020010010b200141146a21012011416c6a22110d000b0b2031450d00200910010b410021204101211b2018213020192131201a21094101211e4101211f0c060b02402008450d0002402032450d0020082032411c6c6a21222008211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d20012022470d000b0b2033450d00200810010b410021214101211b2018213220192133201a21084101211e4101211f410121200c060b02402007450d0002402034450d002007203441186c6a21222007211d03400240201d41046a280200450d00201d28020010010b0240201d41146a2802002211450d00201d28020c2101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41186a21010240201d41106a280200450d00201d410c6a28020010010b2001211d20012022470d000b0b2035450d00200710010b410021224101211b2018213420192135201a21074101211e4101211f410121204101212141012123201c410d4d0d070c080b02402006450d0002402036450d0020062036411c6c6a21222006211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d20012022470d000b0b2037450d00200610010b410021234101211b2018213620192137201a21064101211e4101211f410121204101212141012122201c410d4d0d060c070b4101211e0b4101211f0b410121200b410121210b41012122410121230b201c410d4b0d010b20122101201021110240024002400240024002400240024002400240201c0e0e0900010209090903040c05060708090b02402019450d00201a10010b2016450d0a201710010c0a0b201b450d092018450d0720184104742111201a210103400240200141046a280200450d00200128020010010b200141106a2101201141706a22110d000c080b0b201e450d082018450d06201841286c2111201a210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101201141586a22110d000c070b0b201f450d072018450d05201a20184104746a211c201a211d03400240201d2802082211450d00201d2802002101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41106a21010240201d41046a280200450d00201d28020010010b2001211d2001201c470d000c060b0b2020450d062018450d04201841146c2111201a210103400240200141046a280200450d00200128020010010b200141146a21012011416c6a22110d000c050b0b2021450d052018450d03201a2018411c6c6a211c201a211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d2001201c470d000c040b0b2022450d042018450d02201a201841186c6a211c201a211d03400240201d41046a280200450d00201d28020010010b0240201d41146a2802002211450d00201d28020c2101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41186a21010240201d41106a280200450d00201d410c6a28020010010b2001211d2001201c470d000c030b0b2023450d032018450d01201a2018411c6c6a211c201a211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d2001201c470d000c020b0b024002400240201a41ff017122014102460d0020014101460d012018450d05201910010c050b2016450d01201820164104746a21192018211c0340201c221a41106a211c0240201a2802042201450d000240201a410c6a2802002211450d002011410c6c2111034002402001280200221d450d00200141046a280200450d00201d10010b2001410c6a2101201141746a22110d000b0b201a41086a280200450d00201a41046a28020010010b201c2019470d000c020b0b2016450d002016410c6c211120182101034002402001280200221d450d00200141046a280200450d00201d10010b2001410c6a2101201141746a22110d000b0b2017450d02201810010c020b2019450d01201a10010c010b02402019450d00201a10010b02402016450d002015450d00201610010b2013450d00201410010b20122101201021110b20050d000b0b4100210520112110200121120b2034410020071b21182035410020071b21222032410020081b21382033410020081b21332030410020091b21232031410020091b212120264100200a1b213520274100200a1b2127202f4100200b1b2120202e4100200b1b211b202d4100200c1b2130202c4100200c1b2132202b4100200d1b2116202a4100200d1b211720284100200e1b213420294100200e1b212620244100200f1b211520254100200f1b21142007410420071b21192008410420081b21282009410420091b211f200a4104200a1b2109200b4104200b1b211e200c4104200c1b2108200d4104200d1b2113200e4104200e1b2107200f4104200f1b210a20060d020c010b41042119410021184100212241002123410021214104211f410021204100211b4104211e41002116410021174104211341002115410021144104210a41002105410021124104210741002126410021344104210841002132410021304104210941002127410021354104212841002133410021380b4104210641002137410021360b2002280200211d0240200241086a2802002201450d0020014104742111201d210103400240200141046a280200450d00200128020010010b200141106a2101201141706a22110d000b0b02402002280204450d00201d10010b2002410c6a280200211d0240200241146a2802002201450d00200141286c2111201d210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101201141586a22110d000b0b0240200241106a280200450d00201d10010b02402002411c6a280200450d00200241186a28020010010b0240200241286a280200450d00200241246a28020010010b0240200241346a280200450d00200241306a28020010010b2002413c6a280200211c0240200241c4006a2802002201450d00201c20014104746a211a201c211d03400240201d2802082211450d00201d2802002101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41106a21010240201d41046a280200450d00201d28020010010b2001211d2001201a470d000b0b0240200241c0006a280200450d00201c10010b200241c8006a280200211d0240200241d0006a2802002201450d00200141146c2111201d210103400240200141046a280200450d00200128020010010b200141146a21012011416c6a22110d000b0b0240200241cc006a280200450d00201d10010b200241dc006a280200211c0240200241e4006a2802002201450d00201c2001411c6c6a211a201c211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d2001201a470d000b0b0240200241e0006a280200450d00201c10010b200241e8006a280200211c0240200241f0006a2802002201450d00201c200141186c6a211a201c211d03400240201d41046a280200450d00201d28020010010b0240201d41146a2802002211450d00201d28020c2101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b201d41186a21010240201d41106a280200450d00201d410c6a28020010010b2001211d2001201a470d000b0b0240200241ec006a280200450d00201c10010b200241f4006a280200211c0240200241fc006a2802002201450d00201c2001411c6c6a211a201c211d03400240201d410c6a2802002211450d00201d2802042101201141047421110340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101201141706a22110d000b0b0240201d41086a280200450d00201d41046a28020010010b201d411c6a21010240201d41146a280200450d00201d28021010010b2001211d2001201a470d000b0b20024180016a21010240200241f8006a280200450d00201c10010b20011059024020024184016a2201280200450d0020024180016a28020010010b20024188016a20053602002001200336020020024180016a2004360200200241fc006a2036360200200241f8006a2037360200200241f4006a2006360200200241f0006a2018360200200241ec006a2022360200200241e8006a2019360200200241e4006a2038360200200241e0006a2033360200200241dc006a2028360200200241d8006a2010360200200241d4006a2012360200200241d0006a2023360200200241cc006a2021360200200241c8006a201f360200200241c4006a2035360200200241c0006a20273602002002413c6a2009360200200241386a2020360200200241346a201b360200200241306a201e3602002002412c6a2030360200200241286a2032360200200241246a2008360200200241206a20163602002002411c6a2017360200200241186a2013360200200241146a2034360200200241106a20263602002002410c6a2007360200200241086a2015360200200220143602042002200a36020020002002418c0110f8021a20024190016a24000bbd0201077f024002400240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b22064f0d00200320066a22072003490d0420024101742203200720072003491b22034100480d042002450d0120002802002108200310002207450d052007200820032002200220034b1b10f8021a200810010c020b200028020021070c020b200310002207450d030b20002007360200200041046a2003360200200041086a28020021030b200720036a2005200610f8021a200141086a22072004360200200041086a2200200028020020066a36020041002100024003402000450d012007200441016a22033602002000417f6a210020042d000021062003210420064104470d000b0b02402001280204450d00200128020010010b0f0b1018000b200341011019000bd00503067f017e017f230041306b22022400200241106a200141246a290200370300200241086a2001411c6a29020037030020022001290214370300200241186a41106a200141106a280200360200200241186a41086a200141086a290200370300200220012902003703182000200241186a105b210302400240024002400240024002402000411c6a280200200041206a2802002204470d00200441016a22052004490d0420044101742206200520052006491b2207ad4202862208422088a70d042008a722064100480d042004450d01200041186a2802002109200610002205450d0520052009200620044102742204200420064b1b10f8021a200910010c020b200041186a28020021050c020b200610002205450d030b2000411c6a2007360200200041186a2005360200200041206a28020021040b200520044102746a2003360200200041206a2204200428020041016a360200200241186a41106a200241106a290300370300200241186a41086a200241086a290300370300200220022903003703180240024002400240200041ec006a280200200041f0006a2802002204470d00200441016a22052004490d0420044101742203200520052003491b2206ad42187e2208422088a70d042008a722034100480d042004450d01200041e8006a2802002107200310002205450d06200520072003200441186c2204200420034b1b10f8021a200710010c020b200041e8006a28020021050c020b200310002205450d040b200041ec006a2006360200200041e8006a2005360200200041f0006a28020021040b2005200441186c6a22042002290318370200200441106a200241186a41106a290300370200200441086a200241186a41086a290300370200200041f0006a22042004280200220441016a360200024020012d002c450d0020004101360254200041d8006a20043602000b200241306a24000f0b1018000b200641041019000b200341041019000b9925032e7f017e017f230041306b2202240020012802042103200128020021044101210502400240024002400240024002400240024002400240024002400240024002400240024020012802082206450d00412c10002207450d02200720022f002d3b0001200741023a00002007200636000c200720033600082007200436000420072002290208370210200741036a2002412d6a41026a2d00003a0000200741186a200241106a290200370200200741206a200241186a290200370200200741286a200241086a41186a28020036020041002108410121090c010b4104210741002109410121080b200141106a280200210a200128020c210b0240024002400240200141146a280200220c450d002009410174220d200941016a220e200e200d491b220e412c6c210f2009450d01200f1000220d450d05200d2007200f2009412c6c22102010200f4b1b10f8021a200710010c020b2009210e2007210d0c020b200f1000220d450d030b200d2009412c6c6a220720022f002d3b0001200741033a00002007200c36000c2007200a3600082007200b36000420072002290208370210200741036a2002412f6a2d00003a0000200741186a200241106a290200370200200741206a200241186a290200370200200741286a200241086a41186a280200360200200941016a210941002105200d21070b2001411c6a28020021112001280218211241002113024002400240024002400240200141206a2802002210450d00200e2009470d0141000d1041000d10200e4101742207200e41016a220f200f2007491b220fad422c7ea722074100480d10200e450d02200710002214450d082014200d2007200e412c6c220e200e20074b1b10f8022107200d10012007210d0c030b200e210f410021150c040b200e210f0c020b20071000220d450d050b200d21070b20072009412c6c6a220e41043a0000200e201036000c200e2011360008200e2012360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e200229020837021041012115200941016a21090b200141286a2802002116200128022421170240024002400240024002402001412c6a2802002214450d00200f2009470d0141000d1041000d10200f4101742207200f41016a220e200e2007491b2210ad422c7ea722074100480d10200f450d0220071000220e450d09200e200d2007200f412c6c220f200f20074b1b10f8022107200d10012007210d0c030b200f21100c040b200f21100c020b20071000220d450d060b200d21070b20072009412c6c6a220e41053a0000200e201436000c200e2016360008200e2017360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e200229020837021041012113200941016a21090b200141346a280200211820012802302119024002400240024002400240200141386a2802002214450d0020102009470d0141000d1041000d1020104101742207201041016a220e200e2007491b220fad422c7ea722074100480d102010450d0220071000220e450d0a200e200d20072010412c6c2210201020074b1b10f8022107200d10012007210d0c030b4100211a2010210f0c040b2010210f0c020b20071000220d450d070b200d21070b20072009412c6c6a220e41063a0000200e201436000c200e2018360008200e2019360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e20022902083702104101211a200941016a21090b200141c0006a280200211b200128023c211c4101211d024002400240024002400240200141c4006a280200221e450d00200f2009470d0141000d1041000d10200f4101742207200f41016a220e200e2007491b2210ad422c7ea722074100480d10200f450d0220071000220e450d0b200e200d2007200f412c6c220f200f20074b1b10f8022107200d10012007210d0c030b200f21104101211f0c040b200f21100c020b20071000220d450d080b200d21070b20072009412c6c6a220e41073a0000200e201e36000c200e201b360008200e201c360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a21094100211f0b200141cc006a280200212020012802482121024002400240024002400240200141d0006a2802002222450d0020102009470d0141000d1041000d1020104101742207201041016a220e200e2007491b2214ad422c7ea722074100480d102010450d0220071000220e450d0c200e200d20072010412c6c220f200f20074b1b10f8022107200d10012007210d0c030b201021144101212320012802544101460d040c0d0b201021140c020b20071000220d450d090b200d21070b20072009412c6c6a220e41083a0000200e202236000c200e2020360008200e2021360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241086a41086a290200370200200e2002290208370210200941016a21094100211d4101212320012802544101470d090b200141d8006a2802002110024002400240024020142009470d0041000d0e41000d0e20144101742207201441016a220e200e2007491b220fad422c7ea722074100480d0e2014450d0120071000220e450d0b200e200d20072014412c6c2214201420074b1b10f8022107200d10012007210d0c020b2014210f0c020b20071000220d450d090b200d21070b20072009412c6c6a220e41093a0000200e2010360204200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41206a280200360200200e41206a200241086a41186a290200370200200e41186a200241086a41106a290200370200200e41106a200241106a290200370200200e2002290208370208200941016a21090c090b412c41041019000b200f41041019000b200741041019000b200741041019000b200741041019000b200741041019000b200741041019000b200741041019000b2014210f0b200141e0006a2802002124200128025c2125024002400240024002400240200141e4006a2802002226450d00200f2009470d0141000d0641000d06200f4101742207200f41016a220e200e2007491b2210ad422c7ea722074100480d06200f450d0220071000220e450d09200e200d2007200f412c6c220f200f20074b1b10f8022107200d10012007210d0c030b200f21100c040b200f21100c020b20071000220d450d060b200d21070b20072009412c6c6a220e410a3a0000200e202636000c200e2024360008200e2025360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a2109410021230b200141ec006a28020021272001280268212841012129024002400240024002400240200141f0006a280200222a450d0020102009470d0141000d0641000d0620104101742207201041016a220e200e2007491b2214ad422c7ea722074100480d062010450d0220071000220e450d0a200e200d20072010412c6c220f200f20074b1b10f8022107200d10012007210d0c030b201021144101212b0c040b201021140c020b20071000220d450d070b200d21070b20072009412c6c6a220e410b3a0000200e202a36000c200e2027360008200e2028360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a21094100212b0b200141f8006a280200212c20012802742110024002400240024002400240200141fc006a280200222d450d0020142009470d0141000d0641000d0620144101742207201441016a220e200e2007491b220fad422c7ea722074100480d062014450d0220071000220e450d0b200e200d20072014412c6c2214201420074b1b10f8022107200d10012007210d0c030b2014210f0c040b2014210f0c020b20071000220d450d080b200d21070b20072009412c6c6a220e410c3a0000200e202d36000c200e202c360008200e2010360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a2109410021290b20014184016a2802002114200128028001210e024002400240200f20096b20014188016a280200412c6c222e412c6d22014f0d00200920016a22012009490d03200f4101742207200120012007491b222fad422c7e2230422088a70d032030a722314100480d03200f450d01203110002207450d052007200d2031200f412c6c220f200f20314b1b10f8021a200d10010c020b200920016a2101200f212f0c010b203110002207450d030b20072009412c6c6a200e202e10f8021a02402014450d00200e10010b41c00510002209450d012000200736020820004280c2cdeb16370200200241086a410c6a4210370200200041106a20013602002000410c6a202f3602002002200936021020024280c2cdeb16370308200241106a10592009100102402029450d000240202d450d002010202d411c6c6a210d20102107034002402007410c6a2802002209450d0020072802042101200941047421090340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200941706a22090d000b0b0240200741086a280200450d00200741046a28020010010b2007411c6a21010240200741146a280200450d00200728021010010b200121072001200d470d000b0b202c450d00201010010b0240202b450d000240202a450d002028202a41186c6a210d2028210703400240200741046a280200450d00200728020010010b0240200741146a2802002209450d00200728020c2101200941047421090340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200941706a22090d000b0b200741186a21010240200741106a280200450d002007410c6a28020010010b200121072001200d470d000b0b2027450d00202810010b02402023450d0002402026450d0020252026411c6c6a210d20252107034002402007410c6a2802002209450d0020072802042101200941047421090340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200941706a22090d000b0b0240200741086a280200450d00200741046a28020010010b2007411c6a21010240200741146a280200450d00200728021010010b200121072001200d470d000b0b2024450d00202510010b0240201d450d0002402022450d00202241146c21092021210103400240200141046a280200450d00200128020010010b200141146a21012009416c6a22090d000b0b2020450d00202110010b0240201f450d000240201e450d00201c201e4104746a210d201c21070340024020072802082209450d0020072802002101200941047421090340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200941706a22090d000b0b200741106a21010240200741046a280200450d00200728020010010b200121072001200d470d000b0b201b450d00201c10010b02402018410047201a41017371450d00201910010b02402016410047201341017371450d00201710010b02402011410047201541017371450d00201210010b02402005450d000240200c450d00200c41286c2109200b210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101200941586a22090d000b0b200a450d00200b10010b02402008450d0002402006450d00200641047421092004210103400240200141046a280200450d00200128020010010b200141106a2101200941706a22090d000b0b2003450d00200410010b200241306a24000f0b1018000b41c00541041019000b203141041019000b200741041019000b200741041019000b200741041019000bb90504057f017e017f017e230041106b2203240002402001450d0020012104034020002802940321002004417f6a22040d000b0b02402001450d0003402001417f6a22010d000b0b4100210502402002450d0041002101034002400240200120002f01064f0d00200020014105746a220641386a2802002104200641346a2802002107200141016a2101200641c4006a2802004102460d030c010b0240024020002802002204450d0020003301044220862005ad84210841012106200421010c010b2005ad210841002106410021010b200010012008a72105024002402008422088a7220720042f01064f0d00200121040c010b03400240024020012802002200450d00200641016a210620013301044220862005ad842108200021040c010b2005ad2108410021040b200110012008a72105200421012008422088a7220720002f01064f0d000b0b200420074102746a4198036a2802002100200420074105746a220141c4006a2802002109200141386a2802002104200141346a2802002107024020064101460d00410120066b210103402000280294032100200141016a22010d000b0b4100210120094102460d020b2002417f6a210202402004450d00200710010b20020d000b0b02400240200041e8bdc000460d000240024020002802002201450d00200033010421082003200136020420034101360200200320084220862005ad84220837030841022104200010012001450d020c010b2005ad21084100210141012104200010014100450d010b024020012802002200450d002001330104210a20032000360204200320043602002003200a422086200842ffffffff0f8384370308200110012000450d010c020b410021002001100141000d010b200341106a24000f0b024020002802002201450d000340200010012001210020012802002204210120040d000b0b20001001200341106a24000bdf0201067f230041306b2202240041272103024002400240024002400240200028020022004190ce00490d00412721030340200241096a20036a2204417c6a200020004190ce006e220541f0b17f6c6a220641e4006e2207410174419892c0006a2f00003b00002004417e6a20062007419c7f6c6a410174419892c0006a2f00003b00002003417c6a2103200041ffc1d72f4b21042005210020040d000b41e4002104200541e400480d010c020b41e40021042000220541e4004e0d010b2005220041094a0d010c020b200241096a2003417e6a22036a200541ffff037120046e2200419c7f6c20056a41ffff0371410174419892c0006a2f00003b0000200041094c0d010b200241096a2003417e6a22036a22052000410174419892c0006a2f00003b00000c010b200241096a2003417f6a22036a2205200041306a3a00000b200141014188f0c10041002005412720036b10772100200241306a240020000bac0f01097f024020002802082201450d00200028020022022001412c6c6a2103034020022204412c6a21020240024002400240024002400240024002400240024002400240024020042d00002200410d4b0d00024020000e0e0002030405060708090e0a0b0c0d000b200441086a280200450d0d200441046a280200100120022003470d0e0c0f0b0240200441086a280200450d00200441046a28020010010b0240200441146a2802002200450d00200441186a280200450d00200010010b200441246a280200450d0c200441206a280200100120022003470d0d0c0e0b0240200441086a280200450d00200441046a28020010010b200441146a280200450d0b200441106a280200100120022003470d0c0c0d0b200441046a210502402004410c6a2802002201450d00200528020021002001410474210103400240200041046a280200450d00200028020010010b200041106a2100200141706a22010d000b0b200441086a280200450d0a2005280200100120022003470d0b0c0c0b200441046a210502402004410c6a2802002201450d0020052802002100200141286c210103400240200041046a280200450d00200028020010010b0240200041106a280200450d002000410c6a28020010010b200041286a2100200141586a22010d000b0b200441086a280200450d092005280200100120022003470d0a0c0b0b200441086a280200450d08200441046a280200100120022003470d090c0a0b200441086a280200450d07200441046a280200100120022003470d080c090b200441086a280200450d06200441046a280200100120022003470d070c080b200441046a210602402004410c6a2802002200450d002006280200220520004104746a21070340024020052802082201450d0020052802002100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010010b200041106a2100200141706a22010d000b0b200541106a21000240200541046a280200450d00200528020010010b2000210520002007470d000b0b200441086a280200450d052006280200100120022003470d060c070b200441046a210502402004410c6a2802002201450d0020052802002100200141146c210103400240200041046a280200450d00200028020010010b200041146a21002001416c6a22010d000b0b200441086a280200450d042005280200100120022003470d050c060b200441046a210602402004410c6a2802002200450d00200628020022052000411c6c6a2107034002402005410c6a2802002201450d0020052802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010010b200041106a2100200141706a22010d000b0b0240200541086a280200450d00200541046a28020010010b2005411c6a21000240200541146a280200450d00200528021010010b2000210520002007470d000b0b200441086a280200450d032006280200100120022003470d040c050b200441046a210602402004410c6a2802002200450d0020062802002205200041186c6a210703400240200541046a280200450d00200528020010010b0240200541146a2802002201450d00200528020c2100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010010b200041106a2100200141706a22010d000b0b200541186a21000240200541106a280200450d002005410c6a28020010010b2000210520002007470d000b0b200441086a280200450d022006280200100120022003470d030c040b200441046a210602402004410c6a2802002200450d00200628020022052000411c6c6a2107034002402005410c6a2802002201450d0020052802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010010b200041106a2100200141706a22010d000b0b0240200541086a280200450d00200541046a28020010010b2005411c6a21000240200541146a280200450d00200528021010010b2000210520002007470d000b0b200441086a280200450d012006280200100120022003470d020c030b024002400240200441046a2d000022004102460d0020004101460d0120000d022004410c6a280200450d03200441086a280200100120022003470d040c050b2004410c6a21080240200441146a2802002200450d002008280200220620004104746a210903402006220741106a2106024020072802042200450d0002402007410c6a2802002201450d002001410c6c21010340024020002802002205450d00200041046a280200450d00200510010b2000410c6a2100200141746a22010d000b0b200741086a280200450d00200741046a28020010010b20062009470d000b0b200441106a280200450d022008280200100120022003470d030c040b2004410c6a21070240200441146a2802002201450d00200728020021002001410c6c21010340024020002802002205450d00200041046a280200450d00200510010b2000410c6a2100200141746a22010d000b0b200441106a280200450d012007280200100120022003470d020c030b2004410c6a280200450d00200441086a28020010010b20022003470d000b0b0bfe1f03087f017e177f230041e0036b22032400200341d0026a41106a2204200141106a280200360200200341d0026a41086a2205200141086a290200370300200320012902003703d0022003200341d0026a1053024002400240024002400240024002400240410110002201450d00200141003a0000200320032f01d0023b01c001200441e0083b01002005428180808010370300200320013602d402200341013602d002200320032f01c0013b01e2022003200341d0026a105b2106410310002204450d01200441026a41002d0098b9413a0000200441002f0096b9413b0000410310002205450d02200541026a41002d008680413a0000200541002f008480413b0000200341c0016a41026a2207200341d0026a41026a22082d00003a0000200320032f00d0023b01c001200341146a2209280200210a200341106a2802002101200820072d00003a0000200320032f01c0013b01d002024002400240024002400240024002400240200a2001470d00200141016a220a2001490d0120014101742207200a200a2007491b2208ad42287e220b422088a70d01200ba7220a4100480d01024002402001450d002003410c6a280200210c200a10002207450d0e2007200c200a200141286c22012001200a4b1b10f8021a200c10010c010b200a10002207450d0d0b200341106a20083602002003410c6a2007360200200341146a280200210a0b2003410c6a280200200a41286c6a220141003a00182001200536020c200142838080803037020420012004360200200141106a4283808080303702002001411b6a200341d2026a2d00003a0000200141196a20032f01d0023b00002001411c6a20063602002009200928020041016a360200200341d0026a2003418c0110f8021a20034190016a200341d0026a105620034190016a41106a2802002208412c6c2101200328029801220741586a210402400340410021052001450d01200141546a2101200441286a210a2004412c6a22092104200a2d00004103470d000b200941086a2802002201450d00200141286c2104200928020041186a2101410021050340200520012d0000456a2105200141286a2101200441586a22040d000b0b2008412c6c2101200741586a21042005417f6a210a02400340410021052001450d01200141546a2101200441286a21092004412c6a2206210420092d00004103470d000b200641086a2802002201450d00200141286c2104200628020041186a2101410021050340200520012d0000456a2105200141286a2101200441586a22040d000b0b2008412c6c2101200741606a210402400240024003402001450d01200141546a2101200441206a21092004412c6a2206210420092d00004104470d000b2006280200210120080d010c020b410021012008450d010b200120056a210d20072008412c6c6a210e200241046a210f200241106a211041002111410021080240034002400240024020072d00002201410b460d0002402001410a460d0020014108470d02200728020c2201450d02200141146c2104200728020441106a2101034002402001417c6a2802000d0020012802002205200a490d002001200541016a3602000b200141146a21012004416c6a22040d000c030b0b200728020c2201450d01200728020422092001411c6c6a2106034020092201411c6a2109024020012802182204450d0020012802102101200441027421040340024020012802002205200a490d002001200541016a3602000b200141046a21012004417c6a22040d000b0b20092006470d000c020b0b200728020c2201450d0020072802042212200141186c6a2113034020082114024020122802144104742204450d00201228020c21010340024020012d0000410b470d00200141046a22052802002209200a490d002005200941016a3602000b200141106a2101200441706a22040d000b0b410810002215450d082015428080808010370200410410002216450d092012410c6a210520164100360200024002400240201241146a22172802002218450d0041002104410121082015210141012106201621192016211a4101211b4101210941002018220c4f0d0a02400340200441016a211d02400240024002400240024002400240024002400240024002400240024002400240200528020020044104746a2d00002204417e6a41034f0d002004105c211e200241086a280200211f200f210403402004280200221c41086a2120201c2f0106210c4100210402400340200c2004460d014100417f4101202020046a2d00002221201e41ff017122224b1b20212022461b2221450d04200441016a210420214101460d000b2004417f6a210c0b0240201f450d00201f417f6a211f201c200c4102746a41ec006a21040c010b0b2002210c2009417f6a22042009490d020c180b20044105460d0220044106470d032009450d172009417f6a21090c0b0b02400240201c20044103746a41146a2204450d002004280200221c4101460d182002210c201c4102470d01200441046a210c2009417f6a22042009490d020c180b2002210c0b2009417f6a220420094f0d160b200420094b0d152006201620044102746a28020022044d0d15200120044103746a221c2802042204200c2802006a220c2004490d15201c41046a200c360200024020082006470d00200841016a22012008490d1a20084101742204200120012004491b220cad420386220b422088a70d1a200ba722044100480d1a2008450d04200410002201450d1e20012015200420084103742208200820044b1b10f8021a201510010c050b2008210c0c050b2009450d1420082006470d01200841016a22042008490d182008410174220c20042004200c491b220cad420386220b422088a70d18200ba722044100480d182008450d09200410002215450d1e20152001200420084103742208200820044b1b10f8021a200110010c0a0b2004105c211e200241086a280200211f200f2104024003402004280200221c41086a2120201c2f0106210c4100210402400340200c2004460d014100417f4101202020046a2d00002221201e41ff017122224b1b20212022461b2221450d03200441016a210420214101460d000b2004417f6a210c0b0240201f450d00201f417f6a211f201c200c4102746a41ec006a21040c010b0b2002210c2009417f6a22042009490d070c140b201c20044103746a41146a2204450d042004280200221c4101460d132002210c201c4102470d05200441046a210c2009417f6a22042009490d060c130b2008210c0c090b200410002201450d190b200121150b200120064103746a220441013602042004201d3602000240024002400240201b2009470d00201b41016a2204201b490d17201b4101742208200420042008491b221cad420286220b422088a70d17200ba722044100480d17201b450d01200410002216450d1c2016201a2004201b4102742208200820044b1b10f8021a201a10010c020b201b211c0c020b200410002216450d1a0b201621192016211a0b200641016a2104201620094102746a2006360200200941016a2109201d2018490d070c090b2002210c0b2009417f6a220420094f0d0d0b200420094b0d0c2006201620044102746a28020022044d0d0c200120044103746a221c2802042204200c2802006a220c2004490d0c201c41046a200c3602000b2008210c20062104201b211c201d2018490d030c050b200410002215450d140b201521010b200120064103746a220441013602042004201d3602000240024002400240201b2009417f6a2208470d00201b4101742204200920092004491b221cad420286220b422088a70d10200ba722044100480d10201b450d01200410002216450d17201620192004201b410274221b201b20044b1b10f8021a201910010c020b201b211c0c020b200410002216450d150b201621192016211a0b200641016a2104201620084102746a2006360200201d20184f0d020b200c210820042106201c211b201d22042017280200220c4f0d0c0c000b0b2004450d02200120044103746a21060c010b201541086a21064101211c4101210c201521010b4101210403402001290200210b2003412d3a00d0022003200b4220883e02d40220052004200ba76a2209417f6a200341d0026a105d2003410b3a00d0022003200a3602d40220052009200341d0026a105d200441026a21042006200141086a2201470d000b0b0240200c450d00201510010b0240201c450d00201610010b201241186a211202402010280200450d0020172802002204450d002005280200210120044104742104410021050340024020012d0000412c470d002001410b3a0000200141046a200d360200200541016a21050b200141106a2101200441706a22040d000b410121082005450d0020122013470d010c020b2014210820122013470d000b0b2007412c6a2207200e470d010c020b02402008450d00201510010b410121110240201b450d00201610010b201421082007412c6a2207200e470d000b0b02402011410171450d00200020032903900137020420004101360200200041146a200341a0016a2802003602002000410c6a20034198016a290300370200200341e0036a24000f0b2008410171450d00200341d0026a41106a20034190016a41106a280200360200200341d0026a41086a20034190016a41086a29030037030020032003290390013703d002200341c0016a200341d0026a1053411010002204450d0d200441063a0000410110002201450d0e200141003a0000410110002209450d0f200920012d00003a000020011001411010002205450d10200541063a000041f00010002201450d11200141063a00602001412c3b01502001200a3602442001410b3a0040200141d8003a00302001412d3a0020200141003602142001410f3a0010200141003602042001410f3a00002001200241106a280200360224024020052d00004109470d00200528020841ffffffff0371450d00200528020410010b20051001024020042d00004109470d00200428020841ffffffff0371450d00200428020410010b20041001200341f4026a4287808080f000370200200341f0026a2001360200200341ec026a4100360200200341d0026a410c6a4281808080800c370200200341d0026a41086a4101360200200341003602fc02200342043702e402200320093602d402200341013602d002200341c0016a200341d0026a1055200341d0026a200341c0016a418c0110f8021a200341a8016a200341d0026a105620004100360200200041146a200341b8016a2802003602002000410c6a200341a8016a41086a290300370200200020032903a801370204200341e0036a24000f0b200020032903900137020420004100360200200041146a200341a0016a2802003602002000410c6a20034198016a290300370200200341e0036a24000f0b1018000b41c08ec2002004200c104e000b410841041019000b410441041019000b200441041019000b200441041019000b200441041019000b200441041019000b410141011019000b410341011019000b410341011019000b200a41041019000b411041081019000b410141011019000b410141011019000b411041081019000b41f00041081019000bd60a020f7f017e230041106b220224000240024002400240024002400240024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042101200241086a2000104920022802082208200228020c22094104746a210a4100210b024020094104490d00200341ff0171210c0340024020082d000c200c470d0020082802082004470d002008280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b200741ff017122094104472008410d6a2d0000220e410446220f460d00200e2009460d0920094104460d09200f0d090b02402008411c6a2d0000200c470d00200841186a2802002004470d00200841106a280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b200741ff017122094104472008411d6a2d0000220e410446220f460d00200e2009460d0620094104460d06200f0d060b02402008412c6a2d0000200c470d00200841286a2802002004470d00200841206a280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b200741ff017122094104472008412d6a2d0000220e410446220f460d00200e2009460d0720094104460d07200f0d070b02402008413c6a2d0000200c470d00200841386a2802002004470d00200841306a280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b200741ff017122094104472008413d6a2d0000220e410446220f460d00200e2009460d0820094104460d08200f0d080b200b41046a210b200a200841c0006a22086b413f4b0d000b0b2008200a460d02200741ff017122104104470d01200341ff0171210c0340024020082d000c200c470d0020082802082004470d002008280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b2008410d6a2d00004104460d080b200b41016a210b200841106a2208200a470d000c030b0b20012802042104200241106a240020040f0b200341ff0171210c0340024020082d000c200c470d0020082802082004470d002008280200210d4100210902400340200920044f0d01200120096a210e200d20096a210f200941016a2109200f2d0000200e2d0000460d000c020b0b2008410d6a2d000022092010470d0020094104470d060b200b41016a210b200841106a2208200a470d000b0b0240024002400240200041046a28020020002802082209470d00200941016a22082009490d092009410174220e20082008200e491b220fad4204862211422088a70d092011a7220e4100480d092009450d012000280200210b200e10002208450d0a2008200b200e200941047422092009200e4b1b10f8021a200b10010c020b200028020021080c020b200e10002208450d080b20002008360200200041046a200f360200200041086a28020021090b200820094104746a220920063b010e200920073a000d200920033a000c200920043602082009200536020420092001360200200041086a2204200428020041016a3602002002200010492002280204417f6a210b0c070b200b410172210b20050d030c060b200b410272210b20050d020c050b200b410372210b0b2005450d030b20011001200241106a2400200b0f0b1018000b200e41041019000b200241106a2400200b0bb505000240024002400240024002400240024002400240200041ff0171417f6a220041aa014b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020000eab014a00000000000000000000000000010101010103030404050506060707080809094b0a0a0b0b0c0c0d0d4c4d0e0e0f0f10101111121213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f20204e212122224f2323242450252526262727282829292a2a512b2b2c2c2d2d2e2e2f2f30303131323233333434353536363737383839393a3a3b3b3c3c3d3d3e3e523f3f404041414242434344444545464647474848020202024a0b410a0f0b41080f0b41100f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41050f0b41050f0b41050f0b41050f0b41060f0b41070f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b41000f0b41010f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b41000f0b41010f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410f0f0b410f0f0b410e0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b41110f0b41120f0b41050f0b41130f0b41140f0b41000f0b41020f0b41000f0b41020f0b410e0b9a0203047f017e037f02400240200041086a28020022032001490d00024002400240024002402003200041046a280200470d00200341016a22042003490d0420034101742205200420042005491b2206ad4204862207422088a70d042007a722084100480d042003450d0120002802002109200810002205450d062005200920082003410474220a200a20084b1b10f8021a200910010c020b200341016a2104200028020021050c020b200810002205450d040b20002005360200200041046a20063602000b200520014104746a220541106a2005200320016b41047410f9021a200541086a200241086a29030037030020052002290300370300200041086a20043602000f0b1018000b41e88ec200104f000b200841081019000baf0201027f02400240024002402001410c6a2802002203417f6a220420034d0d00411610002201450d01200020013602042001410e6a41002900c08940370000200141086a41002900ba8940370000200141002900b28940370000200041086a4296808080e002370200200041013602000f0b0240200420026b220220044d0d00411b10002201450d02200020013602042001411a6a41002d00e289403a0000200141186a41002f00e089403b0000200141106a41002900d88940370000200141086a41002900d08940370000200141002900c88940370000200041086a429b808080b003370200200041013602000f0b200320024d0d022000200141046a28020020024104746a360204200041003602000f0b411641011019000b411b41011019000b41908fc20020022003104e000bf50201037f230041106b22032400024002402002450d00200320014100105e20032802004101470d01200020034104722202290200370200200041086a200241086a280200360200200341106a24000f0b20004100360200200341106a24000f0b02400240024002402001280200220420032802042205280208470d0020052d000c450d0120004100360200200341106a24000f0b0240200420026b220220044d0d00410f10002202450d022000428f808080f00137020420002002360200200241076a41002900aa8940370000200241002900a38940370000200341106a24000f0b2000410036020020012002360200200341106a24000f0b412510002202450d01200042a5808080d004370204200020023602002002411d6a410029009b8940370000200241186a41002900968940370000200241106a410029008e8940370000200241086a41002900868940370000200241002900fe8840370000200341106a24000f0b410f41011019000b412541011019000bcf0f03097f027e077f230041b0016b2202240002400240024002400240024002402000280200220341e8bdc000460d00200028020421040c010b41ec0010002203450d0141002104200341003b010620034100360200200341086a200241186a41e40010f8021a20004100360204200020033602000b200141ff01712105024002400340200341086a210720032f01062106410021080240034020062008460d014100417f4101200720086a2d0000220920054b1b20092005461b2209450d03200841016a210820094101460d000b2008417f6a21060b02402004450d002004417f6a2104200320064102746a41ec006a28020021030c010b0b2000200028020841016a3602082002200636021420022000360210200241003602082002200336020c20032f01062208410b4f0d01200341086a2205200641016a22096a200520066a2205200820066b10f9021a200520013a0000200341146a220820094103746a200820064103746a2205200341066a22082f010020066b41037410f9021a20054101360200200820082f010041016a3b0100200241b0016a24000f0b20022004360218200220003602202002200041086a360228200220083602242002200336021c200320084103746a41146a42013702000c050b41ec0010002205450d02200541003b010620054100360200200541086a200241186a41e40010f80221092003410e6a2d0000210a2003290244210b20092003410f6a200341066a22042f010041796a220810f8022109200541146a200341cc006a200841037410f8022107200441063b0100200520083b0106200b422088210c02400240200641064b0d00200341086a2208200641016a22096a200820066a2204200341066a22082f010020066b10f9021a200420013a0000200341146a220420094103746a200420064103746a220920082f010020066b41037410f9021a200941013602000c010b20092006417a6a22046a2009200641796a22066a2209200841ffff037120066b10f9021a200920013a0000200720044103746a200720064103746a2209200541066a22082f010020066b41037410f9021a200941013602000b200ca7210d200ba7210e200820082f010041016a3b01000240024020032802002208450d0003402005210f200a211020032f01042109200822072f01062208410a4d0d02419c0110002205450d04200541003b010620054100360200200541086a200241186a41940110f80221032007410e6a2d0000210a2007290244210b20032007410f6a200741066a22012f0100220641796a220810f8022111200541146a200741cc006a200841037410f8022112200541ec006a20074188016a2006417a6a220441027410f8022113200141063b0100200520083b010602402004450d00410021082013210303402003280200220620083b010420062005360200200341046a21032004200841016a2208470d000b0b200b422088210c02400240200941064b0d00200741086a2203200941016a22086a200320096a220320012f0100220620096b220410f9021a200320103a0000200741146a220320084103746a200320094103746a2203200441037410f9021a2003200e3602002003200d3602042001200641016a22033b0100200741ec006a2206200941027422016a41086a200620084102746a2204200341ffff0371220620086b41027410f9021a2004200f360200200920064f0d01200720016a41f0006a2108034020082802002203200941016a22093b010420032007360200200841046a210820062009470d000c020b0b20112009417a6a22036a2011200941796a22086a2204200541066a22062f010020086b10f9021a200420103a0000201220034103746a201220084103746a220420062f010020086b41037410f9021a2004200e3602002004200d360204200620062f010041016a22043b01002013200941027422016a416c6a201320034102746a2206200441ffff0371220920036b41027410f9021a2006200f360200200320094b0d00200520016a41d4006a2103034020032802002206200841016a22083b010420062005360200200341046a210320092008470d000b0b200ca7210d200ba7210e20072103200728020022080d000b0b419c0110002208450d04200841003b010620084100360200200841086a200241186a41940110f802210620082000280200220336026c200020083602002000200028020441016a360204200341003b010420032008360200200820082f010622034103746a220941186a200d360200200941146a200e360200200620036a200a3a0000200841ec006a200341016a22034102746a2005360200200820033b0106200520033b010420052008360200200241b0016a24000f0b200741086a2206200941016a22036a200620096a2206200820096b220510f9021a200620103a0000200741146a220620034103746a200620094103746a2206200541037410f9021a2006200e3602002006200d360204200741066a200841016a22083b0100200741ec006a220620094102746a41086a200620034102746a2206200841ffff0371220520036b41027410f9021a2006200f360200200920054f0d0420072003417f6a22084102746a41f0006a2103034020032802002206200841016a22083b010420062007360200200341046a210320052008470d000c050b0b41ec0041041019000b419c0141041019000b41ec0041041019000b419c0141041019000b200241b0016a24000b6b000240024020002d000022004101460d0020004102470d01200128021841a48cc000410b2001411c6a28020028020c1100000f0b200128021841978cc000410d2001411c6a28020028020c1100000f0b2001280218418b8cc000410c2001411c6a28020028020c1100000b130020004102360204200041b88fc2003602000bda0801047f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001413f4b0d00200241046a280200200241086a2802002203470d01200341016a22042003490d1520034101742205200420042005491b22054100480d152003450d0520022802002106200510002204450d162004200620052003200320054b1b10f8021a200610010c060b2001418080014f0d01200241046a2802002205200241086a28020022036b41024f0d02200341026a22042003490d1420054101742203200420042003491b22034100480d142005450d0920022802002106200310002204450d162004200620032005200520034b1b10f8021a200610010c0a0b200228020021040c050b20014180808080044f0d01200241046a2802002205200241086a28020022036b41044f0d05200341046a22042003490d1220054101742203200420042003491b22034100480d122005450d0a20022802002106200310002204450d152004200620032005200520034b1b10f8021a200610010c0b0b200228020021040c080b200241046a280200200241086a2802002203470d04200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d0b20022802002106200510002204450d142004200620052003200320054b1b10f8021a200610010c0c0b200510002204450d100b20022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20014102743a0000200141037422010d0b0c0c0b200228020021040c060b200228020021040c080b200310002204450d0c0b20022004360200200241046a2003360200200241086a28020021030b200241086a200341026a360200200420036a20014102744101723b0000200141037422010d060c070b200310002204450d0a0b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a2001410274410272360000200141037422010d030c040b200510002204450d080b20022004360200200241046a2005360200200241086a28020021030b200241086a2206200341016a360200200420036a41033a00000240024002400240200241046a2802002205200628020022036b41044f0d00200341046a22042003490d0620054101742203200420042003491b22034100480d062005450d0120022802002106200310002204450d0b2004200620032005200520034b1b10f8021a200610010c020b200228020021040c020b200310002204450d090b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a200136000020014103742201450d010b200020016a210103402000280200200041046a28020020021064200041086a22002001470d000b0b0f0b1018000b200541011019000b200341011019000b200341011019000b200541011019000b200341011019000bc40901067f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001413f4b0d00200241046a2203280200200241086a22042802002205470d01200541016a22062005490d1420054101742207200620062007491b22074100480d142005450d0520022802002108200710002206450d162006200820072005200520074b1b10f8021a200810010c060b2001418080014f0d01200241046a22032802002207200241086a220428020022056b41024f0d02200541026a22062005490d1320074101742205200620062005491b22054100480d132007450d0920022802002108200510002206450d162006200820052007200720054b1b10f8021a200810010c0a0b200228020021060c050b20014180808080044f0d01200241046a22032802002207200241086a220428020022056b41044f0d05200541046a22062005490d1120074101742205200620062005491b22054100480d112007450d0a20022802002108200510002206450d152006200820052007200720054b1b10f8021a200810010c0b0b200228020021060c080b200241046a2203280200200241086a22042802002205470d04200541016a22062005490d0f20054101742207200620062007491b22074100480d0f2005450d0b20022802002108200710002206450d142006200820072005200520074b1b10f8021a200810010c0c0b200710002206450d100b20022006360200200241046a2007360200200241086a28020021050b2004200541016a360200200620056a20014102743a00000c0b0b200228020021060c060b200228020021060c080b200510002206450d0c0b20022006360200200241046a2005360200200241086a28020021050b2004200541026a360200200620056a20014102744101723b00000c060b200510002206450d0a0b20022006360200200241046a2005360200200241086a28020021050b2004200541046a360200200620056a20014102744102723600000c030b200710002206450d080b20022006360200200241046a2007360200200241086a28020021050b2004200541016a360200200620056a41033a0000024002400240024020032802002207200428020022056b41044f0d00200541046a22062005490d0520074101742205200620062005491b22054100480d052007450d0120022802002108200510002206450d0b2006200820052007200720054b1b10f8021a200810010c020b200228020021060c020b200510002206450d090b20022006360200200241046a2005360200200241086a28020021050b2004200541046a360200200620056a20013600000b024002400240024020032802002206200428020022056b20014f0d00200520016a22032005490d0420064101742205200320032005491b22054100480d042006450d0120022802002107200510002203450d052003200720052006200620054b1b10f8021a200710010c020b200228020021030c020b200510002203450d030b20022003360200200241046a2005360200200241086a28020021050b2004200520016a360200200320056a2000200110f8021a0f0b1018000b200541011019000b200741011019000b200541011019000b200541011019000b200741011019000b200541011019000b850801047f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000413f4b0d00200141046a280200200141086a2802002202470d01200241016a22032002490d1320024101742204200320032004491b22044100480d132002450d0520012802002105200410002203450d142003200520042002200220044b1b10f8021a200510010c060b2000418080014f0d01200141046a2802002204200141086a28020022026b41024f0d02200241026a22032002490d1220044101742202200320032002491b22024100480d122004450d0920012802002105200210002203450d142003200520022004200420024b1b10f8021a200510010c0a0b200128020021030c050b20004180808080044f0d01200141046a2802002204200141086a28020022026b41044f0d05200241046a22032002490d1020044101742202200320032002491b22024100480d102004450d0a20012802002105200210002203450d132003200520022004200420024b1b10f8021a200510010c0b0b200128020021030c080b200141046a280200200141086a2802002202470d04200241016a22032002490d0e20024101742204200320032004491b22044100480d0e2002450d0b20012802002105200410002203450d122003200520042002200220044b1b10f8021a200510010c0c0b200410002203450d0e0b20012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b200128020021030c060b200128020021030c080b200210002203450d0a0b20012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b200210002203450d080b20012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b200410002203450d060b20012003360200200141046a2004360200200141086a28020021020b200141086a2205200241016a360200200320026a41033a00000240024002400240200141046a2802002204200528020022026b41044f0d00200241046a22032002490d0420044101742202200320032002491b22024100480d042004450d0120012802002105200210002203450d092003200520022004200420024b1b10f8021a200510010c020b200128020021030c020b200210002203450d070b20012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b1018000b200441011019000b200241011019000b200241011019000b200441011019000b200241011019000bcf0101027f200028020421020240024020002802004101470d002000410c6a2802002200200110652000450d01200041186c2103200241146a21000340200041706a280200200041746a280200200110642000417c6a280200200028020020011064200041186a2100200341686a22030d000c020b0b200041086a2802002200200110652000450d00200041186c2103200241146a21000340200041706a280200200041746a280200200110642000417c6a280200200028020020011064200041186a2100200341686a22030d000b0b0bb60201037f230041306b22022400024020002802004101470d00200041086a2802002000410c6a28020020011064200041146a280200200041186a280200200110642000411c6a20011068200241306a24000f0b200241086a2000280204110100200228020c200241106a28020020011064200241186a2802002002411c6a28020020011064200241206a22002001106802402000280200450d00200241086a411c6a28020021030240200241086a41246a2802002200450d00200041306c21044100210103400240200320016a2200410c6a280200450d00200041146a280200450d00200041106a28020010010b02402000411c6a280200450d00200041246a280200450d00200041206a28020010010b2004200141306a2201470d000b0b200241286a280200450d00200310010b200241306a24000be205010a7f200028020421020240024002400240024020002802004101470d002000410c6a2802002200200110652000450d01200041306c2103200141086a2104200141046a2105410021060340200220066a2200412c6a2f01002107024002400240024020052802002208200428020022096b41024f0d00200941026a220a2009490d0720084101742209200a200a2009491b22094100480d072008450d012001280200210b20091000220a450d08200a200b20092008200820094b1b10f8021a200b10010c020b2001280200210a0c020b20091000220a450d060b2001200a36020020052009360200200428020021090b2004200941026a360200200a20096a20073b0000200041046a280200200041086a280200200110642000410c6a20011066200041206a280200210902402000411c6a2802004101470d002009200041286a280200200110632003200641306a2206470d010c030b2009200041246a280200200110632003200641306a2206470d000c020b0b200041086a2802002200200110652000450d00200041306c2103200141086a2104200141046a2105410021060340200220066a2200412c6a2f01002107024002400240024020052802002208200428020022096b41024f0d00200941026a220a2009490d0620084101742209200a200a2009491b22094100480d062008450d012001280200210b20091000220a450d08200a200b20092008200820094b1b10f8021a200b10010c020b2001280200210a0c020b20091000220a450d060b2001200a36020020052009360200200428020021090b2004200941026a360200200a20096a20073b0000200041046a280200200041086a280200200110642000410c6a20011066200041206a280200210902402000411c6a2802004101470d002009200041286a280200200110632003200641306a2206470d010c020b2009200041246a280200200110632003200641306a2206470d000b0b0f0b1018000b200941011019000b200941011019000bdf0101027f230041206b22022400024020002802004101470d00200041086a2802002000410c6a28020020011064200041106a2001106a200241206a24000f0b200220002802041101002002280204200241086a280200200110642002410c6a2001106a0240200228020c450d00200241106a28020021030240200241186a2802002200450d002000413c6c2101200341306a210003400240200041786a280200450d002000280200450d002000417c6a28020010010b2000413c6a2100200141446a22010d000b0b200241146a280200450d00200310010b200241206a24000b880f01097f200028020421020240024002400240024002400240024002400240024020002802004101470d002000410c6a2802002200200110652000450d012000413c6c2103410021040340200220046a220041046a280200200041086a28020020011064200141046a22052802002106200141086a220728020021080240024002400240024002400240024002400240200041386a2d00004101470d0020062008470d01200841016a22062008490d0d20084101742209200620062009491b22094100480d0d2008450d032001280200210a200910002206450d0e2006200a20092008200820094b1b10f8021a200a10010c040b20062008470d01200841016a22062008490d0c20084101742209200620062009491b22094100480d0c2008450d052001280200210a200910002206450d0e2006200a20092008200820094b1b10f8021a200a10010c060b200128020021060c030b200128020021060c050b200910002206450d0a0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41013a00000c030b200910002206450d080b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41003a00000b200528020021062007280200210802400240024002400240024002400240024002402000410c6a2802004101470d0020062008470d01200841016a22062008490d0d20084101742209200620062009491b22094100480d0d2008450d032001280200210a200910002206450d102006200a20092008200820094b1b10f8021a200a10010c040b20062008470d01200841016a22062008490d0c20084101742209200620062009491b22094100480d0c2008450d052001280200210a200910002206450d102006200a20092008200820094b1b10f8021a200a10010c060b200128020021060c030b200128020021060c050b200910002206450d0c0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41013a0000200041146a280200200041186a28020020011064200041206a280200200041246a280200200110640c030b200910002206450d0a0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41003a0000200041146a280200200041186a280200200110640b2000412c6a28020021080240200041286a2802004101470d002008200041346a2802002001106320032004413c6a2204470d010c030b2008200041306a2802002001106320032004413c6a2204470d000c020b0b200041086a2802002200200110652000450d002000413c6c2103410021040340200220046a220041046a280200200041086a28020020011064200141046a22052802002106200141086a220728020021080240024002400240024002400240024002400240200041386a2d00004101470d0020062008470d01200841016a22062008490d0c20084101742209200620062009491b22094100480d0c2008450d032001280200210a200910002206450d112006200a20092008200820094b1b10f8021a200a10010c040b20062008470d01200841016a22062008490d0b20084101742209200620062009491b22094100480d0b2008450d052001280200210a200910002206450d112006200a20092008200820094b1b10f8021a200a10010c060b200128020021060c030b200128020021060c050b200910002206450d0d0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41013a00000c030b200910002206450d0b0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41003a00000b200528020021062007280200210802400240024002400240024002400240024002402000410c6a2802004101470d0020062008470d01200841016a22062008490d0c20084101742209200620062009491b22094100480d0c2008450d032001280200210a200910002206450d132006200a20092008200820094b1b10f8021a200a10010c040b20062008470d01200841016a22062008490d0b20084101742209200620062009491b22094100480d0b2008450d052001280200210a200910002206450d132006200a20092008200820094b1b10f8021a200a10010c060b200128020021060c030b200128020021060c050b200910002206450d0f0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41013a0000200041146a280200200041186a28020020011064200041206a280200200041246a280200200110640c030b200910002206450d0d0b2001200636020020052009360200200728020021080b2007200841016a360200200620086a41003a0000200041146a280200200041186a280200200110640b2000412c6a28020021080240200041286a2802004101470d002008200041346a2802002001106320032004413c6a2204470d010c020b2008200041306a2802002001106320032004413c6a2204470d000b0b0f0b1018000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000be103010c7f230041206b22032400024002402002450d0020024102742204100022050d01200441041019000b410421050b0240024002400240200120024103746a22062001460d0020024103742107200141046a210420052108034020082004280200360200200441086a2104200841046a2108200741786a22070d000b200641786a20016b41037641016a21094101210a410021084100210703402001280200210b02400240024002402008200722046b200141046a280200220c4f0d002004200c6a22072004490d072008410174220d20072007200d491b220d4100480d072008450d01200d1000220e450d08200e200a200d20082008200d4b1b10f8022108200a10012008210a0c020b200c20046a21070c020b200d1000220a450d060b200d21080b200a20046a200b200c10f8021a200141086a22012006470d000c020b0b4101210a41002109410021080b200341186a22014200370300200341106a22044200370300200341086a2207420037030020034200370300200a2005200920031005200041186a2001290300370000200041106a2004290300370000200041086a20072903003700002000200329030037000002402008450d00200a10010b02402002450d00200510010b200341206a24000f0b1018000b200d41011019000b2700200028020c200041106a2802001006200041146a3502001007200041186a350200100700000ba50801117f230041c0006b22032400200341086a411c6a22042001360200200341346a2205200241146a2802002201360200200341033a0038200341086a41246a220620022802102207200141037422086a360200200342808080808004370308200320003602204100210120034100360218200341003602102003200736023020032007360228200228020441037421092002280200210a02400240024002400240024002400240024020022802082200450d002000411c6a21072002410c6a28020041246c2102200341206a210b200341386a210c200341306a210d200341086a41086a210e200341086a41146a210f200341186a2110200341286a211103402002450d0220092001460d05200b280200200a20016a2208280200200841046a280200200428020028020c1100000d04200c20002d00203a00002003200028020836020c2003200028020c360208410021080240024002400240200028021822124101460d00024020124103460d0020124102470d02201128020022132006280200460d002011201341086a36020020132802044104470d04201328020028020021120c030b0c030b20072802002213200528020022124f0d0b200d28020020134103746a22132802044104470d02201328020028020021120c010b200728020021120b410121080b200341086a410c6a2012360200200e2008360200410021080240024002400240200028021022124101460d00024020124103460d0020124102470d02201128020022132006280200460d002011201341086a36020020132802044104470d04201328020028020021120c030b0c030b200741786a2802002213200528020022124f0d0c200d28020020134103746a22132802044104470d02201328020028020021120c010b200741786a28020021120b410121080b200f2012360200201020083602000240024020002802004101470d00200741686a2802002208200528020022124f0d08200d28020020084103746a21080c010b201128020022082006280200460d082011200841086a3602000b200041246a21002002415c6a2102200741246a2107200141086a21012008280200200341086a200841046a280200110200450d000c040b0b200341206a211120092101200a210003402008450d022001450d0420112802002000280200200041046a280200200428020028020c1100000d03200841786a2108200141786a2101200041086a21002007280200210220072802042112200741086a21072002200341086a2012110200450d000c030b0b200a20016a21000b2000200a20096a460d01200341206a28020020002802002000280204200341246a28020028020c110000450d010b200341c0006a240041010f0b200341c0006a240041000f0b41a093c20020082012104e000b41b092c200104f000b419093c20020132012104e000b419093c20020132012104e000b900101017f230041c0006b220024002000413336020c200041e08ec000360208200041286a410c6a4105360200200041246a4102360200200041106a410c6a41023602002000410136022c2000418489c20036021820004102360214200041a4aec3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41b4aec3001071000b1c00200128021841c1afc00041052001411c6a28020028020c1100000b1000200120002802002000280204107c0b4a02017f017e230041206b2202240020012902002103200241146a20012902083702002002200337020c200220003602082002418891c20036020420024188f0c1003602002002106c000b02000bd20101047f024002400240024002400240200028020022002802042203200028020822046b20024f0d00200420026a22052004490d0420034101742204200520052004491b22044100480d042003450d0120002802002106200410002205450d052005200620042003200320044b1b10f8021a200610010c020b200028020021050c020b200410002205450d030b20002005360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200520046a2001200210f8021a41000f0b1018000b200441011019000be90401057f230041106b22022400200028020021000240024002400240024002400240024002400240024020014180014f0d00200028020822032000280204470d03200341016a22042003490d0820034101742205200420042005491b22044100480d082003450d0120002802002106200410002205450d092005200620042003200320044b1b10f8021a200610010c020b2002410036020c0240024020014180104f0d0020022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b0240200141ffff034b0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b024020002802042205200028020822036b20014f0d00200320016a22042003490d0820054101742203200420042003491b22034100480d082005450d0420002802002106200310002204450d0a2004200620032005200520034b1b10f8021a200610010c050b200028020021040c050b200410002205450d070b20002005360200200041046a2004360200200041086a28020021030b200028020020036a20013a0000200041086a2200200028020041016a3602000c030b200310002204450d050b20002004360200200041046a2003360200200041086a28020021030b200041086a200320016a360200200420036a2002410c6a200110f8021a0b200241106a240041000f0b1018000b200441011019000b200341011019000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41e090c200200241086a106d2101200241206a240020010b890101017f230041306b220224002002200136020420022000360200200241206a410c6a41033602002002411c6a4102360200200241086a410c6a4102360200200241033602242002418489c2003602102002410236020c2002419891c2003602082002200241046a360228200220023602202002200241206a360218200241086a41a891c2001071000b9a0a01047f230041206b2206240020062003360204200620023602002006418080c4003602080240024002402001450d00200028020022074101710d01200521080c020b2006412d360208200541016a2108200028020021070c010b2006412b360208200541016a21080b41002101200641003a000f02402007410471450d00200641013a000f02402003450d0041002101200321090340200120022d000041c00171418001466a2101200241016a21022009417f6a22090d000b0b200820036a20016b21080b200028020821022006200636021820062006410f6a3602142006200641086a3602100240024002400240024002400240024002400240024002400240024002400240024020024101470d002000410c6a280200220220084d0d0120074108710d02200220086b2109410120002d0030220220024103461b4103712202450d0420024102460d03410021030c050b200641106a200010790d0e2000280218200420052000411c6a28020028020c1100002102200641206a240020020f0b200641106a200010790d0d2000280218200420052000411c6a28020028020c1100002102200641206a240020020f0b200041013a003020004130360204200641106a200010790d0c200220086b21094101200041306a2d0000220220024103461b4103712202450d0420024102460d03410021030c050b200941016a4101762103200941017621090c010b20092103410021090b2006410036021c02402000280204220241ff004b0d00200620023a001c410121010c050b0240200241ff0f4b0d0020062002413f71418001723a001d20062002410676411f7141c001723a001c410221010c050b200241ffff034b0d0320062002413f71418001723a001e20062002410676413f71418001723a001d20062002410c76410f7141e001723a001c410321010c040b200941016a4101762103200941017621090c010b20092103410021090b2006410036021c0240200041046a280200220241ff004b0d00200620023a001c410121010c060b200241ff0f4b0d0220062002413f71418001723a001d20062002410676411f7141c001723a001c410221010c050b20062002413f71418001723a001f2006200241127641f001723a001c20062002410676413f71418001723a001e20062002410c76413f71418001723a001d410421010b417f210202400340200241016a220220094f0d01200041186a2802002006411c6a20012000411c6a28020028020c110000450d000c060b0b200641106a200010790d04200041186a2209280200200420052000411c6a220028020028020c1100000d04417f21020340200241016a220220034f0d0220092802002006411c6a2001200028020028020c110000450d000c050b0b200241ffff034b0d0120062002413f71418001723a001e20062002410676413f71418001723a001d20062002410c76410f7141e001723a001c410321010c020b200641206a240041000f0b20062002413f71418001723a001f2006200241127641f001723a001c20062002410676413f71418001723a001e20062002410c76413f71418001723a001d410421010b417f210202400340200241016a220220094f0d01200041186a2802002006411c6a20012000411c6a28020028020c110000450d000c020b0b200041186a2209280200200420052000411c6a220028020028020c1100000d00417f21020340200241016a220220034f0d0220092802002006411c6a2001200028020028020c110000450d000b0b200641206a240041010f0b200641206a240041000b0d0042b4d39cd2fdebc6cdde000be80201057f230041106b2202240002400240024020002802002802002203418080c400460d002001411c6a2802002104200128021821052002410036020c02400240200341ff004b0d00200220033a000c410121060c010b0240200341ff0f4b0d0020022003413f71418001723a000d20022003410676411f7141c001723a000c410221060c010b0240200341ffff034b0d0020022003413f71418001723a000e20022003410676413f71418001723a000d20022003410c76410f7141e001723a000c410321060c010b20022003413f71418001723a000f2002200341127641f001723a000c20022003410676413f71418001723a000e20022003410c76413f71418001723a000d410421060b4101210320052002410c6a2006200428020c1100000d010b20002802042d0000450d0120012802182000280208220028020020002802042001411c6a28020028020c11000021030b200241106a240020030f0b200241106a240041000b890101017f230041306b220224002002200136020420022000360200200241206a410c6a41033602002002411c6a4102360200200241086a410c6a4102360200200241033602242002418489c2003602102002410236020c200241b891c2003602082002200241046a360228200220023602202002200241206a360218200241086a41c891c2001071000bda0203037f017e027f230041306b220224004127210302400240024020004290ce00540d00412721030340200241096a20036a2204417c6a200020004290ce0080220542f0b17f7e7ca7220641e4006e2207410174419892c0006a2f00003b00002004417e6a2007419c7f6c20066a410174419892c0006a2f00003b00002003417c6a2103200042ffc1d72f5621042005210020040d000b41e40021062005a7220441e400480d020c010b41e400210620002205a7220441e400480d010b200241096a2003417e6a22036a2005a7220741ffff037120066e2204419c7f6c20076a41ffff0371410174419892c0006a2f00003b00000b02400240200441094a0d00200241096a2003417f6a22036a2206200441306a3a00000c010b200241096a2003417e6a22036a22062004410174419892c0006a2f00003b00000b200141014188f0c10041002006412720036b10772103200241306a240020030bfb09010c7f230041106b2203240020002802102104024002400240024002400240024002400240200028020822054101470d0020040d010c020b2004450d070b02402002450d00200120026a2106200041146a280200417f732107410021082001210420012109024002400340200441016a210a0240024020042c0000220b4100480d00200b41ff0171210b200a2104200741016a22070d010c030b024002400240200a2006460d00200a2d0000413f71210c200441026a2204210a200b411f71210d200b41ff0171220b41e001490d010c020b4100210c20062104200b411f71210d200b41ff0171220b41e0014f0d010b200c200d41067472210b200a2104200741016a22070d010c030b02400240024020042006460d00200441016a220a210e20042d0000413f71200c41067472210c200b41f001490d010c020b2006210e4100200c41067472210c200b41f0014f0d010b200c200d410c7472210b200a2104200741016a22070d010c030b02400240200e2006460d00200e41016a2104200e2d0000413f71210b0c010b4100210b200a21040b200c410674200d411274418080f0007172200b72220b418080c400460d03200741016a2207450d020b200820096b20046a21082004210920062004470d000c020b0b200b418080c400460d00024002402008450d0020082002460d0041002104200820024f0d01200120086a2c00004140480d010b200121040b2008200220041b21022004200120041b21010b2005450d020c010b410021022005450d010b4100210a02402002450d002002210b200121040340200a20042d000041c00171418001466a210a200441016a2104200b417f6a220b0d000b0b2002200a6b2000410c6a28020022074f0d014100210a02402002450d004100210a2002210b200121040340200a20042d000041c00171418001466a210a200441016a2104200b417f6a220b0d000b0b200a20026b20076a210b410020002d0030220420044103461b4103712204450d0220044102460d03410021070c040b2000280218200120022000411c6a28020028020c1100002104200341106a240020040f0b2000280218200120022000411c6a28020028020c1100002104200341106a240020040f0b200b21074100210b0c010b200b41016a4101762107200b410176210b0b2003410036020c024002402000280204220441ff004b0d00200320043a000c4101210a0c010b0240200441ff0f4b0d0020032004413f71418001723a000d20032004410676411f7141c001723a000c4102210a0c010b0240200441ffff034b0d0020032004413f71418001723a000e20032004410676413f71418001723a000d20032004410c76410f7141e001723a000c4103210a0c010b20032004413f71418001723a000f2003200441127641f001723a000c20032004410676413f71418001723a000e20032004410c76413f71418001723a000d4104210a0b417f21040240024002400340200441016a2204200b4f0d01200041186a2802002003410c6a200a2000411c6a28020028020c110000450d000c020b0b200041186a220b280200200120022000411c6a220028020028020c110000450d010b200341106a240041010f0b417f210402400340200441016a220420074f0d01200b2802002003410c6a200a200028020028020c110000450d000b200341106a240041010f0b200341106a240041000f0b2000280218200120022000411c6a28020028020c1100002104200341106a240020040bd00901067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b21074180022108024003400240200820014f0d00200020086a2c000041bf7f4a0d020b2008417f6a21064100210520084101460d02200720086a21092006210820094101470d000c020b0b41002105200821060b200420063602142004200036021020044100410520051b36021c20044188f0c10041ae94c00020051b360218024002400240024002400240024002400240200220014b22080d00200320014b0d00200220034b0d02024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0120022001460d01200141016a2109024003400240200220014f0d00200020026a22062c000041bf7f4a0d020b2002417f6a2108024020024101460d0020092002462106200821022006450d010b0b200020086a2206200020016a2202470d040c050b200221082006200020016a2202460d040c030b20042002200320081b360228200441c8006a41146a4101360200200441c8006a410c6a4101360200200441306a41146a4103360200200441306a410c6a41033602002004410336024c200441b0b3c10036023820044103360234200441d891c2003602302004200441186a3602582004200441106a3602502004200441286a3602482004200441c8006a360240200441306a41f091c2001071000b2000200222086a2206200020016a2202470d010c020b200441e4006a4101360200200441c8006a41146a4101360200200441c8006a410c6a4103360200200441306a41146a4104360200200441306a410c6a41043602002004410336024c200441b494c000360238200441043602342004418092c2003602302004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a3602482004200441c8006a360240200441306a41a092c2001071000b4101210141002109024020062c000022064100480d002004200641ff0171360224200441286a21020c050b200221010240200020086a220041016a2002460d00200041026a2101200041016a2d0000413f7121090b2006411f712100200641ff017141e001490d014100210520022107024020012002460d00200141016a210720012d0000413f7121050b20052009410674722101200641ff017141f001490d0241002106024020072002460d0020072d0000413f7121060b20014106742000411274418080f00071722006722206418080c400470d030b41b092c200104f000b200920004106747221060c010b20012000410c747221060b2004200636022441012101200441286a21022006418001490d00410221012006418010490d0041034104200641808004491b21010b200420083602282004200120086a36022c200441ec006a4101360200200441e4006a4101360200200441c8006a41146a4106360200200441c8006a410c6a4107360200200441306a41146a4105360200200441306a410c6a4105360200200420023602582004410336024c200441c495c00036023820044105360234200441c892c2003602302004200441186a3602682004200441106a3602602004200441246a3602502004200441206a3602482004200441c8006a360240200441306a41f092c2001071000b950101017f230041306b22022400200241086a410c6a41083602002002410836020c200220003602082002200041046a3602102001411c6a2802002100200128021821012002412c6a4102360200200241186a410c6a41023602002002418489c2003602202002410236021c2002418093c2003602182002200241086a36022820012000200241186a106d2101200241306a240020010bad0b03037f017e047f410121020240200128021841272001411c6a2802002802101102000d00410221020240024002400240024002400240024002400240024002400240024002402000280200220341776a2200411e4b0d0041f4002104024020000e1f0f0002020302020202020202020202020202020202020202020d020202020d0f0b41ee0021040c030b200341dc00460d0b0b2003108001450d02200341017267410276410773ad4280808080d0008421050c030b41f20021040b0c0a0b0240024002400240200341ffff034b0d0020034180fe037141087621064198a4c000210041002107200341ff0171210402400340200041026a2108200720002d000122026a21090240024020002d000022002006470d0020092007490d09200941b0024f0d0a200741e8a4c0006a210003402002450d022002417f6a210220002d00002107200041016a210020072004470d000c080b0b200020064b0d022009210720082100200841e8a4c000470d010c020b2009210720082100200841e8a4c000470d000b0b200341ffff037121074197a7c0002102410121000340200241016a21040240024020022d000022094118744118752208417f4c0d0020042102200720096b220741004e0d010c040b200441d3a9c000460d0b200241016a2104200241026a21022007200841ff007141087420042d0000726b22074100480d030b20004101732100200241d3a9c000470d000c020b0b200341ffff074b0d0120034180fe0371410876210641d3a9c000210041002107200341ff0171210402400340200041026a2108200720002d000122026a21090240024020002d000022002006470d0020092007490d0a2009419f014f0d0b20074195aac0006a210003402002450d022002417f6a210220002d00002107200041016a210020072004470d000c070b0b200020064b0d02200921072008210020084195aac000470d010c020b200921072008210020084195aac000470d000b0b200341ffff0371210741b3abc0002102410121000340200241016a21040240024020022d000022094118744118752208417f4c0d0020042102200720096b220741004e0d010c030b200441b0aec000460d0b200241016a2104200241026a21022007200841ff007141087420042d0000726b22074100480d020b20004101732100200241b0aec000470d000b0b410121022000410171450d010c090b20034190fc476a4190fc0b490d00200341e28b746a41e28d2c490d002003419fa8746a419f18490d00200341dee2746a410e490d00200341feffff0071419ef00a460d00200341a9b2756a4129490d00200341cb91756a410a4d0d00410121020c080b200341017267410276410773ad4280808080d0008421050b410321020c070b20072009107a000b200941af021076000b20072009107a000b2009419e011076000b41b092c200104f000b41b092c200104f000b0b200321040b200141186a21072001411c6a21030340024002400240024002400240024020024101460d00024020024102460d0020024103470d062005422088a741ff0171417f6a220241044b0d06024020020e050006040503000b200542ffffffff8f6083210541fd002100410321020c070b41dc002100410121020c060b41002102200421000c050b200542ffffffff8f60834280808080c00084210541dc002100410321020c040b200542ffffffff8f608342808080802084210541fb002100410321020c030b200542ffffffff8f608342808080803084210541f5002100410321020c020b20042005a72209410274411c7176410f712202413072200241d7006a2002410a491b210002402009450d002005427f7c42ffffffff0f83200542808080807083842105410321020c020b200542ffffffff8f6083428080808010842105410321020c010b200141186a28020041272001411c6a28020028021011020021020c020b200728020020002003280200280210110200450d000b41010f0b20020b960201017f024002400240024002400240024020004180104f0d00200041037641f8ffffff017141b093c2006a21010c010b02402000418080044f0d00200041067641606a220141e0074f0d02200141c895c2006a2d0000220141c9004b0d032001410374419098c0006a21010c010b2000410c7641706a22014180024f0d03200141a89dc2006a2d00004106742000410676413f7172220141ff034b0d04200141e09cc0006a2d0000220141364b0d05200141037441e0a0c0006a21010b200129030042012000413f71ad86834200520f0b41a89fc200200141e007104e000b41b89fc200200141ca00104e000b41c89fc2002001418002104e000b41d89fc2002001418004104e000b41e89fc20020014137104e000bbb0201037f23004180016b220224000240024002400240200128020022034110710d0020034120710d01200020011058210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441d7006a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141ac94c0004102200220006a4180016a410020006b1077210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441376a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141ac94c0004102200220006a4180016a410020006b1077210020024180016a240020000f0b2003418001107a000b2003418001107a000b08002000200110580b1c00200128021841a8afc000410b2001411c6a28020028020c1100000b1c00200128021841b3afc000410e2001411c6a28020028020c1100000b2601017f20002802002201280200200128020420002802042802002000280208280200107d000baa0603057f027e017f02400240024002400240024002402002450d00200241796a4100200241074b1b210341002104034002400240024002400240200120046a22052d0000220641187441187522074100480d002005410371450d01200441016a22042002490d050c060b4280808080102108200641e68fc0006a2d000022054104460d0120054103460d0220054102470d06200441016a220520024f0d084280808080802021094280808080102108200120056a2d000041c00171418001460d030c0b0b0240200420034f0d000340200120046a220541046a280200200528020072418081828478710d01200441086a22042003490d000b0b0240200420024f0d000340200120046a2c00004100480d01200441016a22042002490d000b0b20042002490d030c040b42002109200441016a220520024f0d07200120056a2d000021050240024020074170470d00200541f0006a41ff0171412f4d0d010b0240200541ff0171220641bf014b0d002007410f6a41ff017141024b0d0020054118744118754100480d010b2006418f014b0d0520074174470d05200541187441187541004e0d050b200441026a220520024f0d07200120056a2d000041c00171418001470d0542002108200441036a220520024f0d09200120056a2d000041c00171418001460d010c080b42002109200441016a220520024f0d06200120056a2d000021050240024020074160470d00200541607141ff017141a001460d010b0240200541ff0171220641bf014b220a0d002007411f6a41ff0171410b4b0d0020054118744118754100480d010b02402006419f014b0d002007416d470d0020054118744118754100480d010b200a0d04200741fe017141ee01470d04200541187441187541004e0d040b42002108200441026a220520024f0d08200120056a2d000041c00171418001470d040b200541016a22042002490d000b0b20002001360204200041086a2002360200200041003602000f0b4280808080802021090c040b428080808080c000210942808080801021080c030b420021090b420021080c010b428080808080e000210942808080801021080b200020092008842004ad84370204200041013602000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a106d2100200241206a240020000b3201017f0240410810002202450d0020004288808080800137020420002002360200200220013700000f0b410841011019000bce0101047f024002400240024002400240200141046a2802002202200141086a28020022036b41044f0d00200341046a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d030b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20003600000f0b1018000b200341011019000b4b00200041ddf5c10036020420004100360200200041206a41023602002000411c6a41a8a0c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b340020004182a0c10036020420004100360200200041146a4104360200200041106a41a0a3c200360200200041086a420e3702000b4b00200041ddf5c10036020420004100360200200041206a41023602002000411c6a41b0a5c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000bfe0601067f02400240024002400240024002400240200141c0004f0d0020022001410274102420010d010c020b024002400240024002400240024002400240024002400240024002402001418080014f0d00200241046a2802002203200241086a28020022046b41024f0d01200441026a22052004490d1020034101742204200520052004491b22044100480d102003450d0520022802002106200410002205450d122005200620042003200320044b1b10f8021a200610010c060b20014180808080044f0d01200241046a2802002203200241086a28020022046b41044f0d02200441046a22052004490d0f20034101742204200520052004491b22044100480d0f2003450d0720022802002106200410002205450d122005200620042003200320044b1b10f8021a200610010c080b200228020021050c050b200241031024200241046a2802002203200241086a28020022046b41044f0d01200441046a22052004490d0d20034101742204200520052004491b22044100480d0d2003450d0820022802002106200410002205450d112005200620042003200320044b1b10f8021a200610010c090b200228020021050c060b200228020021050c080b200410002205450d0c0b20022005360200200241046a2004360200200241086a28020021040b200241086a200441026a360200200520046a20014102744101723b00000c060b200410002205450d0a0b20022005360200200241046a2004360200200241086a28020021040b200241086a200441046a360200200520046a20014102744102723600000c030b200410002205450d080b20022005360200200241046a2004360200200241086a28020021040b200241086a200441046a360200200520046a20013600000b200020016a2107200241086a2105200241046a210603400240024002400240200628020020052802002201470d00200141016a22042001490d0620014101742203200420042003491b22034100480d062001450d0120022802002108200310002204450d072004200820032001200120034b1b10f8021a200810010c020b200228020021040c020b200310002204450d050b2002200436020020062003360200200528020021010b2005200141016a360200200420016a20002d00003a0000200041016a2201210020072001470d000b0b0f0b1018000b200341011019000b200441011019000b200441011019000b200441011019000bea0601067f02400240024002400240024002402001413f4b0d00200220014102741024200241046a2103200241086a21040c010b024002400240024002400240024002400240024002400240024002402001418080014f0d00200241046a22032802002205200241086a220428020022066b41024f0d01200641026a22072006490d0f20054101742206200720072006491b22064100480d0f2005450d0520022802002108200610002207450d112007200820062005200520064b1b10f8021a200810010c060b20014180808080044f0d01200241046a22032802002205200241086a220428020022066b41044f0d02200641046a22072006490d0e20054101742206200720072006491b22064100480d0e2005450d0720022802002108200610002207450d112007200820062005200520064b1b10f8021a200810010c080b200228020021070c050b200241031024200241046a22032802002205200241086a220428020022066b41044f0d01200641046a22072006490d0c20054101742206200720072006491b22064100480d0c2005450d0820022802002108200610002207450d102007200820062005200520064b1b10f8021a200810010c090b200228020021070c060b200228020021070c080b200610002207450d0b0b20022007360200200241046a2006360200200241086a28020021060b2004200641026a360200200720066a20014102744101723b00000c060b200610002207450d090b20022007360200200241046a2006360200200241086a28020021060b2004200641046a360200200720066a20014102744102723600000c030b200610002207450d070b20022007360200200241046a2006360200200241086a28020021060b2004200641046a360200200720066a20013600000b024002400240024020032802002207200428020022036b20014f0d00200320016a22062003490d0420074101742203200620062003491b22034100480d042007450d0120022802002105200310002206450d052006200520032007200720034b1b10f8021a200510010c020b200228020021060c020b200310002206450d030b20022006360200200241046a2003360200200241086a28020021030b2004200320016a360200200620036a2000200110f8021a0f0b1018000b200341011019000b200641011019000b200641011019000b200641011019000b13002000410236020420004188a7c2003602000b130020004105360204200041a0a8c2003602000bcd1b05037f027e057f047e027f230041e0006b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a2203410b4b0d0002400240024020030e0c0008050602090a070b040c01000b2002200141086a10920120004101360200200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b4102210320012d000422044102460d0b4103210320044103470d2d200241186a200141046a220141196a290000370300200241106a200141116a290000370300200241086a200141096a290000370300200220012900013703000c0c0b2002200141086a10930120004105360200200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b200141086a2903004202520d2c20004100360200200041086a4202370300200041106a200141106a290300370300200241e0006a24000f0b200141086a280200417e6a220341044b0d2c024020030e05001b191a18000b41012103200141386a2903002105200141306a29030021062001410c6a2d00004101470d1f0c200b41022103200141086a22042d000022074102460d0f4103210320074103460d0e4104210320074104470d2c20042d000141004721010c100b200141086a2d0000417e6a220841094b0d2c4102210341002109024020080e0a35001d211b242522261c350b2001410c6a28020022094108762107410321030c220b20012d000422034102460d074103210420034103470d2c200241d2006a200141046a220341036a2d00003a0000200241086a200141186a2900003703002002410d6a2001411d6a290000370000200220032f00013b01502002200141106a290000370300200141256a2d00004100472107200141286a280200210a2001410c6a2800002103200141086a280000210b0c080b41022104200141086a28020022034102460d0820034103470d2c410121072001410c6a2d00004101470d0e0c0f0b2002200141086a10940120004106360200200041c0006a200241386a290300370300200041386a200241306a290300370300200041306a200241286a290300370300200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b2002200141086a10950120004107360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b20012802044102470d2a2002200141086a102b2000428980808020370300200041086a2002290200370200200041106a200241086a280200360200200241e0006a24000f0b41022104200141086a22032d000022074102460d054103210420074103470d2a200141306a2903002105200141286a2903002106200141386a290300210c200241c0006a2001410c6a102b200241d0006a200141186a102b2002410b6a200241c0006a41086a280200360000200241176a200241d0006a41086a280200360000200220022903403700032002200229035037000f4200210d4200210e0c060b200241d0006a200141086a102b2002410b6a200241d0006a41086a280200360000200220022903503700030b20002002290300370005200020033a0004200020022f00503b00252000410c3602002000410d6a200241086a290300370000200041156a200241106a2903003700002000411d6a200241186a290300370000200041276a200241d2006a2d00003a0000200241e0006a24000f0b200141086a280200210b41d00010002203450d2820032001410c6a280200109101410221040b200020022f01503b0005200020043a0004200020073a0025200041083602002000410c6a2003360200200041086a200b360200200041106a2002290300370200200041286a200a360200200041076a200241d2006a2d00003a0000200041186a200241086a2903003702002000411d6a2002410d6a290000370000200241e0006a24000f0b410121072001410c6a2d00004101470d070c080b200241176a200341186a290000370000200241106a200341116a290000370300200241086a200341096a29000037030020022003290001370300200141c0006a290300210e200141386a290300210c200141c8006a290300210f200141286a3100002106200241d0006a2001412c6a102b200241d0006a41086a3502004220862002290350220d4220888421052006200d4220868421064200210d0b200020022903003700092000410b360200200041c0006a200e370300200041386a200d200c84370300200041306a2005370300200041286a2006370300200041086a20043a0000200041c8006a200f370300200041116a200241086a290300370000200041196a200241106a290300370000200041206a200241176a290000370000200241e0006a24000f0b200141106a29030021050c010b200241d4006a200441066a2f00003b0100200241086a200141206a290000370300200241106a200141286a2d00003a00002002200441026a2800003602502002200141186a290000370300200141106a2900002105200141096a2d000021010b200020013a00092000200228025036010a20004103360200200041086a20033a0000200041106a2005370300200041186a20022903003703002000410e6a200241d4006a2f01003b0100200041206a200241086a290300370300200041286a200241106a290300370300200241e0006a24000f0b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722103200141246a280000210a200141206a280000210b200141186a2900002106200141146a2800002110410021070b200141c8006a290300210c200141c0006a290300210d410321040c020b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722103200141246a280000210a200141206a280000210b200141186a2900002106200141146a2800002110410021070b0b200020033b000d200041023602002000410f6a20034110763a0000200041c8006a200c370300200041c0006a200d370300200041286a2005370200200041246a200a360200200041206a200b360200200041186a2006370200200041146a20103602002000410c6a20073a0000200041086a2004360200200041386a200141386a290300370300200041306a200141306a290300370300200041106a200141106a280000360200200241e0006a24000f0b2001410c6a28020022034108762104410621010c030b200241106a200141206a2903003703002002200141186a2903003703082002200141106a2802003602002001410c6a28020022034108762104200141286a290300210c410421010c080b2001410c6a28020022034108762104410521010c010b2002200141186a2903003703082002200141106a29030037030041032101410021030b0c050b2001410c6a28020022094108762107200141186a2903002106200141206a2802002110200141106a2903002205a7210b2005422088a7210a410621030c180b2001410c6a28020022094108762107410b21030c060b410121092001410c6a2d00004101470d090c0a0b200141286a3500002001412c6a31000042208684210c2001410d6a2f00002001410f6a2d0000411074722104200141246a2800002107200141206a280000210a200141186a290000210d200141146a280000210b410021030b200220073602142002200a3602102002200d3703082002200b3602042002200141106a280000360200410221010b2000410a360200200041386a2005370300200041306a2006370300200041086a2001360200200041106a2002290300370300200041286a200c3703002000410c6a2004410874200341ff017172360200200041186a200241086a290300370300200041206a200241106a290300370300200241e0006a24000f0b2001410c6a28020022094108762107410521030c010b2001410c6a28020022094108762107410921030b0c0f0b200141106a2903002205a7210b2005422088a7210a410721030c0e0b200141106a2903002205a7210b2005422088a7210a410821030c0d0b41002109200141096a2d00004100472111410a21030c0e0b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722107200141246a2800002104200141206a2800002110200141186a2900002106200141146a280000210a410021090b200141106a280000210b410421030c0b0b41d8ccc200104f000b41a881c300104f000b41c0ccc200104f000b41acd5c200104f000b41a8ccc200104f000b418cabc200104f000b41c4aec300104f000b4180e8c200104f000b4188a8c200104f000b41d00041081019000b0b0b200020113a0009200020022f01003b010a20004104360200200041186a2006370300200041086a20033a0000200041286a2005370200200041246a2004360200200041206a20103602002000410c6a2007410874200941ff017172360200200041106a200aad422086200bad84370300200241e0006a24000bbb0503037f017e057f230041206b220224000240024002400240024002402001280200417e6a220341054b0d0002400240024002400240024020030e06000402030105000b200241086a200141046a102b200041023602002000410c6a200241106a28020036020020002002290308370204200241206a24000f0b200241086a200141046a102b200041063602002000410c6a200241106a28020036020020002002290308370204200241206a24000f0b200241086a200141046a102b200041043602002000410c6a200241106a28020036020020002002290308370204200241206a24000f0b20004105360200200041086a200141086a290300370300200241206a24000f0b20004103360200200241206a24000f0b2001410c6a2802002204ad42187e2205422088a70d012005a72206417f4c0d0120012802042101024002402006450d002006100022070d01200641041019000b410421070b200220012001200441186c6a102e024002400240200420022802042208200228020022036b41186e22014f0d0020044101742209200120012009491b220aad42187e2205422088a70d052005a722014100480d052004450d01200110002209450d062009200720012006200620014b1b10f8021a2007100120032008470d020c070b2004210a2007210920032008470d010c060b200110002209450d0420032008460d050b200241086a410c6a210641002104200921010340200241086a2003102b20062003410c6a102b200141106a200241086a41106a290300370200200141086a200241086a41086a29030037020020012002290308370200200441016a2104200141186a2101200341186a22032008470d000c060b0b41f089c300104f000b102c000b1018000b200141041019000b410021040b20002009360204200041073602002000410c6a2004360200200041086a200a360200200241206a24000bd70201017f02400240024020012d0000417e6a220241054b0d0002400240024002400240024020020e06000402030105000b41d00010002202450d062002200141046a280200109c02200041046a2002360200200041106a200141106a290300370300200041086a200141086a290300370300200041023a00000f0b200041046a200141046a280200360200200041063a00000f0b200020012d00013a0001200041046a200141046a280200360200200041043a00000f0b41d00010002202450d042002200141046a280200109c02200041046a2002360200200041086a200141086a290300370300200020012d00013a0001200041053a00000f0b200041046a200141046a280200360200200041033a00000f0b200041086a200141086a290300370300200041046a200141046a280200360200200041073a00000f0b41a8e6c200104f000b41d00041081019000b41d00041081019000bb00901047f230041206b22022400024002402001280200417e6a220341084b0d000240024002400240024002400240024002400240024002400240024002400240024020030e09000502030106070408000b2001410c6a2802002203417f4c0d11200128020421042003450d0e2003100022050d0f200341011019000b4101210320012d00044101470d07200141086a28020021040c080b2000410436020020002001280204360204200241206a24000f0b2000410536020020002001280204360204200241206a24000f0b20004109360200200041086a200141086a290300370300200241206a24000f0b2001280204210441012103200141086a22052d00004101470d052001410c6a28020021050c060b2000410736020020002001280204360204200241206a24000f0b4101210320012d00044101470d05200141086a28020021010c060b2000410a360200200041086a200141086a290300370300200241206a24000f0b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290000370300200141086a2800002104410021030b200020033a0004200020022f011c3b0005200041086a20043602002000410c6a2002290300370200200041386a200141386a290300370300200041306a200141306a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a280200360200200141286a280200210120004106360200200041286a2001360200200241206a24000f0b2002411e6a200541036a2d00003a0000200241086a200141186a290000370300200241106a200141206a290000370300200241186a200141286a2d00003a0000200220052f00013b011c2002200141106a2900003703002001410c6a2800002105410021030b20002004360204200020022f011c3b0009200041086a20033a00002000410c6a2005360200200041106a20022903003702002000410b6a2002411e6a2d00003a0000200041186a200241086a290300370200200041206a200241106a290300370200200041286a200241186a2802003602002000412c6a2001412c6a29020037020020004103360200200241206a24000f0b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290000370300200141086a2800002101410021030b200020022f011c3b0005200020033a000420004108360200200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a280200360200200241206a24000f0b410121050b20052004200310f80221042000410c6a2003360200200041086a20033602002000200436020420004102360200200041106a200141106a280200360200200241206a24000f0b41d09fc300104f000b102c000bd71c05047f027e067f047e017f230041e0006b22022400024002400240024002400240024002400240024002400240024002400240024020012d0000417e6a220341044b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e050004020301000b41d00010002203450d33200141046a2802002201280200417f6a2204410b4b0d06024020040e0c000c090a060d0e0b0f081005000b2002200141086a10920120034101360200200341106a200241086a290300370300200320022903003703080c410b200041063a0000200041086a200141086a290300370300200241e0006a24000f0b200041043a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200241e0006a24000f0b200041053a0000200041086a200141086a290300370300200241e0006a24000f0b200041033a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00004100473a0000200241e0006a24000f0b4102210420012d000422054102460d0b4103210420054103470d2f200241186a200141046a220141196a290000370300200241106a200141116a290000370300200241086a200141096a290000370300200220012900013703000c0c0b2002200141086a10930120034105360200200341186a200241106a290300370300200341106a200241086a290300370300200320022903003703080c3b0b200141086a2903004202520d2e20034202370308200341003602002003200141106a2903003703100c3a0b200141086a280200417e6a220441044b0d2e024020040e05001b191a18000b41012104200141386a2903002106200141306a29030021072001410c6a2d00004101470d1f0c200b41022104200141086a22052d000022084102460d0f4103210420084103460d0e4104210420084104470d2e20052d000141004721010c100b200141086a2d0000417e6a220941094b0d2e4102210a4100210b024020090e0a37001d211b242522261c370b2001410c6a280200220b41087621054103210a0c220b20012d000422044102460d074103210520044103470d2e200241d2006a200141046a220441036a2d00003a0000200241086a200141186a2900003703002002410d6a2001411d6a290000370000200220042f00013b01502002200141106a290000370300200141256a2d00004100472108200141286a280200210c2001410c6a2800002104200141086a280000210d0c080b41022105200141086a28020022044102460d0820044103470d2e410121082001410c6a2d00004101470d0e0c0f0b2002200141086a10940120034106360200200341c0006a200241386a290300370300200341386a200241306a290300370300200341306a200241286a290300370300200341286a200241206a290300370300200341206a200241186a290300370300200341186a200241106a290300370300200341106a200241086a290300370300200320022903003703080c340b2002200141086a10950120034107360200200341286a200241206a290300370300200341206a200241186a290300370300200341186a200241106a290300370300200341106a200241086a290300370300200320022903003703080c330b20012802044102470d2c2002200141086a102b200342898080802037030020032002290200370208200341106a200241086a2802003602000c320b41022105200141086a22042d000022084102460d054103210520084103470d2c200141306a2903002106200141286a2903002107200141386a290300210e200241c0006a2001410c6a102b200241d0006a200141186a102b2002410b6a200241c0006a41086a280200360000200241176a200241d0006a41086a280200360000200220022903403700032002200229035037000f4200210f420021100c060b200241d0006a200141086a102b2002410b6a200241d0006a41086a280200360000200220022903503700030b20032002290300370005200320043a0004200320022f00503b00252003410c3602002003410d6a200241086a290300370000200341156a200241106a2903003700002003411d6a200241186a290300370000200341276a200241d2006a2d00003a00000c2f0b200141086a280200210d41d00010002204450d2a20042001410c6a280200109101410221050b200320022f01503b0005200320053a00042003200436020c2003200d36020820032002290300370210200320083a00252003200c360228200320022f01403b012620034108360200200341076a200241d2006a2d00003a0000200341186a200241086a2903003702002003411d6a2002410d6a2900003700000c2d0b410121082001410c6a2d00004101470d070c080b200241176a200441186a290000370000200241106a200441116a290000370300200241086a200441096a29000037030020022004290001370300200141c0006a2903002110200141386a290300210e200141c8006a2903002111200141286a3100002107200241d0006a2001412c6a102b200241d0006a41086a3502004220862002290350220f4220888421062007200f4220868421074200210f0b2003200737032820032002290300370009200320053a0008200320113703482003410b360200200341c0006a20103703002003200f200e84370338200341306a2006370300200341116a200241086a290300370000200341196a200241106a290300370000200341206a200241176a2900003700000c2a0b200141106a29030021060c010b200241d4006a200541066a2f00003b0100200241086a200141206a290000370300200241106a200141286a2d00003a00002002200541026a2800003602502002200141186a290000370300200141106a2900002106200141096a2d000021010b200320013a0009200320043a00082003200228025036010a2003200637031020032002290300370318200341033602002003410e6a200241d4006a2f01003b0100200341206a200241086a290300370300200341286a200241106a2903003703000c270b200141286a3500002001412c6a3100004220868421062001410d6a2f00002001410f6a2d0000411074722104200141246a280000210c200141206a280000210d200141186a2900002107200141146a2800002112410021080b200141c8006a290300210e200141c0006a290300210f410321050c020b200141286a3500002001412c6a3100004220868421062001410d6a2f00002001410f6a2d0000411074722104200141246a280000210c200141206a280000210d200141186a2900002107200141146a2800002112410021080b0b200320043b000d2003200f370340200320063702282003200c3602242003200d3602202003200737021820032012360214200320083a000c20032005360208200341023602002003410f6a20044110763a0000200341c8006a200e370300200341386a200141386a2903003703002003200141306a2903003703302003200141106a2800003602100c220b2001410c6a28020022044108762105410621010c030b200241106a200141206a2903003703002002200141186a2903003703082002200141106a2802003602002001410c6a28020022044108762105200141286a290300210e410421010c080b2001410c6a28020022044108762105410521010c010b2002200141186a2903003703082002200141106a29030037030041032101410021040b0c050b2001410c6a280200220b4108762105200141186a2903002107200141206a280200210d200141106a2903002206a7210c2006422088a721084106210a0c1a0b2001410c6a280200220b4108762105410b210a0c060b4101210b2001410c6a2d00004101470d090c0a0b200141286a3500002001412c6a31000042208684210e2001410d6a2f00002001410f6a2d0000411074722105200141246a2800002108200141206a280000210c200141186a290000210f200141146a280000210d410021040b200220083602142002200c3602102002200f3703082002200d3602042002200141106a280000360200410221010b2003200737033020032001360208200320022903003703102003200e3703282003410a360200200341386a200637030020032005410874200441ff01717236020c200341186a200241086a290300370300200341206a200241106a2903003703000c170b2001410c6a280200220b41087621054105210a0c010b2001410c6a280200220b41087621054109210a0b0c110b200141106a2903002206a7210c2006422088a721084107210a0c100b200141106a2903002206a7210c2006422088a721084108210a0c0f0b4100210b200141096a2d00004100472112410a210a0c100b200141286a3500002001412c6a3100004220868421062001410d6a2f00002001410f6a2d0000411074722105200141246a2800002104200141206a280000210d200141186a2900002107200141146a28000021084100210b0b200141106a280000210c4104210a0c0d0b41c081c300104f000b41d00041081019000b41d8ccc200104f000b41a881c300104f000b41c0ccc200104f000b41acd5c200104f000b41a8ccc200104f000b418cabc200104f000b41c4aec300104f000b4180e8c200104f000b4188a8c200104f000b41d00041081019000b0b0b200320123a00092003200a3a000820032006370228200320043602242003200d360220200320022f01003b010a20034104360200200341186a200737030020032005410874200b41ff01717236020c20032008ad422086200cad843703100b200041023a0000200041046a2003360200200241e0006a24000bce0603067f037e037f230041306b22022400200241003a0020200241206a2001280200220320012802042204410047220510f8021a0240024002400240024020042005490d00200141046a200420056b22063602002001200320056a2205360200024002402004450d000240024020022d002022034103712204450d00024020044101460d0020044102470d02200241003a001e200241003b011c2002411c6a200520064103200641034922071b220410f8021a200141046a200620046b3602002001200520046a36020020070d0320022f011c20022d001e41107472410874200372410276ad21080c080b200241003a0020200241206a20052006410047220410f8021a20062004490d06200141046a200620046b3602002001200520046a3602002006450d0220022d002041087420037241fcff0371410276ad21080c070b2003410276ad21080c060b0240024020034102762204450d00024020044104460d002004410c470d024200210a2002420037032820024200370320200241206a200520064110200641104922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d04200241286a2903002109200229032021084201210a0c090b4200210a20024200370320200241206a200520064108200641084922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d03200229032021080c070b20024100360220200241206a200520064104200641044922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d01200235022021080c060b200441046a220b41104b0d00200141046a210c200241106a210d4200210842002109410021030340200241003a0020200241206a20052006410047220410f8021a20062004490d04200c200620046b22073602002001200520046a22053602002006450d01200241086a20023100204200200341037441f8007110fe02200d2903002009842109200229030820088421084201210a20072106200341016a22042103200441ff0171200b490d000c070b0b4200210a0b0c040b20052004107a000b20042006107a000b20042006107a000b420021094201210a0b200020083703082000200a370300200041106a2009370300200241306a24000bc00503057f027e037f230041106b22022400200241003a0008200241086a2001280200220320012802042204410047220510f8021a02400240024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002402004450d000240024020022d000822044103712203450d002004ad2107024020034101460d0020034102470d02200241003a0006200241003b0104200241046a200520064103200641034922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d0320023301042002310006421086844208862007844202882107420121080c050b200241003a0008200241086a20052006410047220410f8021a20062004490d07200141046a200620046b3602002001200520046a3602002006450d0220023100084208862007844202882107420121080c040b2004410276ad2107420121080c030b0240024020044102762204450d0020044104470d014200210820024200370308200241086a200520064108200641084922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d0320022903082107420121080c040b20024100360208200241086a200520064104200641044922031b220410f8021a200141046a200620046b3602002001200520046a36020020030d0120023502082107420121080c030b200441046a220941084b0d0042002107200141046a210a410021030340200241003a0008200241086a20052006410047220410f8021a20062004490d05200a200620046b220b3602002001200520046a22053602002006450d0120023100082003410374413871ad86200784210742012108200b2106200341016a22042103200441ff01712009490d000c030b0b420021080b0b2000200737030820002008370300200241106a24000f0b20052004107a000b20042006107a000b20042006107a000bd20603047f037e037f230041206b22022400200241003a001020012802002001280204200241106a410120012802081004210320012001280208200341016a220341014b6a220436020802400240024020034102490d000240024002400240024020022d001022054103712203450d0020034101460d0120034102470d0220024100360210200220053a0010200141086a220341002001280200200141046a280200200241106a41017241032004100422012001417f461b22014103200141034922011b20032802006a36020020010d052002280210410276ad21060c030b2005410276ad21060c020b200241003b0110200220053a00102001280200200141046a280200200241106a4101724101200410042103200141086a22012001280200200341016a220141014b6a36020020014102490d0320022f0110410276ad21060c010b0240024020054102762203450d0020034104460d012003410c470d03420021072002420037031820024200370310200141086a220341002001280200200141046a280200200241106a41102004100422012001417f461b22014110200141104922011b20032802006a36020020010d05200241106a41086a290300210820022903102106420121070c060b200141046a280200210320024100360210200141086a2205410020012802002003200241106a41042004100422012001417f461b22014104200141044922011b20052802006a36020020010d03200235021021060c010b4200210720024200370310200141086a220341002001280200200141046a280200200241106a41082004100422012001417f461b22014108200141084922011b20032802006a36020020010d03200229031021060b42002108420121070c030b200341046a220941104b0d00200141046a210a200141086a21054200210642002108410021030340200241003a00102001280200200a280200200241106a410120041004210420052005280200200441016a220b41014b6a2204360200200b4102490d01200220023100104200200341037441f8007110fe02200241086a29030020088421082002290300200684210642012107200341016a220341ff01712009490d000c030b0b420021070b0b2000200637030820002007370300200041106a2008370300200241206a24000bbd0503047f027e037f230041106b22022400200241003a000820012802002001280204200241086a410120012802081004210320012001280208200341016a220441014b6a220336020802400240024020044102490d0002400240024020022d000822054103712204450d0020044101460d0120044102470d0220024100360208200220053a0008200141086a220441002001280200200141046a280200200241086a41017241032003100422012001417f461b22014103200141034922011b20042802006a36020020010d032002280208410276ad2106420121070c050b2005410276ad2106420121070c040b200241003b0108200220053a00082001280200200141046a280200200241086a4101724101200310042103200141086a22012001280200200341016a220141014b6a36020020014102490d0120022f0108410276ad2106420121070c030b0240024020054102762204450d0020044104470d014200210720024200370308200141086a220441002001280200200141046a280200200241086a41082003100422012001417f461b22014108200141084922011b20042802006a36020020010d0320022903082106420121070c040b200141046a280200210420024100360208200141086a2205410020012802002004200241086a41042003100422012001417f461b22014104200141044922011b20052802006a36020020010d0120023502082106420121070c030b200441046a220841084b0d0042002106200141046a2109200141086a2105410021040340200241003a000820012802002009280200200241086a410120031004210320052005280200200341016a220a41014b6a2203360200200a4102490d0120023100082004410374413871ad86200684210642012107200441016a220441ff01712008490d000c030b0b420021070b0b2000200637030820002007370300200241106a24000bdb0601057f230041e0006b2203240002402000423f56200142005220015022041b0d0020022000a74102741024200341e0006a24000f0b02400240024002400240024002400240024002400240024002400240024020004280800154410020041b450d00200241046a2802002205200241086a28020022046b41024f0d01200441026a22062004490d0a20054101742204200620062004491b22044100480d0a2005450d0420022802002107200410002206450d0d2006200720042005200520044b1b10f8021a200710010c050b200042808080800454410020041b450d01200241046a2802002205200241086a28020022046b41044f0d02200441046a22062004490d0920054101742204200620062004491b22044100480d092005450d0620022802002107200410002206450d0d2006200720042005200520044b1b10f8021a200710010c070b200228020021060c040b411020017920007942c0007c20014200521ba74103766b22044104490d082002200441027441736a10242003200137030820032000370300034020022000a7102420004208882001423886842100200142088821012004417f6a22040d000b200320003703002003200137030820032003360210200341e8bec000360214200020018450450d09200341e0006a24000f0b200228020021060c050b200410002206450d080b20022006360200200241046a2004360200200241086a28020021040b200241086a200441026a360200200620046a2000a74102744101723b0000200341e0006a24000f0b200410002206450d060b20022006360200200241046a2004360200200241086a28020021040b200241086a200441046a360200200620046a2000a7410274410272360000200341e0006a24000f0b1018000b41d4abc200104f000b200341c8006a41146a4100360200200341306a41146a4109360200200341306a410c6a410a360200200341186a41146a4103360200200341186a410c6a410336020020034188f0c1003602582003420137024c200341bcabc2003602482003410a360234200341b0b3c1003602202003410336021c200341d883c3003602182003200341c8006a3602402003200341146a3602382003200341106a3602302003200341306a360228200341186a41ecabc2001071000b200441011019000b200441011019000b900605027f027e017f027e027f230041a0016b22022400200028020021000240024002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0120054290ce005441002004501b0d0241272100200241186a21060340200241106a200520044290ce00420010fb022002200229031022072006290300220842f0b17f427f10fc02200241206a20006a2203417c6a200520022903007ca7220941e4006e220a410174419892c0006a2f00003b00002003417e6a200a419c7f6c20096a410174419892c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000b41e40021092007a7220341e4004e0d030c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d032001410141ac94c0004102200241206a20006a41800120006b10772100200241a0016a240020000f0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d032001410141ac94c0004102200241206a20006a41800120006b10772100200241a0016a240020000f0b4127210041e40021092005a7220341e400480d030b200241206a2000417e6a22006a2003200341ffff037120096e2209419c7f6c6a41ffff0371410174419892c0006a2f00003b0000200941094a0d030c040b2000418001107a000b2000418001107a000b2003220941094c0d010b200241206a2000417e6a22006a22032009410174419892c0006a2f00003b00000c010b200241206a2000417f6a22006a2203200941306a3a00000b200141014188f0c10041002003412720006b10772100200241a0016a240020000b9c0601057f230041e0006b2202240002402000423f560d0020012000a74102741024200241e0006a24000f0b0240024002400240024002400240024002400240024002400240024002402000428080015a0d00200141046a2802002203200141086a28020022046b41024f0d01200441026a22052004490d0a20034101742204200520052004491b22044100480d0a2003450d0420012802002106200410002205450d0d2005200620042003200320044b1b10f8021a200610010c050b20004280808080045a0d01200141046a2802002203200141086a28020022046b41044f0d02200441046a22052004490d0920034101742204200520052004491b22044100480d092003450d0620012802002106200410002205450d0d2005200620042003200320044b1b10f8021a200610010c070b200128020021050c040b4108200079a74103766b22044104490d082001200441027441736a102420022000370308034020012000a71024200042088821002004417f6a22040d000b200220003703082002200241086a360210200241e8bdc000360214200050450d09200241e0006a24000f0b200128020021050c050b200410002205450d080b20012005360200200141046a2004360200200141086a28020021040b200141086a200441026a360200200520046a2000a74102744101723b0000200241e0006a24000f0b200410002205450d060b20012005360200200141046a2004360200200141086a28020021040b200141086a200441046a360200200520046a2000a7410274410272360000200241e0006a24000f0b1018000b41a4abc200104f000b200241c8006a41146a4100360200200241306a41146a4109360200200241306a410c6a410b360200200241186a41146a4103360200200241186a410c6a410336020020024188f0c1003602582002420137024c200241bcabc2003602482002410b360234200241b0b3c1003602202002410336021c200241d883c3003602182002200241c8006a3602402002200241146a3602382002200241106a3602302002200241306a360228200241186a41c4abc2001071000b200441011019000b200441011019000bca0202027f017e23004180016b22022400200028020021000240024002400240200128020022034110710d002000290300210420034120710d0120042001107b210020024180016a240020000f0b200029030021044180012100024003402000450d01200220006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b0b20004181014f0d012001410141ac94c0004102200220006a41800120006b1077210020024180016a240020000f0b4180012100024003402000450d01200220006a417f6a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b0b20004181014f0d012001410141ac94c0004102200220006a41800120006b1077210020024180016a240020000f0b2000418001107a000b2000418001107a000bd70d06037f057e037f057e017f057e230041206b22012400200141106a41086a220242003703002001420037031041f8bec0004118200141106a1002200141086a200229030037030020012001290310370300411021030240024002400240024002400240024002400240200141104188f0c100410041001004417f460d0020014200370310410020014110200141106a41084100100422022002417f461b220241084922030d022001290310210420014200370310410020014110200141106a41082002410820031b2203100422022002417f461b220241074d0d022001290310210520014200370310410020014110200141106a41082002410820024108491b20036a2203100422022002417f461b220241074d0d022001290310210620014200370310410020014110200141106a41082002410820024108491b20036a2203100422022002417f461b220241074d0d022001290310210720014200370310410020014110200141106a41082002410820024108491b20036a2203100422022002417f461b220241074d0d02200129031021082001410036021020014110200141106a41042002410820024108491b20036a2202100441016a4105490d02200128021021092001410036021020014110200141106a4104200241046a100441016a4105490d02200128021021030c010b42012108418080042109420121074201210642012105420121040b200141106a41086a220242003703002001420037031041bef0c100411b200141106a1002200141086a220a20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d00200142003703182001420037031020014110200141106a411041001004220b417f460d06200b410f4d0d06200141186a290300210c2001290310210d0c010b4200210d4200210c0b20024200370300200142003703104190bfc0004111200141106a1002200a20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d002001410036021020014110200141106a41044100100441016a41044d0d052001280210210a0c010b41e400210a0b4200210e200141106a41086a220242003703002001420037031041a1bfc0004114200141106a1002200141086a20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d00200142003703182001420037031020014110200141106a4110410010042202417f460d072002410f4d0d07200141186a290300210e2001290310210f0c010b4215210f0b42002110200141106a41086a220242003703002001420037031041e7f5c1004114200141106a1002200141086a220b20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d00200142003703182001420037031020014110200141106a4110410010042211417f460d082011410f4d0d08200141186a2903002112200129031021130c010b42002113420021120b200242003703002001420037031041fbf5c1004114200141106a1002200b20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d00200142003703182001420037031020014110200141106a4110410010042202417f460d092002410f4d0d09200141186a2903002114200129031021100c010b420021140b200141106a41086a220242003703002001420037031041b5bfc0004114200141106a1002200141086a20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d002001420037031020014110200141106a41084100100441016a41084d0d03200129031021150c010b42870121150b200141106a41086a220242003703002001420037031041c9bfc0004116200141106a1002200141086a20022903003703002001200129031037030002400240200141104188f0c100410041001004417f460d002001420037031020014110200141106a41084100100441016a41084d0d04200129031021160c010b42af0121160b2000200d37033020002010370360200020133703502000200f3703402000200a360280012000200336022c2000200936022820002008370320200020073703182000200637031020002005370308200020043703002000201637037820002015370370200041386a200c370300200041e8006a2014370300200041d8006a2012370300200041c8006a200e370300200141206a24000f0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b02000be00401027f0240024002400240024002400240024002400240024002400240024020002802002201410b4b0d0020010e0c0d010d0d0d02030405060d070d0b20002d00044102470d0c2000410c6a280200450d0c200041086a28020010010f0b200041086a280200220141064b0d08024020010e070c0c000c0a0c0b0c0b200041106a280200450d0b2000410c6a28020010010f0b200041086a2d000022014105460d0520014102470d0a2000410c6a220028020010a001200028020010010f0b200041086a2802004102470d09200041106a280200450d092000410c6a28020010010f0b200041086a2d00004102470d082000410c6a220028020010a001200028020010010f0b20002d00044102470d072000410c6a220028020010a001200028020010010f0b20002802044102490d062000410c6a280200450d06200041086a28020010010f0b200041086a2d000022014102490d0520014102470d01200041306a280200450d052000412c6a28020010010f0b2000410c6a220028020010a001200028020010010f0b0240200041106a280200450d002000410c6a28020010010b2000411c6a280200450d03200041186a28020010010f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141186a2101200241686a22020d000b0b200041106a280200450d022000410c6a28020010010f0b200041106a280200450d012000410c6a28020010010f0b200041106a280200450d002000410c6a28020010010f0b0b1b002000200128020422012f01063602042000200141086a3602000b8f0801067f230041f0006b22022400200241003a0050200241d0006a2001280200220320012802042204410047220510f8021a0240024020042005490d00200141046a200420056b22063602002001200320056a2205360200024002402004450d0020022d0050220441f0014f0d01410121010c030b200041023a0000200241f0006a24000f0b02400240024002400240200441847e6a220441034b0d00024002400240024020040e0400010203000b200241003b0150200241d0006a20052006410220064102491b220410f8021a200141046a200620046b3602002001200520046a36020041012101200641014d0d0441ef01210420022f015041ef014b0d09200041023a0000200241f0006a24000f0b20024100360250200241d0006a20052006410420064104491b220410f8021a200141046a200620046b3602002001200520046a360200200641034d0d0441ffff03210441012101200228025041ffff034b0d08200041023a0000200241f0006a24000f0b200041023a0000200141046a20062006410420064104491b22006b3602002001200520006a360200200241f0006a24000f0b41002103200241d0006a2006412020064120491b22046a41004100412020046b2004411f4b1b10f7021a200241d0006a2005200410f8021a200141046a200620046b3602002001200520046a3602002006411f4d0d032002412c6a41026a200241d0006a41026a2d00003a0000200241186a200241df006a290000370300200241206a200241e7006a290000370300200241286a200241d0006a411f6a2d00003a0000200220022f00503b012c2002200229005737031020022800532104410121030c040b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b0b200241cc006a41026a22012002412c6a41026a2d00003a0000200241306a41086a2205200241106a41086a290300370300200241306a41106a2206200241106a41106a290300370300200241306a41186a2207200241106a41186a2d00003a0000200220022f012c3b014c2002200229031037033002402003450d002002410c6a41026a20012d00003a0000200241d0006a41086a2005290300370300200241d0006a41106a2006290300370300200241d0006a41186a20072d00003a0000200220022f014c3b010c20022002290330370350410021010c020b200041023a0000200241f0006a24000f0b20052004107a000b200020022f010c3b0001200020013a0000200041046a2004360200200041086a2002290350370200200041036a2002410e6a2d00003a0000200041106a200241d0006a41086a290300370200200041186a200241d0006a41106a290300370200200041206a200241d0006a41186a280200360200200241f0006a24000be70801067f230041f0006b22022400200241003a005020012802002001280204200241d0006a410120012802081004210320012001280208200341016a220341014b6a220436020802400240024020034102490d0020022d0050220341f0014f0d01410121010c020b200041023a0000200241f0006a24000f0b024002400240024002400240200341847e6a220341034b0d0002400240024020030e0400040102000b200141046a2802002103200241003b0150200141086a2205410020012802002003200241d0006a41022004100422012001417f461b2203410220034102491b20052802006a36020041012101200341014d0d0641ef01210320022f015041ef014b0d08200041023a0000200241f0006a24000f0b200141046a280200210320024100360250200141086a2205410020012802002003200241d0006a41042004100422012001417f461b2201410420014104491b20052802006a360200200041023a0000200241f0006a24000f0b200241d0006a41186a4200370300200241d0006a41106a4200370300200241d0006a41086a42003703002002420037035041002105200141086a220341002001280200200141046a280200200241d0006a41202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d022002412e6a20022d00523a0000200241106a41086a200241df006a290000370300200241106a41106a200241e7006a290000370300200241106a41186a200241d0006a411f6a2d00003a0000200220022f01503b012c2002200229005737031020022800532103410121050c030b200041023a0000200241f0006a24000f0b200141046a280200210320024100360250200141086a2205410020012802002003200241d0006a41042004100422012001417f461b2201410420014104491b20052802006a360200200141034d0d0341ffff03210341012101200228025041ffff034b0d04200041023a0000200241f0006a24000f0b0b200241cc006a41026a22012002412c6a41026a2d00003a0000200241306a41086a2204200241106a41086a290300370300200241306a41106a2206200241106a41106a290300370300200241306a41186a2207200241106a41186a2d00003a0000200220022f012c3b014c2002200229031037033002402005450d002002410c6a41026a20012d00003a0000200241d0006a41086a2004290300370300200241d0006a41106a2006290300370300200241d0006a41186a20072d00003a0000200220022f014c3b010c20022002290330370350410021010c030b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200020022f010c3b0001200020013a0000200041046a2003360200200041086a2002290350370200200041036a2002410e6a2d00003a0000200041106a200241d0006a41086a290300370200200041186a200241d0006a41106a290300370200200041206a200241d0006a41186a280200360200200241f0006a24000b900101017f230041106b220224000240024020002d00004101470d002002200041046a280200220036020c200041ffff034d0d01200141fd01102420002001108901200241106a24000f0b200141ff011024200041016a2001101e200241106a24000f0b0240200041ef014b0d00200120001024200241106a24000f0b200141fc011024200120001021200241106a24000b960706047f017e017f027e067f027e230041f0056b22022400200241c8026a200110a601200241d8026a280200210320022802d402210420022802d002210520022903c802210620024180056a200241dc026a41e40010f8021a02400240024002400240024002400240024002402005450d00200241106a20024180056a41e40010f8021a200241086a2001103a2002280208450d05200228020c2207ad220842d8017e2209422088a70d082009a7220a417f4c0d08200a450d01200a1000220b450d0920070d020c030b20004100360208200241f0056a24000f0b4108210b2007450d010b200241c8026a41f8006a210c4100210d0340200241c8026a200110a70120024180056a200241c8026a41f00010f8021a200241c8026a41f0006a2903002109200241a0046a200c41e00010f8021a20094203510d02200241d8016a20024180056a41f00010f8021a200241f8006a200241a0046a41e00010f8021a02402008422088a7220a2008a7470d00200a41016a220e200a490d05200a410174220f200e200e200f491bad221042d8017e2211422088a70d052011a7220e4100480d0502400240200a450d00200e1000220f450d08200f200b200e200a41d8016c220a200a200e4b1b10f802210a200b1001200a210b0c010b200e1000220b450d070b20084280808080708320108421080b200b2008422088a741d8016c6a200241d8016a41f00010f802220a2009370370200a41f8006a200241f8006a41e00010f8021a20084280808080107c2108200d41016a220d2007490d000b0b200b450d01200241c8026a200241106a41e40010f8021a200041106a20033602002000200436020c2000200536020820002006370300200041146a200241c8026a41e40010f8021a200041fc006a2008370200200041f8006a200b360200200241f0056a24000f0b02402008422088a7220a450d00200a41d8016c210d200b4188016a210a0340200a1028200a41d8016a210a200d41a87e6a220d0d000b0b2008a7450d00200b10010b2000410036020802402003450d00200341286c210b2005210a03400240200a2d0000220d450d000240200d4101470d00200a41086a280200450d01200a41046a2802001001200a41286a210a200b41586a220b0d020c030b200a41146a280200450d00200a41106a28020010010b200a41286a210a200b41586a220b0d000b0b02402004450d00200510010b200241f0056a24000f0b1018000b200e41081019000b102c000b200a41081019000bcd0c05087f037e027f017e017f230041d0016b22022400200241b0016a41186a22034200370300200241b0016a41106a22044200370300200241b0016a41086a22054200370300200242003703b001200241b0016a20012802002206200128020422074120200741204922081b220910f8021a2001200720096b3602042001200620096a3602000240024002400240024020080d0020024190016a41186a2207200329030037030020024190016a41106a2209200429030037030020024190016a41086a22062005290300370300200220022903b0013703900120032007290300220a37030020042009290300220b37030020052006290300220c370300200241306a41086a200c370300200241306a41106a200b370300200241306a41186a200a3703002002200229039001220a3703302002200a3703b001200220011097012002290300a7450d012002290308210a200241b0016a41186a22054200370300200241b0016a41106a22064200370300200241b0016a41086a22084200370300200242003703b001200241b0016a2001280200220d200141046a22042802002207412020074120491b220910f8021a2004200720096b22033602002001200d20096a22093602002007411f4d0d0220024190016a41186a2207200529030037030020024190016a41106a220d200629030037030020024190016a41086a220e2008290300370300200220022903b0013703900120052007290300220b3703002006200d290300220c3703002008200e290300220f370300200241d0006a41086a200f370300200241d0006a41106a200c370300200241d0006a41186a200b3703002002200229039001220b3703502002200b3703b001200241b0016a2003412020034120491b22076a41004100412020076b2007411f4b1b10f7021a200241b0016a2009200710f8021a2004200320076b3602002001200920076a3602002003411f4d0d0320024190016a41186a2207200241b0016a41186a220929030037030020024190016a41106a2203200241b0016a41106a220429030037030020024190016a41086a2205200241b0016a41086a2206290300370300200220022903b0013703900120092007290300220b37030020042003290300220c37030020062005290300220f370300200241f0006a41086a2208200f370300200241f0006a41106a220d200c370300200241f0006a41186a220e200b3703002002200229039001220b3703702002200b3703b001200241b0016a200110fd0120022802b0012201450d0420022902b401210b2009200241306a41186a2903003703002004200241306a41106a2903003703002006200241306a41086a2903003703002005200241d0006a41086a2903003703002003200241d0006a41106a2903003703002007200241d0006a41186a290300370300200241106a41086a22102008290300370300200241106a41106a2208200d290300370300200241106a41186a220d200e290300370300200220022903303703b0012002200229035037039001200220022903703703102000200b37020c200020013602082000200a370300200041146a20022903b0013702002000411c6a2006290300370200200041246a20042903003702002000412c6a2009290300370200200041346a2002290390013702002000413c6a2005290300370200200041c4006a2003290300370200200041cc006a2007290300370200200041ec006a200d290300370200200041e4006a2008290300370200200041dc006a2010290300370200200041d4006a2002290310370200200241d0016a24000f0b200320024190016a41186a290000370300200420024190016a41106a290000370300200520024190016a41086a29000037030020022002290090013703b00120004100360208200241d0016a24000f0b20004100360208200241d0016a24000f0b200520024190016a41186a290000370300200620024190016a41106a290000370300200820024190016a41086a29000037030020022002290090013703b00120004100360208200241d0016a24000f0b200241b0016a41186a20024190016a41186a290000370300200241b0016a41106a20024190016a41106a290000370300200241b0016a41086a20024190016a41086a29000037030020022002290090013703b00120004100360208200241d0016a24000f0b20004100360208200241d0016a24000ba41404027f017e107f067e230041a0046b22022400200241086a2001103a02400240024002400240024002400240024002402002280208450d000240200228020c2203450d002003ad2104410021054100210603402005417f460d04200442ffffffff0f832004422088a741016a2205ad422086842104200641016a22062003490d000b0b200241003a00f001200241f0016a2001280200220320012802042205410047220610f8021a20052006490d03200141046a200520066b3602002001200320066a3602002005450d0720022d00f001220541ff00714101470d072005411874411875417f4c0d01420221040c090b20004203370370200241a0046a24000f0b200241b8036a200110a20102400240024020022d00b8034102460d0020024190036a41206a200241b8036a41206a28020036020020024190036a41186a200241b8036a41186a29030037030020024190036a41106a200241b8036a41106a29030037030020024190036a41086a200241b8036a41086a290300370300200220022903b80337039003200241f0016a41386a22074200370300200241f0016a41306a22084200370300200241f0016a41286a22094200370300200241f0016a41206a220a4200370300200241f0016a41186a220b4200370300200241f0016a41106a220c4200370300200241f0016a41086a220d4200370300200242003703f001200241f0016a2001280200220e200141046a220f280200220541c000200541c000491b220610f8021a200f200520066b22033602002001200e20066a220636020002402005413f4d0d00200241c0026a41386a22052007290300370300200241c0026a41306a220e2008290300370300200241c0026a41286a22102009290300370300200241c0026a41206a2211200a290300370300200241c0026a41186a2212200b290300370300200241c0026a41106a2213200c290300370300200241c0026a41086a2214200d290300370300200220022903f0013703c0022007200529030022043703002008200e2903002215370300200920102903002216370300200a20112903002217370300200b20122903002218370300200c20132903002219370300200d2014290300221a370300200241e0036a41086a201a370300200241e0036a41106a2019370300200241e0036a41186a2018370300200241e0036a41206a2017370300200241e0036a41286a2016370300200241e0036a41306a2015370300200241e0036a41386a2004370300200220022903c00222043703e003200220043703f001200242003703f001200241f0016a20062003410820034108491b220510f8021a200f200320056b22073602002001200620056a2205360200200341074d0d0120022903f0012115200241003a00f001200241f0016a20052007410047220610f8021a20072006490d06200141046a200720066b22033602002001200520066a22053602002007450d0120023100f0012217500d02200241003a00f001200241f0016a20052003410047220610f8021a20032006490d07200141046a200320066b3602002001200520066a3602002003450d0142022017420f838622164204540d014201210420023100f0014208862017844204882016420c882217420120174201561b7e22172016540d030c010b2007200241c0026a41386a2900003703002008200241c0026a41306a2900003703002009200241c0026a41286a290000370300200a200241c0026a41206a290000370300200b200241c0026a41186a290000370300200c200241c0026a41106a290000370300200d200241c0026a41086a290000370300200220022900c0023703f0010b420221040c060b420021040b200241f8006a41206a20024190036a41206a280200360200200241f8006a41186a20024190036a41186a290300370300200241f8006a41106a20024190036a41106a290300370300200241f8006a41086a20024190036a41086a290300370300200241a0016a41086a200241e0036a41086a290300370300200241a0016a41106a200241e0036a41106a290300370300200241a0016a41186a200241e0036a41186a290300370300200241a0016a41206a200241e0036a41206a290300370300200241a0016a41286a200241e0036a41286a290300370300200241a0016a41306a200241e0036a41306a290300370300200241a0016a41386a200241e0036a41386a2903003703002002200229039003370378200220022903e0033703a0010c040b1018000b20062005107a000b20062007107a000b20062003107a000b200241c0026a41206a2205200241f8006a41206a280200360200200241c0026a41186a2206200241f8006a41186a290300370300200241c0026a41106a2203200241f8006a41106a290300370300200241c0026a41086a2207200241f8006a41086a290300370300200241f0016a41086a2208200241a0016a41086a290300370300200241f0016a41106a2209200241a0016a41106a290300370300200241f0016a41186a220a200241a0016a41186a290300370300200241f0016a41206a220b200241a0016a41206a290300370300200241f0016a41286a220c200241a0016a41286a290300370300200241f0016a41306a220d200241a0016a41306a290300370300200241f0016a41386a220f200241a0016a41386a290300370300200220022903783703c002200220022903a0013703f00120044202520d010b20004203370370200241a0046a24000f0b200241d0006a41206a2005280200360200200241d0006a41186a2006290300370300200241d0006a41106a2003290300370300200241d0006a41086a2007290300370300200241106a41086a2008290300370300200241106a41106a2009290300370300200241106a41186a200a290300370300200241106a41206a200b290300370300200241106a41286a200c290300370300200241106a41306a200d290300370300200241106a41386a200f290300370300200220022903c002370350200220022903f0013703100b200241f0016a200110d50220022802f0012105200241c0026a200241f0016a41047241cc0010f8021a02402005410d470d0020004203370370200241a0046a24000f0b200241a0016a200241c0026a41cc0010f8021a2000201537030020002002290350370308200041106a200241d0006a41086a290300370300200041186a200241d0006a41106a290300370300200041206a200241d0006a41186a290300370300200041286a200241d0006a41206a2802003602002000200229031037022c200041346a200241106a41086a2903003702002000413c6a200241106a41106a290300370200200041c4006a200241106a41186a290300370200200041cc006a200241106a41206a290300370200200041d4006a200241106a41286a290300370200200041dc006a200241c0006a290300370200200041e4006a200241c8006a29030037020020004188016a200536020020004180016a201737030020002016370378200020043703702000418c016a200241a0016a41cc0010f8021a200241a0046a24000bee0404017f017e027f017e230041d0006b2205240042002106200541306a41086a220742003703002005420037033041d0b0c0004111200541306a1002200541206a41086a220820072903003703002005200529033037032042002109024002400240200541206a41104188f0c100410041001004417f460d0020054200370340200541206a4110200541c0006a41084100100441016a41084d0d01200529034021090b2005200242002003200410fc022005200920017c20027d370340200742003703002005420037033041d0b0c0004111200541306a10022008200729030037030020052005290330370320200541206a4110200541c0006a41081003200541106a200010a90120002005290300220920052903107c2202200541086a2903002201200541106a41086a2903007c2002200954ad7c10aa01200742003703002005420037033041d9f0c1004116200541306a1002200820072903003703002005200529033037032002400240200541206a41104188f0c100410041001004417f460d002005420037034820054200370340200541206a4110200541c0006a4110410010042207417f460d032007410f4d0d03200541c8006a2903002102200529034021060c010b420021020b0240200620097c22092006542207200220017c2007ad7c220620025420062002511b0d002005200937034020052006370348200541306a41086a220742003703002005420037033041d9f0c1004116200541306a1002200541206a41086a200729030037030020052005290330370320200541206a4110200541c0006a411010030b200541d0006a24000f0b41eac4c10041331042000b41eac4c10041331042000bbf0204047f017e017f017e230041206b22022400024002400240411410002203450d002002421437021420022003360210200241106a41eeefc10041141025200241086a220320022802183602002002200229031037030020012002101e20032802002104200228020421052002280200210142002106200241106a41086a220742003703002002420037031020012004200241106a1002200320072903003703002002200229031037030002400240200241104188f0c100410041001004417f460d00200242003703182002420037031020024110200241106a4110410010042203417f460d012003410f4d0d01200241186a2903002108200229031021062005450d040c030b4200210820050d020c030b41eac4c10041331042000b411441011019000b200110010b2000200637030020002008370308200241206a24000bee1207017f017e017f017e037f017e047f230041d0006b2203240042002104200341106a41086a220542003703002003420037031041bef0c100411b200341106a1002200341086a2005290300370300200320032903103703000240024002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a29030021062003290320210441142105411410002207450d010c030b42002106411421054114100022070d020b200541011019000b41eac4c10041331042000b2003421437022420032007360220200341206a41eeefc10020051025200341106a41086a22052003280228360200200320032903203703102000200341106a101e2005280200210820032802142109200328021021072003200237032820032001370320200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030020034110200341206a4110100302402009450d00200710010b02402004200158200620025820062002511b0d00024002400240411410002205450d002003421437022420032005360220200341206a41eeefc10041141025200341106a41086a22052003280228360200200320032903203703102000200341106a101e20052802002108200328021421092003280210210742002106200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d012005410f4d0d01200341286a2903002104200329032021062009450d040c030b4200210420090d020c030b41eac4c10041331042000b411441011019000b200710010b42002102200341106a41086a220542003703002003420037031041d9f0c1004116200341106a1002200341086a2005290300370300200320032903103703000240024002400240024002400240024002400240024002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a2903002101200329032021020c010b420021010b0240200220067d220a200256200120047d2002200654ad7d220220015620022001511b0d002003200a37032020032002370328200341106a41086a220542003703002003420037031041d9f0c1004116200341106a1002200341086a20052903003703002003200329031037030020034110200341206a411010030b411410002205450d022003421437022420032005360220200341206a41eeefc10041141025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021082003280214210920032802102107200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030020034110100802402009450d00200710010b410f10002205450d032003420f37022420032005360220200341206a41ddd2c000410f1025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021072003280214210820032802102105200341086a22094200370300200342003703002005200720031002200341206a41086a200929030037030020032003290300370320200341206a4110100802402008450d00200510010b410f10002205450d042003420f37022420032005360220200341206a41c1b0c000410f1025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021072003280214210820032802102105200341086a22094200370300200342003703002005200720031002200341206a41086a2207200929030037030020032003290300370320200341206a4110100802402008450d00200510010b200341206a41186a200041186a290000370300200341206a41106a200041106a2900003703002007200041086a290000370300200320002900003703202003410036024820034201370340200341c0006a418b9ec100410810252003200341206a10f5012003280204210b2003280200210c02400240024002402003280244220d200328024822076b200328020822094f0d00200720096a22052007490d09200d4101742208200520052008491b22084100480d09200d450d012003280240210e200810002205450d0c2005200e2008200d200d20084b1b10f8021a200e10010c020b20032802402105200d21080c020b200810002205450d0a0b20032008360244200320053602400b200520076a200c200910f8021a200341c0006a41086a200720096a22073602000240200b450d00200c10010b200341086a22094200370300200342003703002005200720031002200341106a41086a20092903003703002003200329030037031002402008450d00200510010b200341106a41101015411110002205450d062003421137022420032005360220200341206a41f384c10041111025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021072003280214210820032802102105200341086a22094200370300200342003703002005200720031002200341206a41086a200929030037030020032003290300370320200341206a4110100802402008450d00200510010b411810002205450d072003421837022420032005360220200341206a4193f1c10041181025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021082003280214210920032802102107200542003703002003420037031020072008200341106a1002200341086a2005290300370300200320032903103703000240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a290300210220032903202101410021052009450d0b0c0a0b4101210520090d090c0a0b41eac4c10041331042000b41eac4c10041331042000b411441011019000b410f41011019000b410f41011019000b1018000b411141011019000b411841011019000b200841011019000b200710010b20012002844200522005410173710d00200010f1020b200341d0006a24000bd40a02027f097e230041f0006b22032400200341d0006a41086a220442003703002003420037035041e1b0c0004116200341d0006a1002200341c0006a41086a2004290300370300200320032903503703400240024002400240024002400240200341c0006a41104188f0c100410041001004417f460d0020034200370360200341c0006a4110200341e0006a41084100100441016a41084d0d02200329036021050c010b42c0843d21050b42002106200341d0006a41086a220442003703002003420037035041d0b0c0004111200341d0006a1002200341c0006a41086a2004290300370300200320032903503703400240200341c0006a41104188f0c100410041001004417f460d0020034200370360200341c0006a4110200341e0006a41084100100441016a41084d0d02200329036021060b02400240200520067d20025a0d00200041f8c1c000360204200041086a411a360200410121040c010b42002105200341d0006a41086a220442003703002003420037035041d3b5c0004111200341d0006a1002200341c0006a41086a20042903003703002003200329035037034002400240200341c0006a41104188f0c100410041001004417f460d002003420037036820034200370360200341c0006a4110200341e0006a4110410010042204417f460d052004410f4d0d05200341e8006a2903002105200329036021060c010b420121060b42002107200341106a200542002002420010fc02200341206a200242002006420010fc022003420042002006420010fc02200341306a200110a90102402003290308200329031884420052200341206a41086a2903002208200329030020032903107c7c220920085472450d0020004192c2c000360204200041086a4127360200410121040c010b200341306a41086a290300210a2003290320210b20032903302108200341d0006a41086a220442003703002003420037035041bef0c100411b200341d0006a1002200341c0006a41086a20042903003703002003200329035037034002400240200341c0006a41104188f0c100410041001004417f460d002003420037036820034200370360200341c0006a4110200341e0006a4110410010042204417f460d062004410f4d0d06200341e8006a290300210c200329036021070c010b4200210c0b02402008200b7d220d200856200a20097d2008200b54ad7d2208200a562008200a511b200d2007542008200c542008200c511b72450d00200041eff0c100360204200041086a4124360200410121040c010b2001200d200810aa0142002108200341d0006a41086a220442003703002003420037035041d9f0c1004116200341d0006a1002200341c0006a41086a20042903003703002003200329035037034002400240200341c0006a41104188f0c100410041001004417f460d002003420037036820034200370360200341c0006a4110200341e0006a4110410010042204417f460d072004410f4d0d07200341e8006a290300210a200329036021080c010b4200210a0b02402008200b7d2207200856200a20097d2008200b54ad7d2208200a562008200a511b0d002003200737036020032008370368200341d0006a41086a220442003703002003420037035041d9f0c1004116200341d0006a1002200341c0006a41086a200429030037030020032003290350370340200341c0006a4110200341e0006a411010030b200041206a2005370300200041186a2006370300200041106a2002370300200041086a2002370300410021040b20002004360200200341f0006a24000f0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b3400200041cd9fc10036020420004100360200200041146a4115360200200041106a41f0acc200360200200041086a42073702000bfb1705147f027e017f047e017f230041d0026b2202240002400240024002402001450d00200241f1016a2103200241d1016a210420024180026a2105200241f8016a2106200241f4016a2107410021080340024002400240024002400240024002400240411210002209450d00200242123702cc01200220093602c801200241c8016a4181cfc00041121025200241a8016a41086a2209200241c8016a41086a220a280200360200200220022903c8013703a8012000200241a8016a101e2009280200210b20022802ac01210c20022802a801210d20094200370300200242003703a801200d200b200241a8016a1002200241b8026a41086a220e2009290300370300200220022903a8013703b8024100210b0240024002400240200241b8026a41104188f0c100410041001004417f460d00200241003602c801200241b8026a4110200241c8016a41044100100441016a41044d0d0120022802c801210b0b0240200c450d00200d10010b200241c8016a41186a220c200041186a220f290000370300200241c8016a41106a2210200041106a2211290000370300200a200041086a2212290000370300200220002900003703c80141121000220d450d04200242123702ac012002200d3602a801200241a8016a4181cfc00041121025200e2009280200360200200220022903a8013703b802200241c8016a200241b8026a101e200e280200211320022802bc02211420022802b802210d2002200b41016a3602cc0220094200370300200242003703a801200d2013200241a8016a1002200e2009290300370300200220022903a8013703b802200241b8026a4110200241cc026a4104100302402014450d00200d10010b20094200370300200242003703a8014193cfc0004119200241a8016a1002200e2009290300370300200220022903a8013703b8024100210d0240200241b8026a41104188f0c100410041001004417f460d00200241003602c801200241b8026a4110200241c8016a41044100100441016a41044d0d0220022802c801210d0b0240200b200d4f0d00200241a8016a41186a200f290000370300200241a8016a41106a201129000037030020092012290000370300200220002900003703a8014101210d200b21150c0c0b4200211620094200370300200242003703a80141accfc000411b200241a8016a1002200e2009290300370300200220022903a8013703b802024002400240200241b8026a41104188f0c100410041001004417f460d00200242003703d001200242003703c801200241b8026a4110200241c8016a4110410010042213417f460d082013410f4d0d08200a290300211720022903c8012116200b200d6b2214210d201441ff004b0d010c020b42002117200b200d6b2214210d201441ff004d0d010b200c200f29000037030020102011290000370300200a2012290000370300200220002900003703c80141121000220d450d08200242123702ac012002200d3602a801200241a8016a4181cfc00041121025200e2009280200360200200220022903a8013703b802200241c8016a200241b8026a101e200e280200211320022802bc02211820022802b802210d2002200b3602cc0220094200370300200242003703a801200d2013200241a8016a1002200e2009290300370300200220022903a8013703b802200241b8026a4110200241cc026a4104100302402018450d00200d10010b41ff00210d2014417f6a4180014f0d090b20024198016a20162017200d41ff007110fe0220094200370300200242003703a80141e7d0c0004112200241a8016a1002200e2009290300370300200220022903a8013703b802200229039801211920024198016a41086a290300211a02400240200241b8026a41104188f0c100410041001004417f460d00200242103702ac012002200241b8026a3602a801200241c8016a200241a8016a103620022802c8012218450d08200a280200210b20022802cc01210d0c010b4100210d410121184100210b0b20094200370300200242003703a80141f9d0c000411d200241a8016a1002200e2009290300370300200220022903a8013703b8020240200241b8026a41104188f0c100410041001004417f460d00200241003602c801200241b8026a4110200241c8016a41044100100441016a41044d0d0320022802c8012113200d450d0b0c0a0b41042113200d0d090c0a0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411241011019000b411241011019000b41eac4c10041331042000b41eac4c10041331042000b411241011019000b41c7cfc00041a0011042000b201810010b0240200b20134d0d0020024180016a20002019201a10ae01200229038001a74101470d0020024180016a41106a290300211b200229038801211c200241c8016a200010af0120022802c80121180240200a280200220b450d0042002116200b4105742213210d420021172018210b0340200241f0006a200b10b001200241f0006a41086a29030020177c2002290370221720167c2216201754ad7c2117200b41206a210b200d41606a220d0d000b2016201784500d002018210b0340200241e0006a200b10b001200241386a2002290360200241e0006a41086a290300201c201b10fc02200241286a2002290338200241386a41086a2903002016201710fb02200241c8006a200b2002290328200241286a41086a29030010ae01200b41206a210b201341606a22130d000b0b20022802cc01450d00201810010b411c1000220b450d032002421c3702cc012002200b3602c801200241c8016a4196d1c000411c10252009200a280200360200200220022903c8013703a8012000200241a8016a101e20022802ac01210b200241c8016a20022802a8012213200928020010b101200c280200410320022903c8014201511b210d0240200b450d00201310010b024002402014200d4f0d002019423f88211b201a420186211c200241c8016a200010b201200a280200210b20022802c8012113200241186a200010b001200241186a41086a2903002116200229031821170240200b450d00200b410574210d2013210b0340200241086a200b10b001200241086a41086a29030020167c2002290308221620177c2217201654ad7c2116200b41206a210b200d41606a220d0d000b0b201c201b84211b2019420186211c024020022802cc01450d00201310010b2017201c5a2016201b5a2016201b511b0d010b20094200370300200242003703a80141e7d0c0004112200241a8016a1002200e2009290300370300200220022903a8013703b8020240200241b8026a41104188f0c100410041001004417f460d00200242103702ac012002200241b8026a3602a801200241c8016a200241a8016a103620022802c8012218450d0620022802cc01211d0240200a280200220b450d00200b41057421134100210d2018210b024002400340200b41086a2900002116200b41106a2900002117200b290000211b200c200b41186a29000037030020102017370300200a20163703002002201b3703c801200241c8016a2000460d01200d200241c8016a2000412010fa0222144100476a210d2014450d02200b41206a210b201341606a22130d000c030b0b4100210d0b2000200d10b301220b0d080b201d450d00201810010b20094200370300200242003703a80141b1d2c0004115200241a8016a1002200e2009290300370300200220022903a8013703b802200241b8026a41104188f0c10041001003200241003a00c80120094200370300200242003703a80141eef1c0004119200241a8016a1002200e2009290300370300200220022903a8013703b802200241b8026a4110200241c8016a410110030b200241a8016a41186a200f290000370300200241a8016a41106a201129000037030020092012290000370300200220002900003703a8014102210d0b2005201a37030020062019370300200a200d3a0000200420022903a801370000200320022f00b8023b000020072015360200200441086a2009290300370000200441106a200241a8016a41106a290300370000200441186a200241a8016a41186a290300370000200341026a200241b8026a41026a2d00003a0000200241033a00c801200241c8016a10b401200841016a22082001490d000b0b200241d0026a24000f0b411c41011019000b41eac4c10041331042000b200b10b501000b8f0602057f077e230041d0006b22042400024002400240411410002205450d002004421437024420042005360240200441c0006a41eeefc10041141025200441306a41086a22052004280248360200200420042903403703302001200441306a101e20052802002106200428023421072004280230210842002109200542003703002004420037033020082006200441306a1002200441206a41086a20052903003703002004200429033037032002400240200441206a41104188f0c100410041001004417f460d002004420037034820044200370340200441206a4110200441c0006a4110410010042205417f460d012005410f4d0d01200441c8006a290300210a200429034021092007450d040c030b4200210a20070d020c030b41eac4c10041331042000b411441011019000b200810010b20012009200220092009200256200a200356200a20035122051b22081b220b7d200a2003200a20081b220c7d2009200b54ad7d10aa014200210d200441306a41086a220842003703002004420037033041d9f0c1004116200441306a1002200441206a41086a200829030037030020042004290330370320024002400240200441206a41104188f0c100410041001004417f460d002004420037034820044200370340200441206a4110200441c0006a4110410010042208417f460d022008410f4d0d02200441c8006a290300210e2004290340210d0c010b4200210e0b0240200d200b7d220f200d56200e200c7d200d200b54ad7d220d200e56200d200e511b0d002004200f3703402004200d370348200441306a41086a220842003703002004420037033041d9f0c1004116200441306a1002200441206a41086a200829030037030020042004290330370320200441206a4110200441c0006a411010030b02400240200920025a200a20035a20051b0d00200441086a20012002200b7d2003200c7d2002200b54ad7d10d402200441186a29030021092004290310210a200429030821030c010b420021030b2000200a37030820002003370300200041106a2009370300200441d0006a24000f0b41eac4c10041331042000baa0201057f230041306b220224000240024002400240411c10002203450d002002421c37022420022003360220200241206a41ddd3c000411c1025200241086a220320022802283602002002200229032037030020012002101e200328020021042002280204210520022802002101200241206a41086a220642003703002002420037032020012004200241206a100220032006290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103620022802202203450d0220002002290224370204200020033602002005450d040c030b200041003602082000420137020020050d020c030b411c41011019000b41eac4c10041331042000b200110010b200241306a24000be50404057f017e017f037e230041206b22022400024002400240411410002203450d002002421437021420022003360210200241106a41eeefc10041141025200241086a220320022802183602002002200229031037030020012002101e20032802002104200228020421052002280200210642002107200241106a41086a220842003703002002420037031020062004200241106a1002200320082903003703002002200229031037030002400240200241104188f0c100410041001004417f460d00200242003703182002420037031020024110200241106a4110410010042203417f460d012003410f4d0d01200241186a2903002109200229031021072005450d040c030b4200210920050d020c030b41eac4c10041331042000b411441011019000b200610010b024002400240411810002203450d002002421837021420022003360210200241106a4193f1c10041181025200241086a220320022802183602002002200229031037030020012002101e2003280200210620022802042104200228020021014200210a200241106a41086a220542003703002002420037031020012006200241106a1002200320052903003703002002200229031037030002400240200241104188f0c100410041001004417f460d00200242003703182002420037031020024110200241106a4110410010042203417f460d012003410f4d0d01200241186a290300210b2002290310210a2004450d040c030b4200210b20040d020c030b41eac4c10041331042000b411841011019000b200110010b2000200a20077c22073703002000200b20097c2007200a54ad7c370308200241206a24000bf30103017f017e017f230041c0006b2203240042002104200341306a41086a220542003703002003420037033020012002200341306a1002200341206a41086a20052903003703002003200329033037032002400240200341206a41104188f0c100410041001004417f460d00200342103702342003200341206a360230200341186a200341306a10352003280218450d01200328021c21012003200341306a1098012003290300a7450d01200341106a290300210420002003290308370308200041186a2001360200200041106a2004370300420121040b20002004370300200341c0006a24000f0b41eac4c10041331042000baa0201057f230041306b220224000240024002400240411510002203450d002002421537022420022003360220200241206a41c8d3c00041151025200241086a220320022802283602002002200229032037030020012002101e200328020021042002280204210520022802002101200241206a41086a220642003703002002420037032020012004200241206a100220032006290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103620022802202203450d0220002002290224370204200020033602002005450d040c030b200041003602082000420137020020050d020c030b411541011019000b41eac4c10041331042000b200110010b200241306a24000bc70c03067f037e047f230041306b22022400200241206a41086a220342003703002002420037032041e7d0c0004112200241206a1002200241086a2003290300370300200220022903203703000240024002400240024002400240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103620022802202203450d02200241286a2802002104200228022421050c010b410021030b2005410020031b21062003410120031b2107024002402004410020031b220420014d0d002000200720014105746a2203460d0120032000412010fa02450d010b41ecd2c00021032006450d0520071001200241306a240041ecd2c0000f0b20072004417f6a22054105746a22012900002108200129000821092001290010210a200341186a200141186a2900003700002003200a370010200320093700082003200837000020024100360228200242013703202005200241206a101b0240024002400240024002402005450d00200441057441606a210b4100200241206a41086a28020022016b210c2002280220210d200228022421052007210e0340200e210302402005200c6a411f4b0d00200141206a22042001490d042005410174220e20042004200e491b22044100480d0420041000210e024002402005450d00200e450d07200e200d20042005200520044b1b10f8021a200d10010c010b200e450d060b200e210d200421050b200341206a210e200d20016a22042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200c41606a210c200141206a2101200b41606a220b0d000b200241286a2001360200200220053602242002200d3602200c010b200241286a2802002101200228022421052002280220210d0b200241206a41086a220342003703002002420037032041e7d0c0004112200241206a1002200241086a20032903003703002002200229032037030020024110200d2001100302402005450d00200d10010b02402006450d00200710010b411c10002203450d052002421c37022420022003360220200241206a4196d1c000411c1025200241086a220320022802283602002002200229032037030020002002101e200328020021042002280204210520022802002101200241206a41086a220c42003703002002420037032020012004200241206a10022003200c2903003703002002200229032037030020024110100802402005450d00200110010b411210002203450d062002421237022420022003360220200241206a4181cfc00041121025200241086a220320022802283602002002200229032037030020002002101e200328020021052002280204210c2002280200210442002108200241206a41086a220142003703002002420037032020042005200241206a100220032001290300370300200220022903203703002002411010080240200c450d00200410010b200142003703002002420037032041f0f1c100410d200241206a100220032001290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002420037032020024110200241206a41084100100441016a41084d0d03200229032021080b200241206a41086a220342003703002002420037032041c6d2c0004117200241206a1002200241086a20032903003703002002200229032037030002400240200241104188f0c100410041001004417f460d002002420037032020024110200241206a41084100100441016a41084d0d0520022903202109410f2103410f10002201450d010c090b42e8072109410f2103410f100022010d080b200341011019000b1018000b200441011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411c41011019000b411241011019000b2002420f37022420022001360220200241206a41ddd2c00020031025200241086a220320022802283602002002200229032037030020002002101e2003280200210420022802042105200228020021012002200920087c370310200241206a41086a220c42003703002002420037032020012004200241206a10022003200c2903003703002002200229032037030020024110200241106a41081003410021032005450d00200110010b200241306a240020030bffa80104057f017e0b7f017e23004180036b22012400200141086a10f001200128020c210220012802082103200141a0016a41086a22044200370300200142003703a00141cef1c100410d200141a0016a1002200141106a41086a2004290300370300200120012903a001370310024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141106a41104188f0c100410041001004417f460d00200142103702242001200141106a3602202001200141206a10352001280200450d6520012802042205ad42f8007e2206422088a70d032006a72204417f4c0d032004450d01200410002207450d042005450d020c050b410021074100210a4100210d4100210b0c060b4108210720050d030b410021044100210c0c030b102c000b200441081019000b200141a0016a4101722108200141286a21094100210a4100210b410021042005210c02400340200141003a00910220092009280200220d2001280220220e2001280224220f20014191026a4101200d100441016a220d41014b6a2210360200200d4102490d010240024020012d009102220d450d004101210e200d4101460d010c030b200141003602a00120094100200e200f200141a0016a410420101004220d200d417f461b220d4104200d410449220d1b20106a360200200d0d0220012802a001210f4100210e0b200141a0016a200141206a10cb0220012d00a001211020014191026a200841ef0010f8021a2010410c460d01200141316a20014191026a41ef0010f8021a200141a0016a200141316a41ef0010f8021a02402004200c470d00200a200441016a220d200d200a491b220cad42f8007e2206422088a70d052006a7220d4100480d0502402004450d00200d10002211450d6220112007200d200b200b200d4b1b10f802210d20071001200d21070c010b200d10002207450d610b2007200b6a220d20103a0000200d41016a200141a0016a41ef0010f8021a200d41f4006a200f360200200d41f0006a200e360200200a41026a210a200b41f8006a210b200441016a22042005490d000c020b0b02402004450d00200741186a2101034002400240200141686a2d000022044108460d00024020044105460d0020044104470d02200141706a2d00000d022001417c6a280200450d02200141786a2802001001200141f8006a2101200b41887f6a220b0d030c040b2001416c6a2d00004103470d010240200141746a280200450d00200141706a28020010010b2001280200450d012001417c6a2802001001200141f8006a2101200b41887f6a220b0d020c030b200141706a280200450d002001416c6a28020010010b200141f8006a2101200b41887f6a220b0d000b0b200c450d5f200710010c5f0b2007450d5e2007210a2007210d2007210b0b200141a0016a200041f00010f8021a024002400240024020044100200b1b2205200c4100200b1b2200470d00200541016a22042005490d042005410174220d20042004200d491b2200ad42f8007e2206422088a70d042006a722044100480d042005450d01200410002211450d5f2011200a4108200b1b220b2004200541f8006c220d200d20044b1b10f8021a200b10010c020b200d4108200b1b210c20074108200b1b21110c020b200410002211450d5d0b2011210c0b200c200541f8006c6a200141a0016a41f00010f802220441f4006a20023602002004200345360270200141003602a801200142013703a001200541016a2208200141a0016a101b02402008450d00200441f8006a210e200141a0016a41086a2104200c210b034002400240024002400240024002400240024002400240024002400240024002400240200b2802704101470d0020012802a4012004280200220d470d01200d41016a2207200d490d13200d410174220a20072007200a491b220a4100480d13200d450d0320012802a0012110200a10002207450d0a20072010200a200d200d200a4b1b10f8021a201010010c040b20012802a4012004280200220d470d01200d41016a2207200d490d12200d410174220a20072007200a491b220a4100480d12200d450d0520012802a0012110200a10002207450d0a20072010200a200d200d200a4b1b10f8021a201010010c060b20012802a00121070c030b20012802a00121070c050b200a10002207450d060b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b2d0000417f6a220d410a4b0d030c0a0b200a10002207450d040b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41f4006a2802002110024002400240024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d0e200a410174220d20072007200d491b220d4100480d0e200a450d0120012802a0012109200d10002207450d0720072009200d200a200a200d4b1b10f8021a200910010c020b20012802a00121070c020b200d10002207450d050b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b2d0000417f6a220d410a4d0d070b024002400240024020012802a4012004280200220d470d00200d41016a2207200d490d0d200d410174220a20072007200a491b220a4100480d0d200d450d0120012802a0012110200a10002207450d0720072010200a200d200d200a4b1b10f8021a201010010c020b20012802a00121070c020b200a10002207450d050b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a00002004280200210d20012802a4012107024002400240024002400240024002400240200b41016a2d00004101470d002007200d470d01200d41016a2207200d490d12200d410174220a20072007200a491b220a4100480d12200d450d0320012802a0012110200a10002207450d0d20072010200a200d200d200a4b1b10f8021a201010010c040b2007200d470d01200d41016a2207200d490d11200d410174220a20072007200a491b220a4100480d11200d450d0520012802a0012110200a10002207450d0d20072010200a200d200d200a4b1b10f8021a201010010c060b20012802a00121070c030b20012802a00121070c050b200a10002207450d090b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41f8006a220b200e470d0a0c0b0b200a10002207450d070b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41f8006a220b200e470d070c080b200a41011019000b200a41011019000b200d41011019000b200a41011019000b200a41011019000b200a41011019000b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200d0e0b00060304010708050a0209000b20012802a4012004280200220d470d0f200d41016a2207200d490db902200d410174220a20072007200a491b220a4100480db902200d450d2120012802a0012110200a10002207450dc20220072010200a200d200d200a4b1b10f8021a201010010c220b20012802a4012004280200220d470d09200d41016a2207200d490db802200d410174220a20072007200a491b220a4100480db802200d450d1420012802a0012110200a10002207450dbd0220072010200a200d200d200a4b1b10f8021a201010010c150b20012802a4012004280200220d470d09200d41016a2207200d490db802200d410174220a20072007200a491b220a4100480db802200d450d1620012802a0012110200a10002207450dbd0220072010200a200d200d200a4b1b10f8021a201010010c170b20012802a4012004280200220d470d09200d41016a2207200d490db602200d410174220a20072007200a491b220a4100480db602200d450d1820012802a0012110200a10002207450dbd0220072010200a200d200d200a4b1b10f8021a201010010c190b20012802a4012004280200220d470d09200d41016a2207200d490db502200d410174220a20072007200a491b220a4100480db502200d450d1a20012802a0012110200a10002207450dbd0220072010200a200d200d200a4b1b10f8021a201010010c1b0b20012802a4012004280200220d470d09200d41016a2207200d490db502200d410174220a20072007200a491b220a4100480db502200d450d1f20012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010c200b20012802a4012004280200220d470d0a200d41016a2207200d490db302200d410174220a20072007200a491b220a4100480db302200d450d2120012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010c220b20012802a4012004280200220d470d0a200d41016a2207200d490db202200d410174220a20072007200a491b220a4100480db202200d450d2320012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010c240b20012802a4012004280200220d470d0a200d41016a2207200d490db102200d410174220a20072007200a491b220a4100480db102200d450d2b20012802a0012110200a10002207450dc00220072010200a200d200d200a4b1b10f8021a201010010c2c0b20012802a4012004280200220d470d0a200d41016a2207200d490db102200d410174220a20072007200a491b220a4100480db102200d450d2d20012802a0012110200a10002207450dc00220072010200a200d200d200a4b1b10f8021a201010010c2e0b20012802a4012004280200220d470d0a200d41016a2207200d490db002200d410174220a20072007200a491b220a4100480db002200d450d2f20012802a0012110200a10002207450dc00220072010200a200d200d200a4b1b10f8021a201010010c300b20012802a00121070c0c0b20012802a00121070c0e0b20012802a00121070c100b20012802a00121070c120b20012802a00121070c170b20012802a00121070c130b20012802a00121070c180b20012802a00121070c1a0b20012802a00121070c220b20012802a00121070c240b20012802a00121070c260b200a10002207450da8020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41053a000002400240200b41046a2d0000220d4101460d000240200d4102460d00200d4103470d0220012802a4012004280200220d470d37200d41016a2207200d490da402200d410174220a20072007200a491b220a4100480da402200d450d970120012802a0012110200a10002207450dd10220072010200a200d200d200a4b1b10f8021a201010010c98010b20012802a4012004280200220d470d34200d41016a2207200d490da302200d410174220a20072007200a491b220a4100480da302200d450d930120012802a0012110200a10002207450dcf0220072010200a200d200d200a4b1b10f8021a201010010c94010b20012802a4012004280200220d470d34200d41016a2207200d490da202200d410174220a20072007200a491b220a4100480da202200d450d980120012802a0012110200a10002207450dd00220072010200a200d200d200a4b1b10f8021a201010010c99010b20012802a4012004280200220d470d35200d41016a2207200d490da102200d410174220a20072007200a491b220a4100480da102200d450d9a0120012802a0012110200a10002207450dd00220072010200a200d200d200a4b1b10f8021a201010010c9b010b200a10002207450da6020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a410a3a0000200b41086a220d41216a2107200d41016a210a024002400240200d2d00004101470d0020012802a4012004280200220d470d01200d41016a2210200d490da202200d4101742209201020102009491b22094100480da202200d450d4020012802a001210f200910002210450db4022010200f2009200d200d20094b1b10f8021a200f10010c410b20012802a4012004280200220d470d01200d41016a2210200d490da102200d4101742209201020102009491b22094100480da102200d450d4220012802a001210f200910002210450db4022010200f2009200d200d20094b1b10f8021a200f10010c430b20012802a00121100c400b20012802a00121100c420b200a10002207450da4020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41033a000002400240200b41086a22072d0000220d4101460d00200d4102470d0120012802a4012004280200220d470d26200d41016a220a200d490d9d02200d4101742210200a200a2010491b22104100480d9d02200d450d6920012802a001210920101000220a450dbe02200a20092010200d200d20104b1b10f8021a200910010c6a0b20012802a4012004280200220d470d23200d41016a220a200d490d9c02200d4101742210200a200a2010491b22104100480d9c02200d450d6520012802a001210920101000220a450dbc02200a20092010200d200d20104b1b10f8021a200910010c660b20012802a4012004280200220d470d25200d41016a2207200d490d9b02200d410174220a20072007200a491b220a4100480d9b02200d450d6a20012802a0012110200a10002207450dbd0220072010200a200d200d200a4b1b10f8021a201010010c6b0b200a10002207450da2020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41043a0000200b41086a2d0000417f6a220d41044b0d280240200d0e05002621251f000b20012802a4012004280200220d470d5e200d41016a2207200d490d9802200d410174220a20072007200a491b220a4100480d9802200d450de20120012802a0012110200a10002207450de20220072010200a200d200d200a4b1b10f8021a201010010ce3010b200a10002207450da0020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a000002400240200b41086a220d2d000022074101460d0020074102470d0120012802a40120042802002207470d25200741016a220a2007490d970220074101742210200a200a2010491b22104100480d97022007450d6f20012802a001210920101000220a450dbc02200a200920102007200720104b1b10f8021a200910010c700b20012802a40120042802002207470d21200741016a220a2007490d960220074101742210200a200a2010491b22104100480d96022007450d6820012802a001210920101000220a450db902200a200920102007200720104b1b10f8021a200910010c690b200141003a00910220012802a40120042802002207470d24200741016a220a2007490d950220074101742210200a200a2010491b22104100480d95022007450d7020012802a001210920101000220a450dbb02200a200920102007200720104b1b10f8021a200910010c710b200a10002207450d9e020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41083a0000024020012802a4012004280200220d470d00200d41016a2207200d490d9402200d410174220a20072007200a491b220a4100480d9402200d450d0720012802a0012110200a10002207450da00220072010200a200d200d200a4b1b10f8021a201010010c080b20012802a00121070c080b200a10002207450d9c020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000024020012802a4012004280200220d470d00200d41016a2207200d490d9002200d410174220a20072007200a491b220a4100480d9002200d450d0720012802a0012110200a10002207450d9e0220072010200a200d200d200a4b1b10f8021a201010010c080b20012802a00121070c080b200a10002207450d9a020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41063a0000200b41056a21072004280200210d20012802a401210a024002400240200b41046a2d00004101470d00200a200d470d01200d41016a220a200d490d8f02200d4101742210200a200a2010491b22104100480d8f02200d450d3420012802a001210920101000220a450da502200a20092010200d200d20104b1b10f8021a200910010c350b200a200d470d01200d41016a220a200d490d8e02200d4101742210200a200a2010491b22104100480d8e02200d450d3620012802a001210920101000220a450da502200a20092010200d200d20104b1b10f8021a200910010c370b20012802a001210a0c340b20012802a001210a0c360b200a10002207450d98020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200141a0016a200b41046a1022200b41f8006a220b200e470d87020c88020b200a10002207450d96020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41086a2903002106024020012802a401220a2004280200220d6b41084f0d00200d41086a2207200d490d8702200a410174220d20072007200d491b220d4100480d8702200a450d0a20012802a0012110200d10002207450d990220072010200d200a200a200d4b1b10f8021a201010010c0b0b20012802a00121070c0b0b200a10002207450d94020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41073a00000240024002400240200b41046a2d0000417f6a220d41034b0d000240200d0e0400040203000b20012802a4012004280200220d470d22200d41016a2207200d490d8702200d410174220a20072007200a491b220a4100480d8702200d450d920120012802a0012110200a10002207450dbc0220072010200a200d200d200a4b1b10f8021a201010010c93010b20012802a4012004280200220d470d1b200d41016a2207200d490d8602200d410174220a20072007200a491b220a4100480d8602200d450d850120012802a0012110200a10002207450db70220072010200a200d200d200a4b1b10f8021a201010010c86010b20012802a4012004280200220d470d1c200d41016a2207200d490d8602200d410174220a20072007200a491b220a4100480d8602200d450d870120012802a0012110200a10002207450db70220072010200a200d200d200a4b1b10f8021a201010010c88010b20012802a4012004280200220d470d1d200d41016a2207200d490d8502200d410174220a20072007200a491b220a4100480d8502200d450d920120012802a0012110200a10002207450dba0220072010200a200d200d200a4b1b10f8021a201010010c93010b20012802a4012004280200220d470d1f200d41016a2207200d490d8302200d410174220a20072007200a491b220a4100480d8302200d450d940120012802a0012110200a10002207450dba0220072010200a200d200d200a4b1b10f8021a201010010c95010b200a10002207450d92020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a410b3a0000024002400240200b2d00014101470d0020012802a4012004280200220d470d01200d41016a2207200d490d8402200d410174220a20072007200a491b220a4100480d8402200d450d2e20012802a0012110200a10002207450d9b0220072010200a200d200d200a4b1b10f8021a201010010c2f0b20012802a4012004280200220d470d01200d41016a2207200d490d8302200d410174220a20072007200a491b220a4100480d8302200d450d3020012802a0012110200a10002207450d9b0220072010200a200d200d200a4b1b10f8021a201010010c310b20012802a00121070c2e0b20012802a00121070c300b200a10002207450d90020b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41093a00000240024002400240200b41086a22072d0000417f6a220d41034b0d000240200d0e0400040203000b20012802a4012004280200220d470d1e200d41016a2207200d490d8202200d410174220a20072007200a491b220a4100480d8202200d450d950120012802a0012110200a10002207450db90220072010200a200d200d200a4b1b10f8021a201010010c96010b20012802a4012004280200220d470d16200d41016a220a200d490d8102200d4101742210200a200a2010491b22104100480d8102200d450d850120012802a001210920101000220a450db302200a20092010200d200d20104b1b10f8021a200910010c86010b20012802a4012004280200220d470d17200d41016a2207200d490d8002200d410174220a20072007200a491b220a4100480d8002200d450d960120012802a0012110200a10002207450db80220072010200a200d200d200a4b1b10f8021a201010010c97010b20012802a4012004280200220d470d18200d41016a2207200d490dff01200d410174220a20072007200a491b220a4100480dff01200d450d980120012802a0012110200a10002207450db80220072010200a200d200d200a4b1b10f8021a201010010c99010b20012802a4012004280200220d470d1b200d41016a220a200d490dfe01200d4101742210200a200a2010491b22104100480dfe01200d450d9a0120012802a001210920101000220a450db802200a20092010200d200d20104b1b10f8021a200910010c9b010b200d10002207450d8e020b2001200d3602a401200120073602a0012004280200210d0b2004200d41086a3602002007200d6a2006370000200b41f8006a220b200e470df8010cf9010b20012802a4012004280200220d470d3c200d41016a2207200d490df901200d410174220a20072007200a491b220a4100480df901200d450dba0120012802a0012110200a10002207450dc00220072010200a200d200d200a4b1b10f8021a201010010cbb010b20012802a001210a0c430b20012802a4012004280200220d470d3b200d41016a2207200d490df701200d410174220a20072007200a491b220a4100480df701200d450dbb0120012802a0012110200a10002207450dbf0220072010200a200d200d200a4b1b10f8021a201010010cbc010b20012802a001210a0c440b20012802a00121070c460b20012802a001210a0c480b20012802a4012004280200220d470d38200d41016a2207200d490df301200d410174220a20072007200a491b220a4100480df301200d450dc00120012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010cc1010b20012802a4012004280200220d470d39200d41016a2207200d490df201200d410174220a20072007200a491b220a4100480df201200d450dc20120012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010cc3010b20012802a001210a0c4b0b4100211020012802a001210a0c4d0b20012802a4012004280200220d470d37200d41016a2207200d490def01200d410174220a20072007200a491b220a4100480def01200d450dc80120012802a0012110200a10002207450dbe0220072010200a200d200d200a4b1b10f8021a201010010cc9010b20012802a00121070c600b20012802a00121070c650b20012802a00121070c610b20012802a00121070c660b20012802a00121070c6b0b20012802a001210a0c700b20012802a00121070c6c0b20012802a00121070c80010b20012802a00121070c760b20012802a00121070c81010b20012802a00121070c710b20012802a00121070c760b20012802a00121070c780b20012802a001210a0c80010b200910002210450df3010b200120093602a401200120103602a0012004280200210d0b2004200d41016a3602002010200d6a41013a0000200a200141a0016a101e2007200141a0016a101e200b41f8006a220b200e470ddc010cdd010b200910002210450df1010b200120093602a401200120103602a0012004280200210d0b2004200d41016a3602002010200d6a41003a0000200a200141a0016a101e2007200141a0016a101e200b41d8006a2903002106200b41d0006a2903002112024002400240024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490de001200a410174220d20072007200d491b220d4100480de001200a450d0120012802a0012110200d10002207450df40120072010200d200a200a200d4b1b10f8021a201010010c020b20012802a00121070c020b200d10002207450df2010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470dd9010cda010b20101000220a450df0010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41013a00002007200141a0016a101e200b41286a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dd901200a410174220d20072007200d491b220d4100480dd901200a450d0a20012802a0012109200d10002207450df30120072009200d200a200a200d4b1b10f8021a200910010c0b0b20012802a00121070c0b0b20101000220a450dee010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41003a00002007200141a0016a101e200b41286a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dd601200a410174220d20072007200d491b220d4100480dd601200a450d0a20012802a0012109200d10002207450df10120072009200d200a200a200d4b1b10f8021a200910010c0b0b20012802a00121070c0b0b200a10002207450dec010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41026a200141a0016a101e200b41f8006a220b200e470dd0010cd1010b200a10002207450dea010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41f8006a220b200e470dcd010cce010b200d10002207450de8010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b412c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dcd01200a410174220d20072007200d491b220d4100480dcd01200a450d0420012802a0012109200d10002207450de90120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200d10002207450de6010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b412c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dca01200a410174220d20072007200d491b220d4100480dca01200a450d0420012802a0012109200d10002207450de70120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200d10002207450de4010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41306a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dc701200a410174220d20072007200d491b220d4100480dc701200a450d0420012802a0012109200d10002207450de50120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200d10002207450de2010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41306a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490dc401200a410174220d20072007200d491b220d4100480dc401200a450d0420012802a0012109200d10002207450de30120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200d10002207450de0010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470dbe010cbf010b200d10002207450dde010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470dbb010cbc010b20012802a00121070c7f0b20012802a00121070c81010b20012802a00121070c89010b20012802a00121070c85010b20012802a00121070c8a010b20012802a00121070c92010b20101000220a450dd6010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41013a0000200741016a200141a0016a101e200741246a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490db501200a410174220d20072007200d491b220d4100480db501200a450d0a20012802a0012109200d10002207450dd90120072009200d200a200a200d4b1b10f8021a200910010c0b0b20012802a00121070c0b0b20101000220a450dd4010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41023a0000200741016a200141a0016a101e200b41386a2903002106200b41306a2903002112024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490db201200a410174220d20072007200d491b220d4100480db201200a450d1020012802a0012110200d10002207450dd90120072010200d200a200a200d4b1b10f8021a201010010c110b20012802a00121070c110b200a10002207450dd2010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41186a2903002106200b41106a2903002112024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490daf01200a410174220d20072007200d491b220d4100480daf01200a450d1020012802a0012110200d10002207450dd70120072010200d200a200a200d4b1b10f8021a201010010c110b20012802a00121070c110b20101000220a450dd0010b200120103602a4012001200a3602a001200428020021070b2004200741016a360200200a20076a41013a0000200d41016a200141a0016a101e200b41f8006a220b200e470da9010caa010b200d10002207450dce010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470da6010ca7010b20101000220a450dcc010b200120103602a4012001200a3602a001200428020021070b2004200741016a360200200a20076a41023a0000200d41016a200141a0016a101e200d41216a200141a0016a101e200b41d8006a2903002106200b41d0006a2903002112024020012802a40122102004280200220d6b41104f0d00200d41106a2207200d490da6012010410174220d20072007200d491b22074100480da6012010450d0a20012802a001210d20071000220a450dcf01200a200d20072010201020074b1b10f8021a200d10010c0b0b20012802a001210a201021070c0b0b20101000220a450dca010b200120103602a4012001200a3602a0012004280200210720012d00910221100b2004200741016a360200200a20076a20103a0000200d41016a200141a0016a101e200d41246a2802002109024020012802a4012210200428020022076b41044f0d00200741046a220a2007490da30120104101742207200a200a2007491b22074100480da3012010450d0a20012802a001210f20071000220a450dcd01200a200f20072010201020074b1b10f8021a200f10010c0b0b20012802a001210a0c0b0b200d10002207450dc8010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d9d010c9e010b200d10002207450dc6010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d9a010c9b010b20071000220a450dc4010b200120073602a4012001200a3602a0012004280200210d0b200a200d6a22102006370008201020123700002004200d41106a220d360200200b41e8006a2903002106200b41e0006a290300211202402007200d6b410f4b0d00200d41106a2210200d490d9a012007410174220d20102010200d491b220d4100480d9a01200d100021102007450d042010450dc5012010200a200d20072007200d4b1b10f8021a200a10010c050b200a21100c050b20071000220a450dc2010b200120073602a4012001200a3602a001200428020021070b2004200741046a360200200a20076a200936000002400240200d41216a2d0000220d4101460d00200d4102470d0120012802a4012004280200220d470d06200d41016a2207200d490d9801200d410174220a20072007200a491b220a4100480d9801200d450d870120012802a0012110200a10002207450dee0120072010200a200d200d200a4b1b10f8021a201010010c88010b20012802a4012004280200220d470d04200d41016a2207200d490d9701200d410174220a20072007200a491b220a4100480d9701200d450d830120012802a0012110200a10002207450dec0120072010200a200d200d200a4b1b10f8021a201010010c84010b20012802a4012004280200220d470d05200d41016a2207200d490d9601200d410174220a20072007200a491b220a4100480d9601200d450d880120012802a0012110200a10002207450ded0120072010200a200d200d200a4b1b10f8021a201010010c89010b2010450dc0010b2001200d3602a401200120103602a0012004280200210d0b2010200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d91010c92010b20012802a00121070c80010b20012802a00121070c82010b20012802a00121070c84010b200a10002207450dbb010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000200b41086a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d8e01200a410174220d20072007200d491b220d4100480d8e01200a450d0a20012802a0012109200d10002207450dbe0120072009200d200a200a200d4b1b10f8021a200910010c0b0b20012802a00121070c0b0b200a10002207450db9010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41033a0000200b41086a280200210d200b2802102207200141a0016a101b02402007450d002007410574210f2004280200210a20012802a4012110034002400240024002402010200a6b41204f0d00200a41206a2207200a490d90012010410174220a20072007200a491b220a4100480d90012010450d0120012802a0012107200a10002209450d920120092007200a20102010200a4b1b10f8021a200710010c020b20012802a0012109200a21070c020b200a10002209450d90010b2001200a3602a401200120093602a00120042802002107200a21100b2004200741206a220a360200200920076a220741086a200d41086a290000370000200741106a200d41106a290000370000200741186a200d41186a2900003700002007200d290000370000200d41206a210d200f41606a220f0d000b0b200b41146a280200210d200b411c6a2802002207200141a0016a101b2007450d722007410574210f2004280200210a20012802a4012110034002400240024002402010200a6b41204f0d00200a41206a2207200a490d8f012010410174220a20072007200a491b220a4100480d8f012010450d0120012802a0012107200a10002209450d920120092007200a20102010200a4b1b10f8021a200710010c020b20012802a0012109200a21070c020b200a10002209450d90010b2001200a3602a401200120093602a00120042802002107200a21100b2004200741206a220a360200200920076a220741086a200d41086a290000370000200741106a200d41106a290000370000200741186a200d41186a2900003700002007200d290000370000200d41206a210d200f41606a220f0d000c730b0b200a10002207450db7010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41056a200141a0016a101e200b41f8006a220b200e470d85010c86010b200a10002207450db5010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41056a200141a0016a101e200b41256a200141a0016a101e200b41f8006a220b200e470d82010c83010b200d10002207450db3010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d7f0c80010b200a10002207450db1010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41056a200141a0016a101e200b41c8006a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d7f200a410174220d20072007200d491b220d4100480d7f200a450d0720012802a0012109200d10002207450db30120072009200d200a200a200d4b1b10f8021a200910010c080b20012802a00121070c080b200a10002207450daf010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41033a0000200b41056a200141a0016a101e200b41f8006a220b200e470d790c7a0b20101000220a450dad010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41003a0000200741046a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d7a200a410174220d20072007200d491b220d4100480d7a200a450d1920012802a0012109200d10002207450db50120072009200d200a200a200d4b1b10f8021a200910010c1a0b20012802a00121070c1a0b200d10002207450dab010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41256a200141a0016a101e200b41cc006a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d76200a410174220d20072007200d491b220d4100480d76200a450d1920012802a0012109200d10002207450db30120072009200d200a200a200d4b1b10f8021a200910010c1a0b20012802a00121070c1a0b200a10002207450da9010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41056a200141a0016a101e200b41256a200141a0016a101e024020012802a4012004280200220d470d00200d41016a2207200d490d73200d410174220a20072007200a491b220a4100480d73200d450d1c20012802a0012110200a10002207450db20120072010200a200d200d200a4b1b10f8021a201010010c1d0b20012802a00121070c1d0b200a10002207450da7010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41043a0000200b41056a200141a0016a101e024020012802a4012004280200220d470d00200d41016a2207200d490d71200d410174220a20072007200a491b220a4100480d71200d450d1c20012802a0012110200a10002207450db00120072010200a200d200d200a4b1b10f8021a201010010c1d0b20012802a00121070c1d0b200a10002207450da5010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000200b41056a200141a0016a101e200b41f8006a220b200e470d6a0c6b0b200a10002207450da3010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41186a2903002106200b41106a2903002112024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490d6b200a410174220d20072007200d491b220d4100480d6b200a450d1920012802a0012110200d10002207450dab0120072010200d200a200a200d4b1b10f8021a201010010c1a0b20012802a00121070c1a0b200a10002207450da1010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41033a0000200b41186a2903002106200b41106a2903002112024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490d68200a410174220d20072007200d491b220d4100480d68200a450d0d20012802a0012110200d10002207450da50120072010200d200a200a200d4b1b10f8021a201010010c0e0b20012802a00121070c0e0b200a10002207450d9f010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41043a0000200b41186a2903002106200b41106a2903002112024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490d65200a410174220d20072007200d491b220d4100480d65200a450d1620012802a0012110200d10002207450da60120072010200d200a200a200d4b1b10f8021a201010010c170b20012802a00121070c170b20101000220a450d9d010b200120103602a4012001200a3602a0012004280200210d0b2004200d41016a360200200a200d6a41023a0000200741246a2802002109024020012802a40122102004280200220d6b41044f0d00200d41046a220a200d490d622010410174220d200a200a200d491b220d4100480d622010450d1620012802a001210f200d1000220a450da401200a200f200d20102010200d4b1b10f8021a200f10010c170b20012802a001210a0c170b200d10002207450d9b010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d5b0c5c0b200d10002207450d99010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d580c590b200d10002207450d97010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d550c560b200a10002207450d95010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a200b41c5006a2d00003a0000200b41c8006a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d55200a410174220d20072007200d491b220d4100480d55200a450d0d20012802a0012109200d10002207450d990120072009200d200a200a200d4b1b10f8021a200910010c0e0b20012802a00121070c0e0b200a10002207450d93010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a200b41256a2d00003a0000200b41f8006a220b200e470d4f0c500b200d10002207450d91010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d4c0c4d0b200d10002207450d8f010b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41f8006a220b200e470d490c4a0b200d1000220a450d8d010b2001200d3602a4012001200a3602a0012004280200210d0b2004200d41046a360200200a200d6a2009360000200b41386a2903002106200b41306a2903002112024020012802a40122102004280200220d6b41104f0d00200d41106a220a200d490d4a2010410174220d200a200a200d491b220d4100480d4a2010450d0420012802a0012109200d1000220a450d8e01200a2009200d20102010200d4b1b10f8021a200910010c050b20012802a001210a0c050b200d10002207450d8b010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41cc006a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d46200a410174220d20072007200d491b220d4100480d46200a450d0420012802a0012109200d10002207450d8c0120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200d1000220a450d89010b2001200d3602a4012001200a3602a0012004280200210d0b200a200d6a220a2006370008200a20123700002004200d41106a360200200741016a200141a0016a101e200b41f8006a220b200e470d400c410b200d10002207450d87010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d3d0c3e0b200a10002207450d85010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41053a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d3d200a410174220d20072007200d491b220d4100480d3d200a450d0420012802a0012109200d10002207450d860120072009200d200a200a200d4b1b10f8021a200910010c050b20012802a00121070c050b200a10002207450d83010b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41033a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d3a200a410174220d20072007200d491b220d4100480d3a200a450d0d20012802a0012109200d10002207450d870120072009200d200a200a200d4b1b10f8021a200910010c0e0b20012802a00121070c0e0b200d10002207450d81010b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000024020012802a4012004280200220d470d00200d41016a2207200d490d37200d410174220a20072007200a491b220a4100480d37200d450d0d20012802a0012110200a10002207450d850120072010200a200d200d200a4b1b10f8021a201010010c0e0b20012802a00121070c0e0b200a10002207450d7f0b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d34200a410174220d20072007200d491b220d4100480d34200a450d1020012802a0012109200d10002207450d840120072009200d200a200a200d4b1b10f8021a200910010c110b20012802a00121070c110b200a10002207450d7d0b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41043a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d31200a410174220d20072007200d491b220d4100480d31200a450d1020012802a0012109200d10002207450d820120072009200d200a200a200d4b1b10f8021a200910010c110b20012802a00121070c110b200a10002207450d7b0b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d2e200a410174220d20072007200d491b220d4100480d2e200a450d1020012802a0012109200d10002207450d800120072009200d200a200a200d4b1b10f8021a200910010c110b20012802a00121070c110b200d10002207450d790b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d280c290b200a10002207450d770b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a200b41096a2d00003a0000200b41f8006a220b200e470d250c260b200a10002207450d750b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b410c6a2802002110024020012802a401220a2004280200220d6b41044f0d00200d41046a2207200d490d25200a410174220d20072007200d491b220d4100480d25200a450d0a20012802a0012109200d10002207450d7820072009200d200a200a200d4b1b10f8021a200910010c0b0b20012802a00121070c0b0b200d10002207450d730b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a201036000002400240200b41096a2d0000220d4101460d00200d4102470d0120012802a4012004280200220d470d0d200d41016a2207200d490d23200d410174220a20072007200a491b220a4100480d23200d450d1b20012802a0012110200a10002207450d7c20072010200a200d200d200a4b1b10f8021a201010010c1c0b20012802a4012004280200220d470d0b200d41016a2207200d490d22200d410174220a20072007200a491b220a4100480d22200d450d1720012802a0012110200a10002207450d7a20072010200a200d200d200a4b1b10f8021a201010010c180b20012802a4012004280200220d470d0c200d41016a2207200d490d21200d410174220a20072007200a491b220a4100480d21200d450d1c20012802a0012110200a10002207450d7b20072010200a200d200d200a4b1b10f8021a201010010c1d0b200d10002207450d710b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d1c0c1d0b200d10002207450d6f0b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41f8006a220b200e470d190c1a0b200d10002207450d6d0b2001200d3602a401200120073602a0012004280200210d0b2004200d41046a3602002007200d6a2010360000200b41286a2903002106200b41206a2903002112024002400240024020012802a401220a2004280200220d6b41104f0d00200d41106a2207200d490d1c200a410174220d20072007200d491b220d4100480d1c200a450d0120012802a0012110200d10002207450d7020072010200d200a200a200d4b1b10f8021a201010010c020b20012802a00121070c020b200d10002207450d6e0b2001200d3602a401200120073602a0012004280200210d0b2007200d6a22072006370008200720123700002004200d41106a360200200b41106a280200210d200b2802182207200141a0016a101b2007450d002007410574210f2004280200210a20012802a4012110034002400240024002402010200a6b41204f0d00200a41206a2207200a490d1d2010410174220a20072007200a491b220a4100480d1d2010450d0120012802a0012107200a10002209450d2120092007200a20102010200a4b1b10f8021a200710010c020b20012802a0012109200a21070c020b200a10002209450d1f0b2001200a3602a401200120093602a00120042802002107200a21100b2004200741206a220a360200200920076a220741086a200d41086a290000370000200741106a200d41106a290000370000200741186a200d41186a2900003700002007200d290000370000200d41206a210d200f41606a220f0d000b0b200b41f8006a220b200e470d150c160b20012802a00121070c0d0b20012802a00121070c0f0b20012802a00121070c110b200a10002207450d680b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41f8006a220b200e470d0f0c100b200a10002207450d660b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000200b41f8006a220b200e470d0c0c0d0b200a10002207450d640b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41f8006a220b200e470d090c0a0b200a10002207450d620b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41013a0000200b41f8006a220b200e470d060c070b200a10002207450d600b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41023a0000200b41f8006a220b200e470d030c040b200a10002207450d5e0b2001200a3602a401200120073602a0012004280200210d0b2004200d41016a3602002007200d6a41003a0000200b41f8006a220b200e470d000b0b200141a0016a41086a2204280200210d20012802a401210720012802a001210b20044200370300200142003703a00141cef1c100410d200141a0016a1002200141106a41086a2004290300370300200120012903a001370310200141106a4110200b200d100302402007450d00200b10010b02402008450d00200541f8006c41f8006a210741002104034002400240200c20046a220b2d0000220d4108460d000240200d4105460d00200d4104470d02200b41086a2d00000d02200b41146a280200450d02200b41106a28020010012007200441f8006a2204470d030c040b200b41046a2d00004103470d010240200b410c6a280200450d00200b41086a28020010010b200b41186a280200450d01200b41146a28020010012007200441f8006a2204470d020c030b200b41086a280200450d00200b41046a28020010010b2007200441f8006a2204470d000b0b02402000450d00201110010b20014180036a24000f0b1018000b1018000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200d41011019000b200941011019000b200941011019000b200d41011019000b201041011019000b201041011019000b200a41011019000b200a41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b201041011019000b201041011019000b200a41011019000b201041011019000b200d41011019000b201041011019000b201041011019000b200d41011019000b200d41011019000b200741011019000b200741011019000b200d41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200d41011019000b200a41011019000b200a41011019000b201041011019000b200d41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b201041011019000b200d41011019000b200d41011019000b200d41011019000b200a41011019000b200a41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200a41011019000b200a41011019000b200d41011019000b200a41011019000b200a41011019000b200a41011019000b200d41011019000b200a41011019000b200a41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200d41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200a41011019000b200441081019000b200d41081019000b41eac4c10041331042000b9f0101017f230041c0006b22012400200141ff0036020c200141b2d1c0003602082001410d36021420012000360210200141306a410c6a410c3602002001412c6a4102360200200141186a410c6a4102360200200141013602342001418489c2003602202001410236021c200141a4aec3003602182001200141106a3602382001200141086a3602302001200141306a360228200141186a41b4aec3001071000b4b00200041ddf5c10036020420004100360200200041206a410a3602002000411c6a41f4b7c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b3400200041ada0c10036020420004100360200200041146a4108360200200041106a41ecbdc200360200200041086a42083702000b4b00200041ddf5c10036020420004100360200200041206a41053602002000411c6a4194c2c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000bba0c05077f017e037f047e047f23004190016b2202240002400240024002400240411210002203450d002002421237027420022003360270200241f0006a4197e5c000411210252002280270210302400240024020022802742204200228027822056b41044f0d00200541046a22062005490d0420044101742207200620062007491b22074100480d042004450d01200710002208450d072008200320072004200420074b1b10f80221082003100120072104200821030c020b200541046a21060c010b200710002203450d05200721040b200320056a200136000042002109200241f0006a41086a220542003703002002420037037020032006200241f0006a1002200241086a20052903003703002002200229037037030002400240200241104188f0c100410041001004417f460d00200241f0006a41186a22064200370300200241f0006a41106a42003703002005420037030020024200370370410020024110200241f0006a41204100100422052005417f461b220141204922080d04200241d0006a41186a220a2006290300370300200241d0006a41106a220b200241f0006a41106a2207290300370300200241d0006a41086a220c200241f0006a41086a2205290300370300200220022903703703502006200a29030022093703002007200b290300220d3703002005200c290300220e370300200241106a41086a200e370300200241106a41106a200d370300200241106a41186a2009370300200220022903502209370310200220093703702002420037037820024200370370410020024110200241f0006a41102001412020081b2201100422062006417f461b2206410f4d0d05200529030021092002290370210d200241f0006a41186a2208420037030020074200370300200542003703002002420037037020024110200241f0006a41202006411020064110491b20016a220510042206417f460d012006411f4d0d01200241d0006a41186a2206200241f0006a41186a2207290300370300200241d0006a41106a2201200241f0006a41106a2208290300370300200241d0006a41086a220a200241f0006a41086a220b2903003703002002200229037037035020072006290300220e37030020082001290300220f370300200b200a2903002210370300200241306a41086a2010370300200241306a41106a200f370300200241306a41186a200e37030020022002290350220e3703302002200e370370200242003703782002420037037020024110200241f0006a4110200541206a10042205417f460d052005410f4d0d05200241f0006a41086a2205290300210e2002290370210f200241f0006a41186a220c200241106a41186a2206290300370300200241f0006a41106a2211200241106a41106a22072903003703002005200241106a41086a2201290300370300200241d0006a41086a2212200241306a41086a2208290300370300200241d0006a41106a2213200241306a41106a220a290300370300200241d0006a41186a2214200241306a41186a220b2903003703002002200229031037037020022002290330370350200b200c290300370300200a2011290300370300200820052903003703002001201229030037030020072013290300370300200620142903003703002002200229037037033020022002290350370310200041206a200e370300200041186a200f370300200041106a20093703002000200d370308200041286a2002290330370300200041306a2008290300370300200041386a200a290300370300200041c0006a200b290300370300200041c8006a2002290310370300200041d0006a2001290300370300200041d8006a2007290300370300200041e0006a2006290300370300420121090b2000200937030002402004450d00200310010b20024190016a24000f0b2008200241d0006a41186a290000370300200241f0006a41106a200241d0006a41106a290000370300200241f0006a41086a200241d0006a41086a2900003703002002200229005037037041eac4c10041331042000b411241011019000b1018000b2006200241d0006a41186a290000370300200241f0006a41106a200241d0006a41106a290000370300200241f0006a41086a200241d0006a41086a290000370300200220022900503703700b41eac4c10041331042000b200741011019000bc20201037f23004180016b22022400200028020021000240024002400240200128020022034110710d0020034120710d01200020011058210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441d7006a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141ac94c0004102200220006a4180016a410020006b1077210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441376a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141ac94c0004102200220006a4180016a410020006b1077210020024180016a240020000f0b2003418001107a000b2003418001107a000bc21002117f017e230041206b220224002000280204210320002802002104410121050240200128021841222001411c6a2802002802101102000d000240024002402003450d00200420036a2106200141186a21072001411c6a2108200421094100210a4100210b02400240024003402009210c200941016a2100024002400240024020092c0000220d4100480d00200d41ff0171210d0c010b02400240024020002006460d0020002d0000413f71210e200941026a22092100200d411f71210f200d41ff0171220d41e001490d010c020b4100210e20062109200d411f71210f200d41ff0171220d41e0014f0d010b200e200f41067472210d0c010b0240024020092006460d00200941016a2200211020092d0000413f71200e41067472210e200d41f001490d010c030b200621104100200e41067472210e200d41f0014f0d020b200e200f410c7472210d0b200021090c010b0240024020102006460d00201041016a210920102d0000413f71210d0c010b4100210d200021090b200e410674200f411274418080f0007172200d72220d418080c400460d020b41022100024002400240024002400240200d41776a220f411e4b0d0041f400210e0240200f0e1f06000303050303030303030303030303030303030303030303020303030302060b41ee00210e0c050b200d41dc00470d010b0c010b0240200d1080010d00024002400240024002400240200d41ffff034b0d00200d4180fe037141087621114198a4c000210e4100210f0240024002400340200e41026a2112200f200e2d000122006a211002400240200e2d0000220e2011470d002010200f490d05201041b0024f0d04200f41e8a4c0006a210e03402000450d022000417f6a2100200e2d0000210f200e41016a210e200f200d41ff0171470d000c0d0b0b200e20114b0d022010210f2012210e201241e8a4c000470d010c020b2010210f2012210e201241e8a4c000470d000b0b200d41ffff0371210f4197a7c00021004101210e0340200041016a21100240024020002d000022124118744118752211417f4c0d0020102100200f20126b220f4100480d060c010b0240201041d3a9c000460d00200041016a2110200041026a2100200f201141ff007141087420102d0000726b220f41004e0d010c060b41b092c200104f000b200e410173210e200041d3a9c000470d000c040b0b201041af021076000b200f2010107a000b200d41ffff074b0d03200d4180fe0371410876211141d3a9c000210e4100210f02400340200e41026a2112200f200e2d000122006a211002400240200e2d0000220e2011470d002010200f490d062010419f014f0d05200f4195aac0006a210e03402000450d022000417f6a2100200e2d0000210f200e41016a210e200f200d41ff0171470d000c0a0b0b200e20114b0d022010210f2012210e20124195aac000470d010c020b2010210f2012210e20124195aac000470d000b0b200d41ffff0371210f41b3abc00021004101210e0340200041016a21100240024020002d000022124118744118752211417f4c0d0020102100200f20126b220f4100480d030c010b0240201041b0aec000460d00200041016a2110200041026a2100200f201141ff007141087420102d0000726b220f41004e0d010c030b41b092c200104f000b200e410173210e200041b0aec000470d000b0b200e410171450d040c030b2010419e011076000b200f2010107a000b200d4190fc476a4190fc0b490d01200d41e28b746a41e28d2c490d01200d419fa8746a419f18490d01200d41dee2746a410e490d01200d41feffff0071419ef00a460d01200d41a9b2756a4129490d01200d41cb91756a410a4d0d010b200b200c6b20096a210b20062009470d040c050b200d41017267410276410773ad4280808080d000842113410321000b200d210e0c010b41f200210e0b20022003360204200220043602002002200a3602082002200b36020c200b200a490d030240200a450d00200a2003460d00200a20034f0d042004200a6a2c000041bf7f4c0d040b0240200b450d00200b2003460d00200b20034f0d042004200b6a2c000041bf7f4c0d040b20072802002004200a6a200b200a6b200828020028020c1100000d0202400340024002400240024002400240024020004101460d0041dc00210a024020004102460d0020004103470d092013422088a741ff0171417f6a220041044b0d09024020000e050006040503000b201342ffffffff8f608321134103210041fd00210a0c070b410121000c060b41002100200e210a0c050b201342ffffffff8f60834280808080c0008421130c030b201342ffffffff8f60834280808080208421134103210041fb00210a0c030b201342ffffffff8f60834280808080308421134103210041f500210a0c020b200e2013a7220f410274411c7176410f712200413072200041d7006a2000410a491b210a0240200f450d002013427f7c42ffffffff0f832013428080808070838421130c010b201342ffffffff8f60834280808080108421130b410321000b2007280200200a2008280200280210110200450d000c040b0b410121000240200d418001490d0041022100200d418010490d0041034104200d41808004491b21000b2000200b6a210a200b200c6b20096a210b20062009470d000b0b200a450d03200a2003460d030240200a20034f0d002004200a6a22002c000041bf7f4a0d050b20042003200a2003107d000b200241206a240041010f0b20022002410c6a3602182002200241086a36021420022002360210200241106a108501000b4100210a0b2004200a6a21000b200141186a220b28020020002003200a6b2001411c6a220a28020028020c1100000d00200b2802004122200a28020028021011020021050b200241206a240020050b3400200041cda0c10036020420004100360200200041146a4101360200200041106a4184c6c200360200200041086a420a3702000b4b00200041ddf5c10036020420004100360200200041206a41023602002000411c6a41c0c6c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b130020004102360204200041d0c7c2003602000b130020004103360204200041b8c8c2003602000b13002000410536020420004184cac2003602000b975a09017f017e017f047e097f027e017f027e077f230041b0046b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001450d00200241f0036a41086a22014200370300200242003703f00341daa3c1004115200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d003200241d0036a41104188f0c100410041001004417f460d01200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0320022903e00221030c020b200241f0036a21040c070b420521030b200241f0036a41086a22014200370300200242003703f00341d9f1c0004115200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d00302400240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d034200210520022903e00220037e22034200510d010c050b4200210542e80720037e22034200520d040b200241f0036a41086a22012005370300200220053703f00341b1ecc000411c200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d0030240200241d0036a41104188f0c100410041001004417f460d00200242003703e802200242003703e002200241d0036a4110200241e0026a4110410010042201417f460d032001410f4d0d03200241e8026a290300210820022903e00221050c050b420021080c040b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b2000200320032000541b22062005510d0a42002100200241f0036a41086a22014200370300200242003703f00341b1ecc000411c200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d00302400240200241d0036a41104188f0c100410041001004417f460d00200242003703e802200242003703e002200241d0036a4110200241e0026a4110410010042201417f460d0b2001410f4d0d0b200241e8026a290300210720022903e00221000c010b420021070b200241d0026a200020072003421086200680420010fc0220022903d002421088200241d8026a2903002200423086842105200042108821080b200241e0026a41086a22014200370300200242003703e00241c8f2c0004112200241e0026a1002200241f0036a41086a2001290300370300200220022903e0023703f003024002400240200241f0036a41104188f0c100410041001004417f460d00200242103702d4032002200241f0036a3602d003200241e0026a200241d0036a103620022802e0022209450d0d20022802e402210a2009410120091b210b200241e8026a280200410020091b22040d010c020b410021094100410141001b210b4100410041001b2204450d010b200b20044105746a210c200241f0026a210d200b210e0340411c10002201450d032002421c3702e402200220013602e002200241e0026a4196d1c000411c1025200241f0036a41086a220f200241e0026a41086a2201280200360200200220022903e0023703f003200e200241f0036a101e20022802f4032110200241e0026a20022802f0032211200f28020010b101200d290300420020022903e002420151220f1b210020012903004200200f1b210302402010450d00201110010b02400240024002402005200320052003200554200020085420002008511b220f1b22127d2206200820002008200f1b22137d2005201254ad7d220784500d00200241e0026a200e10af012001280200211120022802e0022114200241c0026a200e10b001200241c0026a41086a290300210020022903c00221032011450d0120114105742210210f201421010340200241b0026a200110b001200241b0026a41086a29030020007c20022903b002220020037c2203200054ad7c2100200141206a2101200f41606a220f0d000b20004200200342015620004200522000501b22011b21002003420120011b210302402011450d002003200084500d0b201421010340200241a0026a200110b00120024190026a20022903a002200241a0026a41086a2903002006200710fc0220024180026a20022903900220024190026a41086a2903002003200010fb02200120022903800220024180026a41086a29030010c201200141206a2101201041606a22100d000b0b200241e0016a200e10b00120032000844200510d09200241e0016a41086a290300211520022903e00121160c020b42002100420021030c020b200241d0016a200e10b00120004200200342015620004200522000501b22011b21002003420120011b2103200241d0016a41086a290300211520022903d00121160b200241c0016a201620152006200710fc02200241b0016a20022903c001200241c0016a41086a2903002003200010fb02200241b0016a41086a290300210320022903b001210020022802e402450d00201410010b200e200020127c2206200320137c2006200054ad7c10c201200e41206a2201210e2001200c470d000b0b200241a0016a200520082004ad2206420010fc02200241f8026a2008370300200241e0026a41106a2005370300200241e0026a41086a41003a0000200241033a00e002200241e0026a10b401200241f0036a41086a22014200370300200242003703f00341cdecc0004112200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d003200241d0036a41104188f0c1004100410010042101200241a0016a41086a290300210020022903a0012103024002402001417f460d00200242003703e802200242003703e002200241d0036a4110200241e0026a4110410010042201417f460d0920014110490d09200242003703e802200242003703e002200241d0036a4110200241e0026a4110411010042201417f460d092001410f4d0d09200241e8026a290300210720022903e00221050c010b42002105420021070b20024190016a200520072006420010fc0202402003200084500d00200229039001220620024190016a41086a290300220584500d0042002107200241f0036a41086a22014200370300200242003703f00341d9f0c1004116200241f0036a1002200241d0036a41086a220f2001290300370300200220022903f0033703d00302400240200241d0036a41104188f0c100410041001004417f460d00200242003703e802200242003703e002200241d0036a4110200241e0026a4110410010042210417f460d0e2010410f4d0d0e200241e8026a290300211220022903e00221080c010b42002108420021120b20024180016a200820067d201220057d2008200654ad7d2006200510fb02200241f0006a20022903800120024180016a41086a2903002003200010fc0220014200370300200242003703f00341cdc2c000410c200241f0036a1002200f2001290300370300200220022903f0033703d003200241d0036a41104188f0c1004100410010042101200241f0006a41086a290300210020022903702103024002402001417f460d00200242003703e802200242003703e002200241d0036a4110200241e0026a4110410010042201417f460d0f2001410f4d0d0f200241e8026a290300210620022903e00221070c010b420021060b2002200720037c22033703e0022002200620007c2003200754ad7c3703e802200241f0036a41086a22014200370300200242003703f00341cdc2c000410c200241f0036a1002200241d0036a41086a2001290300370300200220022903f0033703d003200241d0036a4110200241e0026a411010030b200241f0036a21042009450d00200a450d00200b10010b200441086a220f420037000020044200370000419bf2c000411420041002200241d0036a41086a2201200f290000370300200220042900003703d003420021000240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0220022903e00221000b20014200370300200242003703d00341b1d2c0004115200241d0036a1002200241f0036a41086a2001290300370300200220022903d0033703f0030240200241f0036a41104188f0c100410041001004417f460d00200241d0036a41086a22014200370300200242003703d00341b1d2c0004115200241d0036a1002200441086a2001290300370000200420022903d0033700002004411010080c0d0b200441086a220142003700002004420037000041dfecc000411b20041002200241d0036a41086a220f2001290000370300200220042900003703d003420021030240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0520022903e00221030b200142003700002004420037000041faecc000411620041002200f2001290000370300200220042900003703d00302400240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0720022903e00222064200520d0141d8acc200104f000b42e80721060b200020037d2006824200510d0c0c0d0b411c41011019000b41eac4c10041331042000b41b8c7c200104f000b200241f0016a201410b00141b8c7c200104f000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41b8c7c200104f000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200441086a22014200370000200442003700004190edc000411220041002200241d0036a41086a2001290000370300200220042900003703d003024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0220022903e00242017c21000c010b420121000b200220003703e002200441086a22014200370000200442003700004190edc000411220041002200241d0036a41086a220f2001290000370300200220042900003703d003200241d0036a4110200241e0026a41081003200142003700002004420037000041a2edc000411a20041002200f2001290000370300200220042900003703d0030240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d02200220022903e00222003703a004200441086a220142003700002004420037000041faecc000411620041002200241d0036a41086a2001290000370300200220042900003703d00302400240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d05200020022903e002520d010c020b200042e807510d010b200220003703e002200441086a220142003700002004420037000041faecc000411620041002200241d0036a41086a220f2001290000370300200220042900003703d003200241d0036a4110200241e0026a410810032001420037000020044200370000419bf2c000411420041002200f2001290000370300200220042900003703d003420021000240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0520022903e00221000b200220003703e002200142003700002004420037000041dfecc000411b20041002200f2001290000370300200220042900003703d003200241d0036a4110200241e0026a410810030b4108210b200441086a220142003700002004420037000041e7d0c000411220041002200241d0036a41086a2001290000370300200220042900003703d00341002117024002400240200241d0036a41104188f0c100410041001004417f460d00200242103702f4032002200241d0036a3602f003200241e0026a200241f0036a103620022802e002220a450d0720022802e40221184105210f200241e8026a2802004100200a1b221041057422010d010c020b4100210a4105210f4100410041001b22104105742201450d010b2001200f752217ad42307e2200422088a70d092000a7220f4100480d09200f1000220b450d060b0240200a4101200a1b221920016a22092019460d00201041057441606a410576211a200b21102019210e0340200241e0026a41186a2214200e41186a290000370300200241e0026a41106a220c200e41106a290000370300200241e0026a41086a220d200e41086a2900003703002002200e2900003703e002200241f0036a200241e0026a10b201200241f0036a41086a280200210120022802f0032111200241e0006a200241e0026a10b001200241e0006a41086a29030021002002290360210302402001450d002001410574210f201121010340200241d0006a200110b001200241d0006a41086a29030020007c2002290350220020037c2203200054ad7c2100200141206a2101200f41606a220f0d000b0b200e41206a210e024020022802f403450d00201110010b200241d0036a41186a22012014290300370300200241d0036a41106a220f200c290300370300200241d0036a41086a2211200d290300370300200220022903e0023703d0032010200037030820102003370300201041286a2001290300370300201041206a200f290300370300201041186a2011290300370300201020022903d003370310201041306a2110200e2009470d000b201a41016a2101200a450d080c070b41002101200a0d060c070b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200f41081019000b2018450d00201910010b200441086a220f42003700002004420037000041f9d0c000411d20041002200241d0036a41086a200f290000370300200220042900003703d003024002400240024002400240200241d0036a41104188f0c100410041001004417f460d00200241003602e002200241d0036a4110200241e0026a41044100100441016a41044d0d02200120022802e0024f0d010c190b20014104490d180b41002109200b2001410041202001676b10c30142002100200441086a220f42003700002004420037000041bcedc000411620041002200241d0036a41086a200f290000370300200220042900003703d0030240200241d0036a41104188f0c100410041001004417f460d00200241003602e002200241d0036a4110200241e0026a41044100100441016a41044d0d0220022802e00221090b024002402001450d00200120012009200920014b1b417f6a220f4d0d04200b41086a2903002103200b200f41306c6a220f2903002107200f41086a2903002105200b29030021004110210f411010002210450d010c050b4200210342002107420021054110210f4110100022100d040b200f41011019000b41eac4c10041331042000b41eac4c10041331042000b41f0ccc200200f2001104e000b2010200037000020102003370008024002400240024041201000220f450d00200f2010290000370000200f41086a201041086a29000037000020101001200f41186a2005370000200f2007370010200441086a221042003700002004420037000041cdecc000411220041002200241d0036a41086a2010290000370300200220042900003703d003200241d0036a4110200f41201003200f10014100211a02402009200141306c221041306d220f200f20094b1b221b450d00201bad4205862200422088a70d052000a7220f4100480d05200f1000221c450d022009450d040c030b4101211c4100211b20090d020c030b412041011019000b200f41011019000b200b20106a200b460d00200141306c210d200241e0026a41106a21104101210e201c210f200b21010340200241e0026a41286a200141286a290300370300200241e0026a41206a200141206a290300370300200241e0026a41186a200141186a2903003703002010200141106a290300370300200241e0026a41086a200141086a290300370300200241d0036a41086a2211201041086a290300370300200241d0036a41106a2214201041106a290300370300200241d0036a41186a220c201041186a290300370300200220012903003703e002200220102903003703d003200f41186a200c290300370000200f41106a2014290300370000200f41086a2011290300370000200f20022903d0033700002009200e221a460d01200141306a2101201a41016a210e200f41206a210f200d41506a220d0d000b0b02402017450d00200b10010b200241e0026a41086a22014200370300200242003703e00241c8f2c0004112200241e0026a1002200241f0036a41086a2001290300370300200220022903e0023703f003024002400240200241f0036a41104188f0c100410041001004417f460d00200242103702d4032002200241f0036a3602d003200241e0026a200241d0036a103620022802e0022219450d1220022802e40221184101210a2019410120191b2117200241e8026a280200410020191b22010d010c020b410021194101210a4100410141001b21174100410041001b2201450d010b2001410574210d201721100340411c10002201450d052002421c3702e402200220013602e002200241e0026a41ddd3c000411c1025200241f0036a41086a2201200241e0026a41086a220c280200360200200220022903e0023703f0032010200241f0036a101e2001280200210f20022802f403211420022802f0032111200441086a220e4200370000200442003700002011200f20041002200241d0036a41086a220f200e290000370300200220042900003703d003200241d0036a4110100802402014450d00201110010b411210002211450d06200242123702e402200220113602e002200241e0026a4181cfc000411210252001200c280200360200200220022903e0023703f0032010200241f0036a101e2001280200211420022802f403210920022802f0032111200f4200370300200242003703d00320112014200241d0036a10022001200f290300370300200220022903d0033703f003024002400240200241f0036a41104188f0c100410041001004417f470d004100410041001b211420090d010c020b200241003602e002200241f0036a4110200241e0026a410441001004200a6a41044d0d0620022802e002210b200f4200370300200242003703d00320112014200241d0036a1002200e200f290300370000200420022903d003370000200441101008200b410041011b21142009450d010b201110010b024020144102490d00411210002211450d0b200242123702e402200220113602e002200241e0026a4181cfc000411210252001200c280200360200200220022903e0023703f0032010200241f0036a101e2001280200211120022802f403210c20022802f003210120022014417f6a3602e002200e4200370000200442003700002001201120041002200f200e290000370300200220042900003703d003200241d0036a4110200241e0026a41041003200c450d00200110010b201041206a2110200d41606a220d0d000b0b02402019450d002018450d00201710010b201c201a4105746a211d0240201a450d00201c21090340200241a0046a200910b201411c10002201450d072002421c3702e402200220013602e002200241e0026a41ddd3c000411c1025200241f0036a41086a2201200241e0026a41086a220b280200360200200220022903e0023703f0032009200241f0036a101e2001280200211720022802f403211820022802f003210a200b4100360200200242013703e00220022802a0042119200241a0046a41086a2802002201200241e0026a101b024002402001450d002001410574210c4100200b280200220f6b211120022802e002211420022802e402210e2019210d0340200d21010240200e20116a411f4b0d00200f41206a2210200f490d06200e410174220d20102010200d491b22104100480d0620101000210d02400240200e450d00200d450d09200d20142010200e200e20104b1b10f8021a201410010c010b200d450d080b200d21142010210e0b200141206a210d2014200f6a22102001290000370000201041186a200141186a290000370000201041106a200141106a290000370000201041086a200141086a290000370000201141606a2111200f41206a210f200c41606a220c0d000b200b200f3602002002200e3602e402200220143602e0020c010b200b280200210f20022802e402210e20022802e00221140b200441086a2201420037000020044200370000200a201720041002200241d0036a41086a2001290000370300200220042900003703d003200241d0036a41102014200f10030240200e450d00201410010b02402018450d00200a10010b200941206a2109024020022802a404450d00201910010b2009201d470d000b0b201aad2200421b88a70d0d2000420586a72201417f4c0d0d024002402001450d0020011000220f0d01200141011019000b4101210f0b200f201c201a410574220c10f8022109200241003602e802200242013703e002201a200241e0026a101b02400240201a450d004100200241e0026a41086a280200220f6b211120022802e002211420022802e402210e2009210d0340200d21010240200e20116a411f4b0d00200f41206a2210200f490d04200e410174220d20102010200d491b22104100480d0420101000210d02400240200e450d00200d450d0f200d20142010200e200e20104b1b10f8021a201410010c010b200d450d0e0b200d21142010210e0b200141206a210d2014200f6a22102001290000370000201041186a200141186a290000370000201041106a200141106a290000370000201041086a200141086a290000370000201141606a2111200f41206a210f200c41606a220c0d000b200241e8026a200f3602002002200e3602e402200220143602e0020c010b200241e8026a280200210f20022802e402210e20022802e00221140b200441086a220142003700002004420037000041c8f2c000411220041002200241d0036a41086a2001290000370300200220042900003703d003200241d0036a41102014200f10030240200e450d00201410010b0240201a450d00200910010b200241c8006a201c201d102e41002111024002400240200228024c220c200228024822016b220f410576220b450d00200f416071220f4100480d03200f1000220d450d132001200c470d010c020b4101210d4100210b2001200c460d010b200c416020016b6a4105762109200d210f0340200141086a2900002100200141106a290000210320012900002106200241e0026a41186a2210200141186a290000370300200241e0026a41106a220e2003370300200241e0026a41086a22112000370300200220063703e002200241f0036a41186a22142010290300370300200241f0036a41106a2210200e290300370300200241f0036a41086a220e2011290300370300200220022903e0023703f003200f41186a2014290300370000200f41106a2010290300370000200f41086a200e290300370000200f20022903f003370000200f41206a210f200c200141206a2201470d000b200941016a21110b410610002201450d0e200242063702e402200220013602e002200241e0026a41bab6c10041061025200241f8036a220120022802e802360200200220022903e0023703f003200241f0036a41b7b6c1004103102520022802f403210f20022802f003220e200128020010c40121100240200f450d00200e10010b41002101200241d0036a410020101046024002400240024020022802d8032011470d004100210e20022802d0032214210f200d21100240410020114f0d00034002402014200d460d00200f2010412010fa020d030b200f41206a210f201041206a2110200e41016a220e2011490d000b0b20022802d403450d01201410010c010b200241e0026a41086a220c200241d0036a41086a280200360200200220022903d0033703e002200241e0026a10c50102402011450d002011410574211041002101200d210f0340200220013602a00441061000220e450d0b200242063702e4022002200e3602e002200241e0026a41bab6c10041061025200241f0036a41086a220e200c280200360200200220022903e0023703f003200241f0036a200241a0046a4104102520022802f403211120022802f0032214200e280200200f10c60102402011450d00201410010b200f41206a210f200141016a2101201041606a22100d000b0b41061000220f450d14200242063702e4022002200f3602e002200241e0026a41bab6c10041061025200241f8036a220f20022802e802360200200220022903e0023703f003200241f0036a41b7b6c1004103102520022802f403211020022802f003220e200f28020010c401210902402010450d00200e10010b0240200920014d0d002001210f0340410610002210450d0c200242063702e402200220103602e002200241e0026a41bab6c10041061025200241f0036a41086a2210200241e0026a41086a220c280200360200200220022903e0023703f003200241f0036a41b7b6c1004103102520022802f403210e20022802f0032214201028020010c40121110240200e450d00201410010b02402011200f4d0d002002200f3602a00441061000220e450d10200242063702e4022002200e3602e002200241e0026a41bab6c100410610252010200c280200360200200220022903e0023703f003200241f0036a200241a0046a4104102520022802f403210e20022802f003221120102802001008200e450d00201110010b2009200f41016a220f470d000b0b41061000220f450d15200242063702e4022002200f3602e002200241e0026a41bab6c10041061025200241f8036a220f20022802e802360200200220022903e0023703f003200241f0036a41b7b6c10041031025200f280200211020022802f403210e20022802f003210f200220013602e002200f2010200241e0026a41041003200e450d00200f1001200b0d010c020b200b450d010b200d10010b200441086a220142003700002004420037000041d2edc000411420041002200241d0036a41086a2001290000370300200220042900003703d00302400240200241d0036a41104188f0c100410041001004417f460d00200241003602e002200241d0036a4110200241e0026a41044100100441016a41044d0d0d20022802e00221010c010b41c0843d21010b200241386a200720052001ad420010fc02200241286a2002290338200241386a41086a290300428094ebdc03420010fb022002200241286a41086a2903003703e802200220022903283703e002200441086a220142003700002004420037000041accfc000411b20041002200241d0036a41086a220f2001290000370300200220042900003703d003200241d0036a4110200241e0026a41101003200142003700002004420037000041e6edc000411520041002200f2001290000370300200220042900003703d00302400240200241d0036a41104188f0c100410041001004417f460d00200241003602e002200241d0036a4110200241e0026a41044100100441016a41044d0d0e20022802e00221010c010b413c21010b200241186a200720052001ad420010fc02200241086a2002290318200241186a41086a290300428094ebdc03420010fb022002200241086a41086a2903003703e802200220022903083703e002200441086a220142003700002004420037000041b1ecc000411c20041002200241d0036a41086a2001290000370300200220042900003703d003200241d0036a4110200241e0026a41101003201b450d14201c10010c140b1018000b201041011019000b41eac4c10041331042000b411c41011019000b411241011019000b411c41011019000b410641011019000b410641011019000b411241011019000b201041011019000b410641011019000b41eac4c10041331042000b41eac4c10041331042000b102c000b410641011019000b41eac4c10041331042000b200f41011019000b410641011019000b410641011019000b2017450d00200b10010b200241f0036a41086a22014200370300200242003703f00341c8f2c0004112200241f0036a1002200241e0026a41086a2001290300370300200220022903f0033703e00202400240024002400240200241e0026a41104188f0c100410041001004417f460d00200242103702d4032002200241e0026a3602d003200241f0036a200241d0036a103620022802f0032201450d02200241f8036a280200211020022802f403210e0c010b410021010b20022001410120011b220f3602e8022002200e410020011b3602e4022002200f3602e0022002200f2010410020011b4105746a3602ec0220024190046a200241e0026a10400240410e10002201450d002002420e3702e402200220013602e002200241e0026a41d79bc100410e1025200241f8036a220120022802e802360200200220022903e0023703f003200241f0036a41b7b6c1004103102520022802f403210f20022802f003220e200128020010c40121100240200f450d00200e10010b41002101200241a0046a41002010104120022802a004210d200228029004210c02400240024002400240024002400240200228029804220920022802a804470d00200c210f200d21100340200120094f0d02200141016a220e2001490d020240200c200d460d00200f2010412010fa020d020b201041206a2111200f41206a2114200f41286a210f201041286a2110200e210120142903002011290300510d000b0b2002280294042101200241e0026a10c70120022802f002220f450d0120022802f402450d02200f100120010d030c040b024020022802a404450d00200d10010b200228029404450d04200c10010c040b200441086a220f42003700002004420037000041f0f1c100410d20041002200241d0036a41086a200f290000370300200220042900003703d003420021000240200241d0036a41104188f0c100410041001004417f460d00200242003703e002200241d0036a4110200241e0026a41084100100441016a41084d0d0520022903e00221000b200241f8026a2009360200200241f4026a20013602002002200c3602f002200242003703e802200220003703e002200241003602f803200242013703f00341081000220f450d07200f20003700002002428880808080013702f4032002200f3602f003411010002210450d082010200f290000370000200f1001201042003700082002429080808080023702f403200220103602f003200241f0036a200241e0026a41106a1022200241f0036a41086a280200211020022802f403210e20022802f003210f200441086a221142003700002004420037000041e59bc100411d20041002200241d0036a41086a2011290000370300200220042900003703d003200241d0036a4110200f20101003200e450d00200f10010b2001450d010b200c10010b20022802a404450d00200d1001200241b0046a24000f0b200241b0046a24000f0b41eac4c10041331042000b410e41011019000b41eac4c10041331042000b410841011019000b411041011019000ba20504057f017e017f027e230041c0006b220324002003200010b001024002402003290300200341086a29030084500d00024002400240411410002204450d002003421437023420032004360230200341306a41eeefc10041141025200341206a41086a22042003280238360200200320032903303703202000200341206a101e20042802002105200328022421062003280220210742002108200341306a41086a220942003703002003420037033020072005200341306a1002200420092903003703002003200329033037032002400240200341206a41104188f0c100410041001004417f460d002003420037033820034200370330200341206a4110200341306a4110410010042204417f460d012004410f4d0d01200341386a290300210a200329033021082006450d040c030b4200210a20060d020c030b41eac4c10041331042000b411441011019000b200710010b2000200820017c220b200a20027c200b200854ad7c10aa014200210a200341306a41086a220042003703002003420037033041d9f0c1004116200341306a1002200341206a41086a20002903003703002003200329033037032002400240200341206a41104188f0c100410041001004417f460d002003420037033820034200370330200341206a4110200341306a4110410010042200417f460d032000410f4d0d03200341386a29030021082003290330210a0c010b420021080b200a20017c2201200a542200200820027c2000ad7c220a200854200a2008511b0d00200320013703102003200a370318200341306a41086a220042003703002003420037033041d9f0c1004116200341306a1002200341206a41086a200029030037030020032003290330370320200341206a4110200341106a411010030b200341c0006a24000f0b41eac4c10041331042000bc12d09087f047e0f7f017e077f017e017f017e027f230041d0026b220424000240024020014115490d00410121054101210602400240024002400340200620057141017321070340024002402003450d0020054101710d012000200110da012003417f6a21030c010b2000200110db01200441d0026a24000f0b2001410276220641036c2108200641017421094100210a024020014132490d00410241012000200641306c6a220b41506a290300220c200b290300220d54200b41586a290300220e200b41086a290300220f54200e200f511b22101b2010200c200d20101b220c200b41306a290300220d54200e200f20101b220e200b41386a290300220f54200e200f511b22111b200020062006417f6a221220101b221341306c6a220b290300200d200c20111b54200b41086a290300220c200f200e20111b220e54200c200e511b22146a2000200941306c6a220b41506a290300220c200b290300220d54200b41586a290300220e200b41086a290300220f54200e200f511b22156a200c200d20151b220c20002009410172221641306c6a220b290300220d54200e200f20151b220e200b41086a290300220f54200e200f511b22176a200020092009417f6a221820151b221941306c6a220b290300200d200c20171b54200b41086a290300220c200f200e20171b220e54200c200e511b221a6a2000200841306c6a220b41506a290300220c200b290300220d54200b41586a290300220e200b41086a290300220f54200e200f511b221b6a200c200d201b1b220c200b41306a290300220d54200e200f201b1b220e200b41386a290300220f54200e200f511b220b6a200020082008417f6a221c201b1b221d41306c6a220a290300200d200c200b1b54200a41086a290300220c200f200e200b1b220e54200c200e511b221e6a210a201d200841016a201c2008201b1b200b1b201e1b2108201920162018200920151b20171b201a1b21092013200641016a2012200620101b20111b20141b21060b200a2000200641306c6a220b290300220c2000200941306c6a2210290300220d54200b41086a290300220e201041086a290300220f54200e200f511b220b6a200c200d200b1b220c2000200841306c6a2210290300220d54200e200f200b1b220e201041086a290300220f54200e200f511b22106a210a0240024002400240200020092006200b1b221e41306c6a2215290300200d200c20101b5a201541086a290300220c200f200e20101b220e5a200c200e511b0d00200a41016a220a410b4d0d01024020014101762208450d002000200141306c6a41506a2106200021090340200441a0026a41286a220b200941286a2210290300370300200441a0026a41206a220a200941206a2215290300370300200441a0026a41186a221b200941186a2211290300370300200441a0026a41106a2217200941106a2212290300370300200441a0026a41086a2213200941086a2214290300370300200420092903003703a002200641086a2216290300210e200641106a2218290300210f200641186a2219290300210c200641206a221a290300210d2006290300211f2010200641286a221c2903003703002015200d3703002011200c3703002012200f3703002014200e3703002009201f370300201c200b290300370300201a200a2903003703002019201b2903003703002018201729030037030020162013290300370300200620042903a002370300200941306a2109200641506a21062008417f6a22080d000b0b2001201e417f736a211e4101452007724101710d030c020b200820062009200b1b20101b211e0b200a45452007724101710d010b2000200110dc010d080b024002400240024002402002450d00201e20014f0d0a2000201e41306c6a2206290300200229030054200641086a2209290300220e200241086a290300220f54200e200f511b0d01200441a0026a41286a220a200041286a2212290300370300200441a0026a41206a2215200041206a2213290300370300200441a0026a41186a221b200041186a2214290300370300200441a0026a41106a2211200041106a2208290300370300200441a0026a41086a2217200041086a220b290300370300200420002903003703a0022009290300210e200641106a2210290300210f200641186a2216290300210c200641206a2218290300210d2006290300211f2012200641286a22192903003703002013200d3703002014200c3703002008200f370300200b200e3703002000201f3703002019200a290300370300201820152903003703002016201b2903003703002010201129030037030020092017290300370300200620042903a002370300200b290300210e2000290300210c200441186a22202012290300370300200441106a22212013290300370300200441086a2222201429030037030020042008290300370300200041506a2116200041306a211841002109410020012208417f6a220b4f0d02410621230c030b2001450d080b201e20014f0d06200441a0026a41286a2218200041286a2226290300370300200441a0026a41206a2219200041206a2228290300370300200441a0026a41186a221a200041186a2220290300370300200441a0026a41106a221c200041106a2221290300370300200441a0026a41086a221d200041086a2222290300370300200420002903003703a0022000201e41306c6a2206290300210e200641086a2209290300210f200641106a2208290300210c200641186a220b290300210d200641206a2210290300211f2026200641286a220a2903003703002028201f3703002020200d3703002021200c3703002022200f3703002000200e370300200a201829030037030020102019290300370300200b201a2903003703002008201c2903003703002009201d290300370300200620042903a0023703002022290300210e2000290300210f200441186a22052026290300370300200441106a22072028290300370300200441086a222a202029030037030020042021290300370300200041306a21154100212402402001417f6a2208450d00201521060340200f20062903005a200e200641086a290300220c5a200e200c511b0d01200641306a2106202441016a22242008490d000b0b2000200141306c6a210620082109024003402006210b2009222520244d0d012025417f6a2109200f200b41506a220629030054200e200b41586a290300220c54200e200c511b450d000b0b20252024490d0520082025490d0241800121144100210a41002112410021104100211741800121162015202441306c6a222b21150340200b20156b220641306e21090240024002400240024002400240200641afe0004b221e0d00200941807f6a20092012200a492017201049220872221b1b2106201b450d012016200620081b21162006201420081b21140b20172010470d020c010b2006200641017622166b211420172010470d010b2016450d0141002109200441206a22172110201521060340201020093a00002010200f20062903005a200e200641086a290300220c5a200e200c511b6a2110200641306a2106200941016a22092016490d000b0b2012200a470d020c010b200441206a221021172012200a470d010b02402014450d00200b41506a210641002109200441a0016a2212210a0340200a20093a0000200a200f200629030054200e200641086a290300220c54200e200c511b6a210a200641506a2106200941016a22092014490d000c020b0b200441a0016a220a21120b0240200a20126b2206201020176b2209200920064b1b2213450d002018201520172d000041306c6a220641286a2903003703002019200641206a290300370300201a200641186a290300370300201c200641106a290300370300201d200641086a290300370300200420062903003703a002201520172d000041306c6a2206200b20122d0000417f7341306c6a2209290300370300200641286a200941286a290300370300200641206a200941206a290300370300200641186a200941186a290300370300200641106a200941106a290300370300200641086a200941086a290300370300024020134101460d00410021080340200b201220086a221b2d0000417f7341306c6a22062015201720086a41016a22112d000041306c6a2209290300370300200641286a200941286a290300370300200641206a200941206a290300370300200641186a200941186a290300370300200641106a200941106a290300370300200641086a200941086a290300370300201520112d000041306c6a2206200b201b41016a2d0000417f7341306c6a2209290300370300200641286a200941286a290300370300200641206a200941206a290300370300200641186a200941186a290300370300200641106a200941106a290300370300200641086a200941086a290300370300200841026a2106200841016a2209210820062013490d000b201220096a2112201720096a21170b200b20122d0000417f7341306c6a220620042903a002370300200641286a2018290300370300200641206a2019290300370300200641186a201a290300370300200641106a201c290300370300200641086a201d290300370300201241016a2112201741016a21170b2015201641306c6a201520172010461b2115200b410020146b41306c6a200b2012200a461b210b201e0d000b02400240201720104f0d000340201820152010417f6a22102d000041306c6a220941286a22082903003703002019200941206a220a290300370300201a200941186a221b290300370300201c200941106a2211290300370300201d200941086a2212290300370300200420092903003703a002200b41506a2206290300210c200b41586a2213290300210d200b41606a2214290300211f200b41686a22162903002127200b41706a221e29030021292008200b41786a220b290300370300200a2029370300201b20273703002011201f3703002012200d3703002009200c370300200b2018290300370300201e20192903003703002016201a2903003703002014201c2903003703002013201d290300370300200620042903a0023703002006210b20172010490d000c020b0b201521062012200a4f0d000340200a417f6a220a2d000021092018200641286a22082903003703002019200641206a2210290300370300201a200641186a2215290300370300201c200641106a221b290300370300201d200641086a2211290300370300200420062903003703a002200b2009417f7341306c6a2209290300210c200941086a2217290300210d200941106a2213290300211f200941186a22142903002127200941206a221629030021292008200941286a221e2903003703002010202937030020152027370300201b201f3703002011200d3703002006200c370300201e2018290300370300201620192903003703002014201a2903003703002013201c2903003703002017201d290300370300200920042903a002370300200641306a21062012200a490d000b0b2000200e3703082000200f37030020262005290300370300202820072903003703002020202a290300370300200020042903003703100240024020012006202b6b41306e20246a22094d0d002018202629030037030020192028290300370300201a2020290300370300201c2021290300370300201d2022290300370300200420002903003703a0022000200941306c6a2206290300210e200641086a2208290300210f200641106a220b290300210c200641186a2210290300210d200641206a220a290300211f2026200641286a22152903003703002028201f3703002020200d3703002021200c3703002022200f3703002000200e37030020152018290300370300200a20192903003703002010201a290300370300200b201c2903003703002008201d290300370300200620042903a002370300200120096b2208450d0120082009200920084b1b210b20014103762110200641306a210a024020092008417f6a22014f0d00200020092002200310c30120062102200a2100200b20104f2105202520244d2106200141154f0d070c0c0b200a20012006200310c301200b20104f2105202520244d21062009220141154f0d060c0b0b4190d4c20020092001104e000b41a0d4c200104f000b410021230b03400240024002400240024002400240024002400240024002400240024002400240024020230e09040507080603000102020b2018200941306c6a2106410721230c100b2006290300200c54200641086a290300220f200e54200f200e511b0d0a410821230c0f0b200641306a2106200941016a2209200b490d070c080b200a2018200941306c6a220641286a220b2903003703002015200641206a2219290300370300201b200641186a221a2903003703002011200641106a221c2903003703002017200641086a221d290300370300200420062903003703a002201041306a221e290300210f201041386a2224290300210d201041c0006a2225290300211f201041c8006a22262903002127201041d0006a22282903002129200b201041d8006a221029030037030020192029370300201a2027370300201c201f370300201d200d3703002006200f3703002010200a290300370300202820152903003703002026201b2903003703002025201129030037030020242017290300370300201e20042903a002370300200941016a22092008417f6a220b490d09410021230c0d0b2016200841306c6a2106410121230c0c0b20092008417f6a22084f0d0a410421230c0b0b2006290300210f200641086a210b200641506a22102106200f200c54200b290300220f200e54200f200e511b0d070c080b2000200c3703002000200e370308201220202903003703002013202129030037030020142022290300370300200020042903003703102001200941016a2206490d01410321230c090b2000200641306c6a2100200120066b220141154f0d0a0c100b20062001107a000b410721230c060b410021230c050b410021230c040b410621230c030b410121230c020b410521230c010b410221230c000b0b0b0b202520081076000b20242025107a000b4190d4c200201e2001104e000b4180d4c20041004100104e000b41b8d4c200201e2001104e000b20014102490d00200041a07f6a21104100210a410121090340200941016a210b02402000200941306c6a220841506a22062903002008290300220c5a200841586a290300220f200841086a2215290300220e5a200f200e511b0d00200441186a2211200841286a221b290300370300200441106a2217200841206a2212290300370300200441086a2213200841186a221429030037030020042008290310370300200820062903003703002015200641086a290300370300200841106a200641106a2903003703002014200641186a2903003703002012200641206a290300370300201b200641286a29030037030020002009417f6a221541306c6a211b02400240024002402015450d00200a210920102106200841a07f6a290300200c5a200841a87f6a290300220f200e5a200f200e511b0d03034020064188016a200641d8006a29030037030020064180016a200641d0006a290300370300200641f8006a200641c8006a290300370300200641f0006a200641c0006a290300370300200641e8006a200641386a290300370300200641e0006a200641306a29030037030020094101460d022006290300210f200641086a21082009417f6a2109200641506a2106200f200c542008290300220f200e54200f200e511b0d000c030b0b410021150c020b410021090b2000200941306c6a211b200921150b201b200c370300201b200e3703082000201541306c6a220641286a2011290300370300200641206a2017290300370300200641186a2013290300370300200620042903003703100b200a41016a210a201041306a2110200b2109200b2001490d000b0b200441d0026a24000b6401027f230041106b220224004100210302400240200020014188f0c100410041001004417f460d002002410036020c200020012002410c6a41044100100441016a41044d0d01200228020c21030b200241106a240020030f0b41eac4c10041331042000bc30603037f017e067f230041306b22012400200141206a41086a2202420037030020014200370320419ab6c100411d200141206a1002200141086a200229030037030020012001290320370300024002400240024002400240200141104188f0c100410041001004417f460d002001421037021420012001360210200141206a200141106a103420012802202202450d0402402001280224450d00200210010b20002802002202450d01200041046a280200450d0120021001200141306a24000f0b0240024020002802002203450d002000290204210420012003360210200120043702142004422088a721000c010b410610002200450d052001420637022420012000360220200141206a41bab6c10041061025200141086a2200200128022836020020012001290320370300200141b7b6c100410310252001280204210220012802002205200028020010c401210002402002450d00200510010b200141106a41002000104620012802102103200128021821000b20014100360228200142013703202000200141206a101b024002402000450d0020004105742106200141206a41086a280200210720012802202108200128022421052003210903402009210002400240024002402005200722026b41204f0d00200241206a22072002490d0820054101742209200720072009491b22094100480d0820091000210a2005450d01200a450d09200a200820092005200520094b1b10f8021a200810010c020b200241206a21070c020b200a450d070b200a2108200921050b200041206a2109200820026a22022000290000370000200241186a200041186a290000370000200241106a200041106a290000370000200241086a200041086a290000370000200641606a22060d000b200141286a200736020020012005360224200120083602200c010b200141286a280200210720012802242105200128022021080b200141206a41086a2200420037030020014200370320419ab6c100411d200141206a1002200141086a2000290300370300200120012903203703002001411020082007100302402005450d00200810010b2001280214450d00200310010b200141306a24000f0b1018000b200941011019000b41eac4c10041331042000b410641011019000b6001017f0240412010002203450d0020032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a29000037000020002001200341201003200310010f0b412041011019000bcc0202037f027e230041306b22012400200141206a41086a220242003703002001420037032041e59bc100411d200141206a1002200141086a20022903003703002001200129032037030002400240200141104188f0c100410041001004417f460d002001200136021020014110360214200142003703202001410020014110200141206a41084100100422022002417f461b22024108200241084922031b220236021820030d012001290320210420014200370320200141106a41086a410020014110200141206a41082002100422032003417f461b2203410820034108491b20026a360200200341074d0d0120012903202105200141206a200141106a103c20012802202202450d0120002001290224370214200020023602102000200537030820002004370300200141306a24000f0b20004100360210200141306a24000f0b41eac4c10041331042000bc00301057f230041d0006b22022400024002400240411210002203450d002002421237023420022003360230200241306a4185efc00041121025200241086a220320022802383602002002200229033037030020012002101e200328020021042002280204210520022802002101200241306a41086a220342003703002002420037033020012004200241306a1002200241206a41086a20032903003703002002200229033037032002400240200241206a41104188f0c100410041001004417f460d00200241c8006a4200370300200241306a41106a42003703002003420037030020024200370330200241206a4110200241306a4120410010042203417f460d012003411f4d0d01200241186a2203200241306a41186a290300370300200241106a2204200241306a41106a290300370300200241086a2206200241306a41086a29030037030020022002290330370300200041013a000020002002290300370001200041096a2006290300370000200041116a2004290300370000200041196a20032903003700002005450d040c030b200041003a000020050d020c030b41eac4c10041331042000b411241011019000b200110010b200241d0006a24000bcb04010c7f230041206b220224000240411510002203450d002002421537021420022003360210200241106a41c8d3c00041151025200241086a220320022802183602002002200229031037030020002002101e20032802002104200228020421052002280200210620024100360218200242013703102001280200210720012802082200200241106a101b02400240024002402000450d0020004105742108200241106a41086a28020021092002280210210a2002280214210b2007210c0340200c21000240024002400240200b200922036b41204f0d00200341206a22092003490d07200b410174220c20092009200c491b220c4100480d07200c1000210d200b450d01200d450d08200d200a200c200b200b200c4b1b10f8021a200a10010c020b200341206a21090c020b200d450d060b200d210a200c210b0b200041206a210c200a20036a22032000290000370000200341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a290000370000200841606a22080d000b200241186a20093602002002200b3602142002200a3602100c010b200241106a41086a28020021092002280214210b2002280210210a0b200241106a41086a220042003703002002420037031020062004200241106a1002200241086a20002903003703002002200229031037030020024110200a200910030240200b450d00200a10010b02402005450d00200610010b0240200141046a280200450d00200710010b200241206a24000f0b1018000b200c41011019000b411541011019000bbb0604057f017e017f017e230041206b2202240002400240410f10002203450d002002420f37021420022003360210200241106a41ddd2c000410f1025200241086a220320022802183602002002200229031037030020012002101e20032802002104200228020421052002280200210642002107200241106a41086a220842003703002002420037031020062004200241106a1002200320082903003703002002200229031037030002400240024002400240200241104188f0c100410041001004417f460d002002420037031020024110200241106a41084100100441016a41084d0d01200229031021070b02402005450d00200610010b42002109200241106a41086a220342003703002002420037031041f0f1c100410d200241106a1002200241086a2003290300370300200220022903103703000240200241104188f0c100410041001004417f460d002002420037031020024110200241106a41084100100441016a41084d0d02200229031021090b418485c1002103024020072009560d00411110002203450d062002421137021420022003360210200241106a41f384c10041111025200241086a220320022802183602002002200229031037030020012002101e20032802002101200228020421042002280200210642002107200241106a41086a220542003703002002420037031020062001200241106a100220032005290300370300200220022903103703000240200241104188f0c100410041001004417f460d002002420037031020024110200241106a41084100100441016a41084d0d04200229031021070b02402004450d00200610010b42002109200241106a41086a220342003703002002420037031041f0f1c100410d200241106a1002200241086a2003290300370300200220022903103703000240200241104188f0c100410041001004417f460d002002420037031020024110200241106a41084100100441016a41084d0d05200229031021090b418485c100410020072009561b21030b2000411e36020420002003360200200241206a24000f0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b410f41011019000b411141011019000bb30301097f23002102200128020821032001280204210420012802002105200241306b2201411c6a22064100360200200141186a2207200536020020012004360214200120044100472208360210024002402004450d002004417f6a2102200141106a41047221092005210a0340200a28029002210a200641003602002007200a36020020012002360214200120024100473602102002417f6a2202417f470d000c020b0b200141106a41047221090b200141086a200941086a280200360200200120092902003703002001411c6a220a4100360200200141106a41086a22062005360200200120043602142001200836021002402004450d002004417f6a21020340200520052f01064102746a4190026a2802002105200a41003602002006200536020020012002360214200120024100473602102002417f6a2202417f470d000b0b2001411c6a2802002105200141106a41086a28020022022f0106210a20012802142106200020033602202000411c6a200a360200200041186a2005360200200041146a2002360200200020063602102000410036020c200041086a200141086a280200360200200020012903003702000bf20202067f027e230041206b22012400200141086a200010cd01024020012802082202450d00200141186a2103200141146a2104034020032802002105200428020021060240200128020c450d00200210010b02402006450d002005450d00200610010b200141086a200010cd01200128020822020d000b0b024002402000280204220641e8bdc000460d0020002802002102200028020821000240024020062802002205450d00200633010421072001200536020c2001200241016a2202360208200120074220862000ad842207370310200610012005450d020c010b2000ad210741002105200610014100450d010b0240024020052802002206450d00200533010421082001200636020c2001200241016a36020820012008422086200742ffffffff0f8384370310200510012006450d020c010b41002106200510014100450d010b034020062802002205450d02200610012005210620050d000b0b200141206a24000f0b20061001200141206a24000bee0903077f017e017f230041f0006b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2205200128020422032f01064f0d01200241186a41086a220620032005410c6c6a220741106a2802003602002002200741086a290200370318200241086a220820074194016a2802003602002007418c016a29020021092001410c6a200541016a360200200141086a2004360200200141046a200336020020022009370300200241c8006a41086a22032006280200360200200241dc006a200828020036020020002002290318220937020020022002290300370254200041086a2003290300370200200041106a200241c8006a41106a29030037020020022009370348200241f0006a24000f0b20004100360200200241f0006a24000f0b200128020021070240024020032802002205450d00200333010421092002200536024c2002200741016a2207360248200220094220862004ad8422093703500c010b2004ad2109410021050b2003100120052f01062103200241086a22042005360200200220073602040240024002402009422088a7220620034f0d00200241106a20063602002002410c6a20093e02002002410036020020024104722108200241186a21070c010b2002410c6a2206200937020020024101360200200241047221080240200528020022030d004103210a0c020b4100210a0c010b4105210a0b03400240024002400240024002400240024002400240024002400240024002400240200a0e0a01030002040508090607070b20062009370200200420033602002002200736020420024101360200200322052802002203450d094100210a0c0f0b2005330104422086200942ffffffff0f83842109200741016a21070c090b200942ffffffff0f832109410021034101210a0c0d0b200510012009422088a7220520032f01064f0d084104210a0c0c0b200241106a20053602002002410c6a20093e0200200241086a20033602002002200736020420024100360200200241186a21074105210a0c0b0b20072008290200370200200741086a200841086a290200370200200241286a41086a200228021c220520022802242204410c6c6a220341106a2802003602002002200341086a290200370328200241386a41086a20034194016a28020036020020022003418c016a290200370338200520044102746a4194026a280200210520072802002108200241c8006a410c6a220720022802202204360200200241c8006a41086a2206200536020020022008417f6a220336024c200220034100473602482003450d074108210a0c0a0b2008417e6a2103200241c8006a41047221084109210a0c090b200528029002210520072004360200200620053602002002200336024c200220034100473602482003417f6a2203417f470d060c070b200241c8006a41047221084107210a0c070b20012008290200370200200141086a200841086a2802003602002001410c6a4100360200200241c8006a41086a2203200241286a41086a280200360200200241dc006a200241386a41086a28020036020020002002290328220937020020022002290338370254200041086a2003290300370200200041106a200241c8006a41106a29030037020020022009370348200241f0006a24000f0b4103210a0c050b4101210a0c040b4102210a0c030b4106210a0c020b4109210a0c010b4107210a0c000b0bf30502067f027e230041206b220124002000280208210220002802042103200028020021042001411c6a22054100360200200141186a22062004360200200120033602142001200341004736021002402003450d002003417f6a21000340200428026c2104200541003602002006200436020020012000360214200120004100473602102000417f6a2200417f470d000b0b2001411c6a2802002104200141186a28020021052001280214210602402003450d0003402003417f6a22030d000b0b41002100024003402002450d010240200020052f01064f0d0020004103742103200041016a21002002417f6a2102200520036a41146a290200a74103470d010c020b0240024020052802002200450d00200641016a210620053301044220862004ad8421070c010b2004ad2107410021000b20051001024002402007422088a7220320002f01064f0d00200021040c010b03400240024020002802002204450d002000330104422086200742ffffffff0f83842107200641016a21060c010b200742ffffffff0f832107410021040b20001001200421002007422088a7220320042f01064f0d000b0b200420034102746a41f0006a2802002105200420034103746a41146a29020021082007a72104024020064101460d00410120066b21000340200528026c2105200041016a22000d000b0b41002106410021002002417f6a21022008a74103470d000b0b02400240200541e8bdc000460d000240024020052802002203450d0020053301042107200120033602142001200641016a2206360210200120074220862004ad842207370318200510012003450d020c010b2004ad210741002103200510014100450d010b0240024020032802002200450d0020033301042108200120003602142001200641016a36021020012008422086200742ffffffff0f8384370318200310012000450d020c010b41002100200310014100450d010b034020002802002204450d02200010012004210020040d000b0b200141206a24000f0b20001001200141206a24000bb30301097f23002102200128020821032001280204210420012802002105200241306b2201411c6a22064100360200200141186a2207200536020020012004360214200120044100472208360210024002402004450d002004417f6a2102200141106a41047221092005210a0340200a2802f806210a200641003602002007200a36020020012002360214200120024100473602102002417f6a2202417f470d000c020b0b200141106a41047221090b200141086a200941086a280200360200200120092902003703002001411c6a220a4100360200200141106a41086a22062005360200200120043602142001200836021002402004450d002004417f6a21020340200520052f01064102746a41f8066a2802002105200a41003602002006200536020020012002360214200120024100473602102002417f6a2202417f470d000b0b2001411c6a2802002105200141106a41086a28020022022f0106210a20012802142106200020033602202000411c6a200a360200200041186a2005360200200041146a2002360200200020063602102000410036020c200041086a200141086a280200360200200020012903003702000bb50302077f027e230041a0016b22012400200141086a200010d101024020012903284202510d00200141d8006a4104722102200141c8006a2103200141c4006a2104200141c0006a2105200141286a21060340200141d8006a41086a200341086a29030037030020012003290300370358024020052802002207450d002004280200450d00200710010b20014190016a41086a200241086a2802003602002001200229020037039001200141e8006a20014190016a10cb01200141e8006a10cc01200141086a200010d10120062903004202520d000b0b02400240024002402000280204220241e8bdc000460d0020022802002203450d0120002802082107200233010421082001200028020041016a2200360208200120084220862007ad8422083703102001200336020c2002100120032802002202450d02200333010421092001200236020c2001200041016a36020820012009422086200842ffffffff0f838437031020031001034020022802002203450d04200210012003210220030d000b0b200141a0016a24000f0b20021001200141a0016a24000f0b20031001200141a0016a24000f0b20021001200141a0016a24000ba20d030d7f017e017f230041e0016b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2205200128020422032f01064f0d01200241306a41186a2206200320054105746a220741206a290000370300200241306a41106a2208200741186a290000370300200241306a41086a2209200741106a2900003703002002200741086a290000370330200241d0006a41286a220a2003200541306c6a22074190036a290300370300200241d0006a41206a220b20074188036a290300370300200241d0006a41186a220c20074180036a290300370300200241d0006a41106a220d200741f8026a290300370300200241d0006a41086a220e200741f0026a290300370300200741e8026a290300210f2001410c6a200541016a360200200141086a2004360200200141046a20033602002002200f37035020024180016a41186a200629030037030020024180016a41106a200829030037030020024180016a41086a200929030037030020024180016a41286a200e29030037030020024180016a41306a200d290300370300200241b8016a200c290300370300200241c0016a200b290300370300200241c8016a200a2903003703002002200229033037038001200220022903503703a001200020024180016a41d00010f8021a200241e0016a24000f0b20004202370320200241e0016a24000f0b200128020021050240024020032802002207450d002003330104210f20022007360284012002200541016a2205360280012002200f4220862004ad84220f370388010c010b2004ad210f410021070b20031001200241106a220420073602002002200536020c024002400240200f422088a7220320072f01064f0d00200241186a2003360200200241146a200f3e020020024100360208200241086a4104722108200241206a21050c010b200241146a2206200f37020020024101360208200241086a41047221080240200728020022030d00410321100c020b410021100c010b410521100b0340024002400240024002400240024002400240024002400240024002400240024020100e0a01030002040508090607070b2006200f37020020024101360208200322072802002203450d09410021100c0f0b2007330104422086200f42ffffffff0f8384210f200541016a21050c090b200f42ffffffff0f83210f41002103410121100c0d0b20071001200420033602002002200536020c200f422088a7220720032f01064f0d08410421100c0c0b200241186a2007360200200241146a200f3e020020024100360208200241206a2105410521100c0b0b20052008290200370200200541086a200841086a290200370200200241306a41086a20022802242207200228022c22044105746a220341106a290000370300200241306a41106a200341186a290000370300200241306a41186a200341206a2900003703002002200341086a290000370330200241f8006a2007200441306c6a22034190036a290300370300200241d0006a41206a20034188036a290300370300200241d0006a41186a20034180036a290300370300200241d0006a41106a200341f8026a290300370300200241d0006a41086a200341f0026a2903003703002002200341e8026a290300370350200720044102746a41fc066a2802002107200528020021082002418c016a22052002280228220436020020024180016a41086a2206200736020020022008417f6a22033602840120022003410047360280012003450d07410821100c0a0b2008417e6a210320024180016a4104722108410921100c090b20072802f80621072005200436020020062007360200200220033602840120022003410047360280012003417f6a2203417f470d060c070b20024180016a4104722108410721100c070b20012008290200370200200141086a200841086a2802003602002001410c6a410036020020024180016a41186a200241306a41186a29030037030020024180016a41106a200241306a41106a29030037030020024180016a41086a200241306a41086a29030037030020024180016a41286a200241d0006a41086a290300370300200241b0016a200241d0006a41106a290300370300200241b8016a200241d0006a41186a290300370300200241c0016a200241f0006a290300370300200241c8016a200241d0006a41286a2903003703002002200229033037038001200220022903503703a001200020024180016a41d00010f8021a200241e0016a24000f0b410321100c050b410121100c040b410221100c030b410621100c020b410921100c010b410721100c000b0bf906020a7f027e230041206b220124002000280208210220002802042103200028020021042001411c6a22054100360200200141186a22062004360200200120033602142001200341004736021002402003450d002003417f6a2100034020042802e8022104200541003602002006200436020020012000360214200120004100473602102000417f6a2200417f470d000b0b2001411c6a2802002107200141186a28020021052001280214210602402003450d0003402003417f6a22030d000b0b02402002450d0041002100034002400240200020052f01064f0d002005200041146c6a22084194016a280200210920084190016a280200210a20052000410c6c6a2203410c6a2802002104200341086a2802002103200041016a21002008419d016a2d000041ff01714105460d030c010b0240024020052802002200450d00200641016a210620053301044220862007ad84210b0c010b2007ad210b410021000b2005100102400240200b422088a7220320002f01064f0d00200021040c010b03400240024020002802002204450d002000330104422086200b42ffffffff0f8384210b200641016a21060c010b200b42ffffffff0f83210b410021040b2000100120042100200b422088a7220320042f01064f0d000b0b200420034102746a41ec026a28020021052004200341146c6a2200419d016a2d0000210820004194016a280200210920004190016a280200210a20042003410c6c6a2200410c6a2802002104200041086a2802002103200ba72107024020064101460d00410120066b2100034020052802e8022105200041016a22000d000b0b4100210641002100200841ff01714105460d020b02402004450d00200310010b2002417f6a210202402009450d00200a10010b20020d000b0b02400240200541e8bdc000460d000240024020052802002204450d002005330104210b200120043602142001200641016a22063602102001200b4220862007ad84220b370318200510012004450d020c010b2007ad210b41002104200510014100450d010b0240024020042802002200450d002004330104210c200120003602142001200641016a3602102001200c422086200b42ffffffff0f8384370318200410012000450d020c010b41002100200410014100450d010b034020002802002204450d02200010012004210020040d000b0b200141206a24000f0b20001001200141206a24000b810703047f017e087f230041d0006b21020240024020012802202203450d00200141206a2003417f6a360200200128020c2204200128020422032f01064f0d012001410c6a200441016a36020020002003200441146c6a418c016a360204200020032004410c6c6a41086a3602000f0b20004100360204200041003602000f0b0240024020032802002205450d002003330104422086200141086a350200842106200128020041016a21040c010b410021050b20052f01062103200241106a220720053602002002200436020c0240024002402006422088a7220820034f0d00200241186a2008360200200241146a20063e020020024100360208200241086a4104722109200241206a21030c010b200241146a220a200637020020024101360208200241086a41047221090240200528020022030d004103210b0c020b4100210b0c010b4105210b0b03400240024002400240024002400240024002400240024002400240024002400240200b0e0a01030002040508090607070b200a200637020020024101360208200322052802002203450d094100210b0c0f0b200642ffffffff0f832005330104422086842106200441016a21040c090b410021034101210b0c0d0b20032f01062105200720033602002002200436020c2006422088a7220820054f0d084104210b0c0c0b200241186a2008360200200241146a20063e020020024100360208200241206a21034105210b0c0b0b200341086a200941086a2902003702002003200929020022063702002002280224200228022c4102746a41ec026a2802002104200241086a41086a2802002103200241186a280200210a200241306a410c6a220520022802282207360200200241306a41086a2208200436020020022006a7220c417f6a2209360234200220094100473602302003200a41146c6a210d2003200a410c6c6a210e2009450d074108210b0c0a0b200c417e6a2103200241306a410472210a4109210b0c090b20042802e8022104200520073602002008200436020020022003360234200220034100473602302003417f6a2203417f470d060c070b200241306a410472210a4107210b0c070b2001200a290200370200200141086a200a41086a2802003602002001410c6a41003602002000200d418c016a3602042000200e41086a3602000f0b4103210b0c050b4101210b0c040b4102210b0c030b4106210b0c020b4109210b0c010b4107210b0c000b0b3400200041bf9fc10036020420004100360200200041146a4108360200200041106a41e0cdc200360200200041086a42073702000b4b00200041ddf5c10036020420004100360200200041206a41033602002000411c6a4188d2c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000bce1601157f230041c0056b220424000240024020014115490d00410121054101210602400240024002400340200620057141017321070340024002402003450d0020054101710d012000200110d7012003417f6a21030c010b2000200110d801200441c0056a24000f0b2001410276220841036c2109200841017421064100210a024020014132490d0020092009417f6a220b2000200941e0016c6a220a280200220c200a41a07e6a280200220d49220e1b220f200941016a200b2009200e1b200a41e0016a2802002209200d200c200e1b220a49220c1b2009200a200c1b2000200f41e0016c6a2802004922101b210920062006417f6a220a2000200641e0016c6a220b280200220d200b41a07e6a280200220f49220b1b221120064101722212200a2006200b1b2000201241e0016c6a2802002206200f200d200b1b220a49220d1b2006200a200d1b2000201141e0016c6a2802004922111b210620082008417f6a22122000200841e0016c6a220f2802002213200f41a07e6a280200221449220a1b2215200841016a20122008200a1b200f41e0016a280200220820142013200a1b221249220f1b20082012200f1b2000201541e0016c6a2802004922121b210841024101200a1b200a200f1b20126a200b6a200d6a20116a200e6a200c6a20106a210a0b200a2000200641e0016c6a280200220b2000200841e0016c6a280200220c49220e6a2000200941e0016c6a280200220a200c200b200e1b220d49220c6a210b0240024002400240200a200d200c1b200020062008200e1b220a41e0016c6a2802004f0d00200b41016a220b410b4d0d01024020014101762209450d002000200141e0016c6a41a07e6a2108200021060340200441e0036a200641e00110f8021a2006200841e00110f90241e0016a21062008200441e0036a41e00110f80241a07e6a21082009417f6a22090d000b0b2001200a417f736a210a4101452007724101710d030c020b200920082006200e1b200c1b210a0b200b45452007724101710d010b2000200110d9010d080b024002400240024002402002450d00200a20014f0d0a20022802002000200a41e0016c6a2208280200490d01200441e0036a200041e00110f8021a2000200841e00110f902210c2008200441e0036a41e00110f8021a200c280200210e200441046a200c41046a221041dc0110f8021a200c41a07e6a210d200c41e0016a210f41002106410020012209417f6a220a4f0d02410621160c030b2001450d080b200a20014f0d06200441e0036a200041e00110f8021a20002000200a41e0016c6a220841e00110f90221152008200441e0036a41e00110f8021a20152802002110200441046a201541046a221741dc0110f8021a201541e0016a210e4100211302402001417f6a2209450d00200e21080340200828020020104f0d01200841e0016a2108201341016a22132009490d000b0b2015200141e0016c6a210820092106024003402008210a2006221420134d0d012014417f6a2106200a41a07e6a220828020020104f0d000b0b20142013490d0520092014490d024180012107410021094100210f410021064100210d4180012111200e201341e0016c6a2218210e0340200a200e6b220841e0016e210b0240024002400240024002400240200841dfc1034b22120d00200b41807f6a200b200f200949200d200649220c7222051b21082005450d0120112008200c1b211120082007200c1b21070b200d2006470d020c010b2008200841017622116b2107200d2006470d010b2011450d0141002108200441e0016a220d2106200e210b0340200620083a00002006200b28020020104f6a2106200b41e0016a210b200841016a22082011490d000b0b200f2009470d020c010b200441e0016a2206210d200f2009470d010b02402007450d00200a41a07e6a21084100210b200441e0026a220f210903402009200b3a0000200920082802002010496a2109200841a07e6a2108200b41016a220b2007490d000c020b0b200441e0026a2209210f0b02402009200f6b22082006200d6b220b200b20084b1b2205450d00200441e0036a200e200d2d000041e0016c6a41e00110f8021a200e200d2d000041e0016c6a200a200f2d0000417f7341e0016c6a41e00110f8021a024020054101460d00410021080340200a200f20086a220b2d0000417f7341e0016c6a200e200d20086a41016a220c2d000041e0016c6a41e00110f8021a200e200c2d000041e0016c6a200a200b41016a2d0000417f7341e0016c6a41e00110f8021a200841026a210b200841016a220c2108200b2005490d000b200f200c6a210f200d200c6a210d0b200a200f2d0000417f7341e0016c6a200441e0036a41e00110f8021a200f41016a210f200d41016a210d0b200e201141e0016c6a200e200d2006461b210e200a410020076b41e0016c6a200a200f2009461b210a20120d000b02400240200d20064f0d00200a21080340200441e0036a200e2006417f6a22062d000041e0016c6a220941e00110f8021a2009200841a07e6a220841e00110f9021a2008200441e0036a41e00110f8021a200d2006490d000c020b0b200e2108200f20094f0d0003402009417f6a22092d00002106200441e0036a200841e00110f8021a2008200a2006417f7341e0016c6a220641e00110f90221082006200441e0036a41e00110f8021a200841e0016a2108200f2009490d000b0b201520103602002017200441046a41dc0110f8021a024002402001200820186b41e0016e20136a22084d0d00200441e0036a201541e00110f8021a20152015200841e0016c6a220641e00110f902210c2006200441e0036a41e00110f8022109200120086b2206450d0120062008200820064b1b210a2001410376210e200941e0016a210b024020082006417f6a22014f0d00200c20082002200310d60120092102200b2100200a200e4f2105201420134d2106200141154f0d070c0c0b200b20012009200310d601200a200e4f2105201420134d21062008220141154f0d060c0b0b4190d4c20020082001104e000b41a0d4c200104f000b410021160b03400240024002400240024002400240024002400240024002400240024002400240024020160e09040507080603000102020b200f200641e0016c6a2108410721160c100b200e2008280200490d0a410821160c0f0b200841e0016a2108200641016a2206200a490d070c080b200441e0036a200f200641e0016c6a220841e00110f8021a2008200b41e0016a220a41e00110f9021a200a200441e0036a41e00110f8021a200641016a22062009417f6a220a490d09410021160c0d0b200d200941e0016c6a2108410121160c0c0b20062009417f6a22094f0d0a410421160c0b0b2008280200210a200841a07e6a220b2108200e200a490d070c080b200c200e3602002010200441046a41dc0110f8021a2001200641016a2208490d01410321160c090b200c200841e0016c6a2100200120086b220141154f0d0a0c100b20082001107a000b410721160c060b410021160c050b410021160c040b410621160c030b410121160c020b410521160c010b410221160c000b0b0b0b201420091076000b20132014107a000b4190d4c200200a2001104e000b4180d4c20041004100104e000b41b8d4c200200a2001104e000b20014102490d00200041a07e6a210b4100210c410121060340200641016a210e02402000200641e0016c6a2209280200220a200941a07e6a22082802004f0d00200441046a200941046a41dc0110f8021a2009200841e00110f802210d02402006417f6a450d00200c2106200b2109200a200d41c07c6a2802004f0d0003402009220841e0016a200841e00110f8021a200641016a2206450d01200a200841a07e6a2209280200490d000b0b2008200a360200200841046a200441046a41dc0110f8021a0b200c417f6a210c200b41e0016a210b200e2106200e2001490d000b0b200441c0056a24000ba70301087f230041e0016b22022400024002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d032001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d0120022000200441e0016c6a220841e00110f802210420082000200541e0016c6a220541e00110f9021a2005200441e00110f8021a200320014f0d022006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d0120042000200341e0016c6a220941e00110f802210820092000200541e0016c6a220541e00110f9021a2005200841e00110f8021a2003410172220420014f0d032006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d0120082000200441e0016c6a220141e00110f802210320012000200541e0016c6a220041e00110f9021a2000200341e00110f8021a0b200241e0016a24000f0b4190d4c20020052001104e000b200321040b4180d4c20020042001104e000b8d0401087f230041e0016b2202240002400240024002400240024020014101762203450d0003402003417f6a2203210403402004410174220641017221070240200641026a220620014f0d00200720014f0d06200620072000200741e0016c6a2802002000200641e0016c6a280200491b21070b0240200720014f0d00200420014f0d042000200441e0016c6a22042802002000200741e0016c6a22062802004f0d002002200441e00110f80221052004200641e00110f9021a2006200541e00110f8021a200721040c010b0b20030d000b0b024020014102490d002001210603402006417f6a220620014f0d062002200041e00110f802210820002000200641e0016c6a220741e00110f90221052007200841e00110f8021a4100210403402004410174220341017221070240200341026a220320064f0d00200720064f0d07200320072005200741e0016c6a2802002005200341e0016c6a280200491b21070b0240200720064f0d00200420064f0d052005200441e0016c6a22042802002005200741e0016c6a22032802004f0d002008200441e00110f80221092004200341e00110f9021a2003200941e00110f8021a200721040c010b0b200641014b0d000b0b200241e0016a24000f0b41d8d4c20020042001104e000b41d8d4c20020042006104e000b41c8d4c20020072001104e000b41c8d4c20020072006104e000b4190d4c20020062001104e000b9d0501107f230041e0016b2202240020004180796a2103200041a07e6a210441002105200141324921064101210702400240024002400340024002400240200720014f0d002004200741e0016c6a21080340200841e0016a22092802002008280200490d0220092108200741016a22072001490d000b0b41002108200720014622090d030c010b41012108200720014622090d020b20060d012007417f6a220920014f0d032008450d0420022000200941e0016c6a220841e00110f802210a20082000200741e0016c220b6a220941e00110f80221082009200a41e00110f8022109024020074102490d002008280200220c20002007417e6a220d41e0016c6a220e2802004f0d00200a200841046a41dc0110f802210f2008200e41e00110f8021a0240200d450d00200c200941e07a6a2802004f0d00410220076b210d2003200b6a21080340200841c0036a200841e0016a220e41e00110f8021a200d41016a220d450d012008280200210b200841a07e6a2108200c200b490d000b0b200e200c360200200e41046a200f41dc0110f8021a0b200541016a21050240200120076b220d4102490d0020092802e0012009280200220e4f0d00200a200941046a41dc0110f80221102009200941e0016a220b41e00110f80221090240200d4103490d0020092802c003200e4f0d00200941c0036a210c410321084102210f03402009200f41e0016c6a41a07e6a200c220b41e00110f8021a2008200d4f0d01200841016a220c2008490d01200841e0016c21112008210f200c2108200920116a220c280200200e490d000b0b200b200e360200200b41046a201041dc0110f8021a0b20054105490d000c020b0b200241e0016a240020090f0b200a41e0016a240041000f0b4180d4c20020092001104e000b4190d4c20020072001104e000b86090b107f017e017f017e017f017e017f017e017f017e017f230041306b22022400024002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d032001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241286a22082000200441306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e2903003703002013201029030037030020052002290300370300200320014f0d022006410d7420067322044111762004732204410574200473220620077122044100200120042001491b6b220520014f0d01200241286a22082000200341306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e29030037030020132010290300370300200520022903003703002003410172220420014f0d032006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241286a22032000200441306c6a220141286a2204290300370300200241206a2206200141206a2207290300370300200241186a2208200141186a2209290300370300200241106a220a200141106a220b290300370300200241086a220c200141086a220d290300370300200220012903003703002000200541306c6a22002903002112200041086a22052903002114200041106a220e2903002116200041186a220f2903002118200041206a2210290300211a2004200041286a22112903003703002007201a37030020092018370300200b2016370300200d2014370300200120123703002011200329030037030020102006290300370300200f2008290300370300200e200a2903003703002005200c290300370300200020022903003703000b200241306a24000f0b4190d4c20020052001104e000b200321040b4180d4c20020042001104e000bb50a090d7f017e037f017e017f017e017f027e027f230041306b2202240002400240024002400240024020014101762203450d0003402003417f6a22032104034020044101742211410172211a0240201141026a221120014f0d00201a20014f0d062011201a2000201141306c6a220e2903002000201a41306c6a221029030054200e41086a290300220f201041086a290300221354200f2013511b1b211a0b0240201a20014f0d00200420014f0d042000201a41306c6a22112903002000200441306c6a220429030054201141086a2210290300220f200441086a220e290300221354200f2013511b450d00200241286a2205200441286a2206290300370300200241206a2207200441206a2208290300370300200241186a2209200441186a220a290300370300200241106a220b200441106a220c290300370300200241086a220d200e290300370300200220042903003703002010290300210f201141106a22122903002113201141186a22142903002115201141206a22162903002117201129030021182006201141286a221929030037030020082017370300200a2015370300200c2013370300200e200f370300200420183703002019200529030037030020162007290300370300201420092903003703002012200b2903003703002010200d29030037030020112002290300370300201a21040c010b0b20030d000b0b024020014102490d002001210e0340200e417f6a220e20014f0d06200241286a2206200041286a2211290300370300200241206a2207200041206a221a290300370300200241186a2208200041186a2210290300370300200241106a2209200041106a2205290300370300200241086a220a200041086a220b290300370300200220002903003703002000200e41306c6a2204290300210f200441086a220c2903002113200441106a220d2903002115200441186a22122903002117200441206a221429030021182011200441286a2216290300370300201a20183703002010201737030020052015370300200b20133703002000200f370300201620062903003703002014200729030037030020122008290300370300200d2009290300370300200c200a2903003703002004200229030037030041002104034020044101742211410172211a0240201141026a2211200e4f0d00201a200e4f0d072011201a2000201141306c6a22102903002000201a41306c6a220529030054201041086a290300220f200541086a290300221354200f2013511b1b211a0b0240201a200e4f0d002004200e4f0d052000201a41306c6a22112903002000200441306c6a220429030054201141086a2205290300220f200441086a2210290300221354200f2013511b450d002006200441286a220b2903003703002007200441206a220c2903003703002008200441186a220d2903003703002009200441106a2212290300370300200a2010290300370300200220042903003703002005290300210f201141106a22142903002113201141186a22162903002115201141206a2219290300211720112903002118200b201141286a2203290300370300200c2017370300200d2015370300201220133703002010200f37030020042018370300200320062903003703002019200729030037030020162008290300370300201420092903003703002005200a29030037030020112002290300370300201a21040c010b0b200e41014b0d000b0b200241306a24000f0b41d8d4c20020042001104e000b41d8d4c2002004200e104e000b41c8d4c200201a2001104e000b41c8d4c200201a200e104e000b4190d4c200200e2001104e000bf50b05087f027e107f017e017f230041306b22022400200041c07e6a2103200041506a21044100210520014132492106410121070240024002400340024002400240200720014f0d002004200741306c6a210803402008290300200841306a220929030054200841086a290300220a200841386a290300220b54200a200b511b0d0220092108200741016a22072001490d000b0b41002108200720014622090d030c010b41012108200720014622090d020b20060d012007417f6a220920014f0d022008450d032000200941306c6a2208290300210a20082000200741306c220c6a2209290300370300200241286a220d200841286a220e290300370300200241206a220f200841206a2210290300370300200241186a2211200841186a2212290300370300200241106a2213200841106a2214290300370300200241086a2215200841086a22162903003703002016200941086a22172903003703002014200941106a22182903003703002012200941186a22192903003703002010200941206a221a290300370300200e200941286a221b2903003703002002200a370300201b200d290300370300201a200f29030037030020192011290300370300201820132903003703002017201529030037030020092002290300370300024020074102490d0020002007417e6a220f41306c6a220d2903002008290300221c5a200d41086a221d290300220b2016290300220a5a200b200a511b0d002008200d2903003703002016201d2903003703002008290310210b2014200d41106a2903003703002011200e29030037030020132010290300370300201520122903003703002012200d41186a2903003703002010200d41206a290300370300200e200d41286a2903003703002002200b3703000240024002400240200f450d0020002007417d6a221641306c6a2208290300201c5a200841086a290300220b200a5a200b200a511b0d032003200c6a2108034020084188016a200841d8006a29030037030020084180016a200841d0006a290300370300200841f8006a200841c8006a290300370300200841f0006a200841c0006a290300370300200841e8006a200841386a290300370300200841e0006a200841306a2903003703002016450d022008290300210b200841086a210d200841506a21082016417f6a2116200b201c54200d290300220b200a54200b200a511b0d000b201641016a210f0c020b4100210f0c020b4100210f0b2000200f41306c6a210d0b200d201c370300200d200a3703082000200f41306c6a22082002290300370310200841286a2011290300370300200841206a2013290300370300200841186a20152903003703000b200541016a21050240200120076b220e4102490d002009290300220b20092903305a2017290300220a200941386a290300221c5a200a201c511b0d002009200941306a22082903003703002017200841086a2903003703002009290310211c2018200841106a2903003703002011201b2903003703002013201a290300370300201520192903003703002019200841186a290300370300201a200841206a290300370300201b200841286a2903003703002002201c370300410121120240200e4103490d00200b20092903605a200a200941e8006a290300221c5a200a201c511b0d00200941e0006a21164103210d41022117034020092017221241306c6a220841786a201641286a290300370300200841706a201641206a290300370300200841686a201641186a290300370300200841606a201641106a290300370300200841586a201641086a290300370300200841506a2016290300370300200d200e4f0d01200d41016a2216200d490d01200d41306c2110200d21172016210d200b200920106a221629030054200a201641086a290300221c54200a201c511b0d000b0b2008200b3703002008200a3703082009201241306c6a22082002290300370310200841286a2011290300370300200841206a2013290300370300200841186a20152903003703000b20054105490d000b410021090b200241306a240020090f0b4180d4c20020092001104e000b4190d4c20020072001104e000b130020004101360204200041e8d4c2003602000b9e0101057f20002802042102024003402000280200220441086a210520042f01064105742100417f210302400240024003402000450d01200341016a210320012005412010fa022206450d05200041606a2100200541206a21052006417f4a0d000b20020d010c020b20042f010621032002450d010b2002417f6a2102200420034102746a41f8066a21000c010b0b41000f0b2004200341306c6a41e8026a0b980301077f230041f0066b220324000240024002402001280200220441e8bdc000460d00200128020421050c010b41f80610002204450d0141002105200441003b010620044100360200200441086a200341f00610f8021a20014100360204200120043602000b024002400340200441086a210720042f010641057421084100210602400240024003402008450d0120022007412010fa022209450d05200841606a2108200641016a2106200741206a21072009417f4a0d000b2006417f6a210620050d010c020b20042f010621062005450d010b2005417f6a2105200420064102746a41f8066a28020021040c010b0b41012107410021050c010b410021070b20002005360204200041146a200141086a360200200041106a20063602002000410c6a2001360200200041086a20043602004101210802402007450d00200041186a2002290000370000200041306a200241186a290000370000200041286a200241106a290000370000200041206a200241086a290000370000410021080b20002008360200200341f0066a24000f0b41f80641081019000be91905087f017e017f017e087f230041c0036b2204240020022802082105200228020421062002280200210702400240024002402001280200220241e8bdc000460d00200128020421080c010b41900210002202450d0141002108200241003b010620024100360200200241086a20044188016a41880210f8021a20014100360204200120023602000b20044188016a41086a21092001210a03402009200a3602002004200236028c012004200836028801200441106a20044188016a10a101200428021022022004280214410c6c6a2108428080808070210c417f210b0240034002400240024020022008460d002002450d00024020072002280200200241086a280200220a20052005200a4b1b10fa02220d450d00200c4280808080107c210c417f4101200d4100481b220a450d020c030b200c4280808080107c210c4100417f41012005200a491b2005200a461b220a0d020c010b200441086a20044188016a10a101200428020c210b0c030b200141086a2102200c20044188016a41086a35020084210c200428028c01210a200428028801210502402006450d00200710010b200420023602980120042005360288012004200a36028c012004200c37039001200441f8006a41086a2202200341086a28020036020020042003290200370378200441186a41086a2205200a200c422088a7410c6c6a220a4194016a220b2802003602002004200a418c016a220a290200370318200b2002280200360200200a200429037837020020022005280200360200200420042903183703782005200228020036020020042004290378370318200041013602002000410c6a200528020036020020002004290318370204200441c0036a24000f0b2002410c6a2102200b41016a210b200a4101460d000b0b2009280200210a200428028c01210202402004280288012208450d002008417f6a21082002200b4102746a4190026a28020021020c010b0b200441286a20023602002001200128020841016a3602082004412c6a200bad422086200aad84220e3702002004200636021c2004200736021820042005ad370320200441e8006a41086a220b200341086a28020036020020042003290200370368024020022f01062201410b4f0d00200241086a220a200e422088a72208410c6c220d410c6a22096a200a200d6a220a200120086b410c6c10f9021a200a2005360208200a2006360204200a20073602002002418c016a220520096a2005200d6a2205200241066a22022f010020086b410c6c10f9021a200541086a200b28020036020020052004290368370200200220022f010041016a3b01000c020b0240024041900210002209450d00200941003b010620094100360200200941086a20044188016a41880210f802210b20044188016a41086a2201200241dc016a280200360200200420022902d40137038801200241d4006a290200210c200241d0006a280200210f200b200241dc006a200241066a220a2f010041796a2208410c6c220d10f80221032009418c016a200241e0016a200d10f802210d200a41063b0100200920083b0106200441f8006a41086a2001280200360200200420042903880137037802400240200e422088a7220b41064b0d002001200441e8006a41086a2802003602002004200429036837038801200241086a2208200b410c6c220d410c6a22036a2008200d6a2208200a2f0100200b6b410c6c10f9021a2008200536020820082006360204200820073602002002418c016a220520036a2005200d6a2205200a2f0100200b6b410c6c10f9021a200541086a20012802003602002005200429038801370200200a200a2f010041016a3b01000c010b2003200b410c6c220a41b87f6a22016a2003200a41ac7f6a22106a220a200841ffff0371200b41796a220b6b410c6c10f9021a200a2005360208200a2006360204200a2007360200200d20016a200d20106a2205200941066a220a2f0100200b6b410c6c10f9021a200541086a200441e8006a41086a28020036020020052004290368370200200a200a2f010041016a3b01000b200441d8006a41086a2205200441f8006a41086a28020036020020042004290378370358200441386a41086a200528020036020020042004290358370338200ea7211102400240024002400240024020022802002208450d00200420022f0104220d3602940120042011360290012004200836028c0141012105200441013602880141000d010c020b20042011360290012004200236028c012004410036028801201121054101450d010b20044188016a210a41c002210b41c002100022020d010c050b0340200441d8006a41086a2210200441386a41086a22132802003602002004200429033837035820082f01062202410a4d0d0241c0021000220b450d03200b41003b0106200b4100360200200b41086a20044188016a41b80210f80221022008290254210e2008280250211220044188016a41086a2203200841dc016a280200360200200420082902d401370388012002200841dc006a200841066a22072f0100220541796a220a410c6c220110f8022114200b418c016a200841e0016a200110f8022115200b4190026a200841ac026a2005417a6a220141027410f8022106200741063b0100200b200a3b010602402001450d00410021022006210503402005280200220a20023b0104200a200b360200200541046a2105200241016a22022001490d000b0b200441f8006a41086a220220032802003602002004200429038801370378200441e8006a41086a221620022802003602002004200429037837036802400240200d41064b0d00200320102802003602002004200429035837038801200841086a2205200d410c6c2202410c6a220a6a200520026a220520072f0100200d6b410c6c10f9021a2005200c3702042005200f3602002008418c016a2205200a6a200520026a220220072f0100200d6b410c6c10f9021a200241086a20032802003602002002200429038801370200200720072f010041016a22053b010020084190026a220a200d41027422016a41086a200a200d41016a22024102746a220a200541ffff037120026b41027410f9021a200a2009360200200220072f0100220d4b0d01200820016a4194026a21050340200241016a220a2002490d022005280200220120023b010420012008360200200541046a2105200a2102200a200d4d0d000c020b0b2014200d410c6c220241b87f6a220a6a2014200241ac7f6a22016a2202200b41066a22052f0100200d41796a22076b410c6c10f9021a2002200c3702042002200f3602002015200a6a201520016a220220052f010020076b410c6c10f9021a200241086a201028020036020020022004290358370200200520052f010041016a220a3b01002006200d41027422076a416c6a2006200d417a6a22024102746a2201200a41ffff037120026b41027410f9021a20012009360200200220052f0100220d4b0d00200b20076a41f8016a21050340200241016a220a2002490d012005280200220120023b01042001200b360200200541046a2105200a2102200a200d4d0d000b0b200441c8006a41086a22022016280200360200200420042903683703482013200228020036020020042004290348370338024020082802002202450d0020082f0104210d20022108200e210c2012210f200b21090c010b0b20044188016a210a200e210c2012210f20112105200b210941c002210b41c00210002202450d040b200241003b010620024100360200200241086a200a41b80210f802210a2002200528020036029002200520023602002005200528020441016a360204200228029002220541003b010420052002360200200a20022f01062205410c6c220b6a220a200c3702042002200b6a220b4194016a200441386a41086a2802002201360200200b418c016a2004290338220c370200200a200f36020020024190026a200541016a22054102746a2009360200200220022f010641016a3b010620044188016a41086a2001360200200920053b0104200920023602002004200c370388010c050b20044188016a41086a220b200441d8006a41086a2802003602002004200429035837038801200841086a220a200d410c6c2205410c6a22016a200a20056a220a2002200d6b410c6c10f9021a200a200c370204200a200f3602002008418c016a220220016a200220056a2202200841066a22052f0100200d6b410c6c10f9021a200241086a200b2802003602002002200429038801370200200520052f010041016a3b010020084190026a220a200d410274220b6a41086a200a200d41016a22024102746a220a20052f010020026b41027410f9021a200a2009360200200220052f010022014b0d042008200b6a4194026a21050340200241016a220a2002490d052005280200220b20023b0104200b2008360200200541046a2105200a2102200a20014d0d000c050b0b41c00241041019000b41900241041019000b200b41041019000b41900241041019000b20004100360200200441c0036a24000bc31d05087f017e017f017e0c7f230041c0046b2204240020022802082105200228020421062002280200210702400240024002402001280200220241e8bdc000460d00200128020421080c010b41e80210002202450d0141002108200241003b010620024100360200200241086a200441b0016a41e00210f8021a20014100360204200120023602000b200441b0016a41086a21092001210a03402009200a360200200420023602b401200420083602b001200441106a200441b0016a10a101200428021022022004280214410c6c6a2108428080808070210c417f210b0240034002400240024020022008460d002002450d00024020072002280200200241086a280200220a20052005200a4b1b10fa02220d450d00200c4280808080107c210c417f4101200d4100481b220a450d020c030b200c4280808080107c210c4100417f41012005200a491b2005200a461b220a0d020c010b200441086a200441b0016a10a101200428020c210b0c030b200141086a2102200c200441b0016a41086a220a35020084210c20042802b401210b20042802b001210502402006450d00200710010b200420023602a80120042005360298012004200b36029c012004200c3703a001200441186a41106a2202200341106a280200360200200441186a41086a2205200341086a29020037030020042003290200370318200441b0016a41106a2201200b200c422088a741146c6a220b419c016a2208280200360200200a200b4194016a220d2902003703002004200b418c016a220b2902003703b00120082002280200360200200d2005290300370200200b2004290318370200200220012802003602002005200a290300370300200420042903b001370318200041106a2002280200360200200041086a200529030037020020002004290318370200200441c0046a24000f0b2002410c6a2102200b41016a210b200a4101460d000b0b2009280200210a20042802b4012102024020042802b0012208450d002008417f6a21082002200b4102746a41e8026a28020021020c010b0b200441186a41106a20023602002001200128020841016a360208200441186a41146a200bad422086200aad84220e3702002004200636021c2004200736021820042005ad37032020044180016a41106a2201200341106a28020036020020044180016a41086a2208200341086a2902003703002004200329020037038001024020022f0106220d410b4f0d002002200e422088a7220a410c6c6a220b41146a200b41086a2209200d200a6b410c6c10f9021a200b41106a2005360200200b410c6a2006360200200920073602002002200a41146c6a220541a0016a2005418c016a220b200241066a22022f0100200a6b41146c10f9021a2005419c016a200128020036020020054194016a2008290300370200200b200429038001370200200220022f010041016a3b01000c020b0240024041e80210002209450d00200941003b010620094100360200200941086a200441b0016a41e00210f802210a200441b0016a41106a220820024194026a280200360200200441b0016a41086a220d2002418c026a29020037030020042002290284023703b001200241d4006a290200210c200241d0006a280200210f200a200241dc006a200241066a220b2f010041796a2201410c6c10f80221032009418c016a20024198026a200141146c10f8022110200b41063b0100200920013b010620044198016a41106a200828020036020020044198016a41086a200d290300370300200420042903b0013703980102400240200e422088a7220a41064b0d00200820044180016a41106a280200360200200d20044180016a41086a29030037030020042004290380013703b001200241086a200a410c6c6a2201410c6a2001200b2f0100200a6b410c6c10f9021a2001200536020820012006360204200120073602002002418c016a200a41146c6a220541146a2005200b2f0100200a6b41146c10f9021a200541106a2008280200360200200541086a200d290300370200200520042903b001370200200b200b2f010041016a3b01000c010b2003200a410c6c6a220b41b87f6a200b41ac7f6a2208200141ffff0371200a41796a22016b410c6c10f9021a200b41b47f6a2005360200200b41b07f6a2006360200200820073602002010200a41146c6a220541887f6a200541f47e6a220b200941066a220a2f010020016b41146c10f9021a200541847f6a20044180016a41106a280200360200200541fc7e6a20044180016a41086a290300370200200b200429038001370200200a200a2f010041016a3b01000b200441e8006a41106a220520044198016a41106a280200360200200441e8006a41086a220a20044198016a41086a2903003703002004200429039801370368200441386a41106a2005280200360200200441386a41086a200a29030037030020042004290368370338200ea7211102400240024002400240024020022802002208450d00200420022f0104220d3602bc01200420113602b801200420083602b40141012105200441013602b00141000d010c020b200420113602b801200420023602b401200441003602b001201121054101450d010b200441b0016a210a419803210b419803100022020d010c050b0340200441e8006a41106a2213200441386a41106a2214280200360200200441e8006a41086a2215200441386a41086a22162903003703002004200429033837036820082f01062202410a4d0d024198031000220b450d03200b41003b0106200b4100360200200b41086a200441b0016a41900310f80221052008290254210e20082802502112200441b0016a41106a220320084194026a280200360200200441b0016a41086a22062008418c026a29020037030020042008290284023703b0012005200841dc006a200841066a22072f0100220a41796a2202410c6c10f8022117200b418c016a20084198026a200241146c10f8022118200b41e8026a20084184036a200a417a6a220141027410f8022110200741063b0100200b20023b010602402001450d00410021022010210503402005280200220a20023b0104200a200b360200200541046a2105200241016a22022001490d000b0b20044198016a41106a2202200328020036020020044198016a41086a22052006290300370300200420042903b0013703980120044180016a41106a2219200228020036020020044180016a41086a221a200529030037030020042004290398013703800102400240200d41064b0d002003201328020036020020062015290300370300200420042903683703b001200841086a200d410c6c6a2202410c6a200220072f0100200d6b410c6c10f9021a2002200c3702042002200f3602002008418c016a200d41146c6a220241146a200220072f0100200d6b41146c10f9021a200241106a2003280200360200200241086a2006290300370200200220042903b001370200200720072f010041016a22053b0100200841e8026a220a200d41027422016a41086a200a200d41016a22024102746a220a200541ffff037120026b41027410f9021a200a2009360200200220072f0100220d4b0d01200820016a41ec026a21050340200241016a220a2002490d022005280200220120023b010420012008360200200541046a2105200a2102200a200d4d0d000c020b0b2017200d410c6c6a220241b87f6a200241ac7f6a220a200b41066a22052f0100200d41796a22016b410c6c10f9021a200241b07f6a200c370200200a200f3602002018200d41146c6a220241887f6a200241f47e6a220a20052f010020016b41146c10f9021a200241847f6a2013280200360200200241fc7e6a2015290300370200200a2004290368370200200520052f010041016a220a3b01002010200d41027422076a416c6a2010200d417a6a22024102746a2201200a41ffff037120026b41027410f9021a20012009360200200220052f0100220d4b0d00200b20076a41d0026a21050340200241016a220a2002490d012005280200220120023b01042001200b360200200541046a2105200a2102200a200d4d0d000b0b200441d0006a41106a22022019280200360200200441d0006a41086a2205201a2903003703002004200429038001370350201420022802003602002016200529030037030020042004290350370338024020082802002202450d0020082f0104210d20022108200e210c2012210f200b21090c010b0b200441b0016a210a200e210c2012210f20112105200b2109419803210b41980310002202450d040b200241003b010620024100360200200241086a200a41900310f802210a200220052802003602e802200520023602002005200528020441016a36020420022802e802220541003b010420052002360200200a20022f01062205410c6c6a220b200c3702042002200541146c6a220a419c016a200441386a41106a2802002201360200200a4194016a200441386a41086a290300220c370200200a418c016a2004290338220e370200200b200f360200200241e8026a200541016a22054102746a2009360200200220022f010641016a3b0106200441b0016a41106a2001360200200441b0016a41086a200c370300200920053b0104200920023602002004200e3703b0010c050b200441b0016a41106a220a200441e8006a41106a280200360200200441b0016a41086a220b200441e8006a41086a290300370300200420042903683703b0012008200d410c6c6a220541146a200541086a22012002200d6b410c6c10f9021a2005410c6a200c3702002001200f3602002008200d41146c6a220241a0016a2002418c016a2201200841066a22052f0100200d6b41146c10f9021a2002419c016a200a28020036020020024194016a200b290300370200200120042903b001370200200520052f010041016a3b0100200841e8026a220a200d410274220b6a41086a200a200d41016a22024102746a220a20052f010020026b41027410f9021a200a2009360200200220052f010022014b0d042008200b6a41ec026a21050340200241016a220a2002490d052005280200220b20023b0104200b2008360200200541046a2105200a2102200a20014d0d000c050b0b41980341041019000b41e80241041019000b200b41041019000b41e80241041019000b200041053a0011200441c0046a24000bbd2a012f7f230041a00a6b2202240020002802102203200328020041016a360200200028020c210420002802082105200028020021062000280204210320024192016a2207200041166a2d00003a0000200220002f00143b0190012002200041276a29000037031820022000412c6a29000037001d200041176a28000021082000411b6a28000021092000411f6a280000210a200041236a280000210b200241c0096a41286a220c200141286a290300370300200241c0096a41206a220d200141206a290300370300200241c0096a41186a220e200141186a290300370300200241c0096a41106a220f200141106a290300370300200241c0096a41086a2210200141086a290300370300200220012903003703c009024020032f01062201410b4f0d00200320044105746a220041286a200041086a2206200120046b41057410f9021a200041206a200229001d370000200041176a200b360000200041136a200a3600002000410f6a20093600002000410b6a20083600002000410a6a20072d00003a0000200620022f0190013b00002000411b6a20022903183700002003200441306c6a22004198036a200041e8026a2201200341066a22032f010020046b41306c10f9021a20004190036a200c29030037030020004188036a200d29030037030020004180036a200e290300370300200041f8026a200f290300370300200041f0026a2010290300370300200120022903c009370300200320032f010041016a3b0100200241a00a6a240020010f0b0240024002400240024041f80610002207450d00200741003b010620074100360200200741086a200241a0026a41f00610f8022100200241a0026a41086a220d20034190056a290300370300200241a0026a41106a220e20034198056a290300370300200241a0026a41186a220f200341a0056a290300370300200241a0026a41206a2210200341a8056a290300370300200241a0026a41286a2211200341b0056a2903003703002002200341ca016a2d00003a0086022002200341c8016a2f00003b0184022002200341db016a2900003703f0012002200341e0016a2900003700f501200220034188056a2903003703a002200341cb016a2800002112200341cf016a2800002113200341d3016a2800002114200341d7016a28000021152000200341e8016a200341066a22012f010041796a220c41057410f8022100200741e8026a200341b8056a200c41306c10f8022116200141063b01002007200c3b0106200241ec016a41026a20022d0086023a0000200220022f0184023b01ec01200220022903f0013703d801200220022900f5013700dd01200241f0096a41286a2011290300370300200241f0096a41206a2010290300370300200241f0096a41186a200f290300370300200241f0096a41106a200e290300370300200241f0096a41086a200d290300370300200220022903a0023703f00902400240200441064b0d00200341086a20044105746a220041206a200020012f010020046b41057410f9021a200041186a200229001d3700002000200b36000f2000200a36000b2000200936000720002008360003200041026a20024190016a41026a2d00003a0000200020022f0190013b000020002002290318370013200341e8026a200441306c6a221741306a201720012f010020046b41306c10f9021a201741286a200241c0096a41286a290300370300201741206a200241c0096a41206a290300370300201741186a200241c0096a41186a290300370300201741106a200241c0096a41106a290300370300201741086a200241c0096a41086a290300370300201720022903c009370300200120012f010041016a3b01000c010b200020044105746a41c07e6a2000200441796a22014105746a2200200c41ffff037120016b41057410f9021a200041186a200229001d3700002000200b36000f2000200a36000b2000200936000720002008360003200041026a20024190016a41026a2d00003a0000200020022f0190013b0000200020022903183700132016200441306c6a220041e07d6a200041b07d6a2217200741066a22042f010020016b41306c10f9021a200041d87d6a200241c0096a41286a290300370300200041d07d6a200241c0096a41206a290300370300200041c87d6a200241c0096a41186a290300370300200041c07d6a200241c0096a41106a290300370300200041b87d6a200241c0096a41086a290300370300201720022903c009370300200420042f010041016a3b01000b200241f8006a41026a2200200241ec016a41026a2d00003a0000200241a8016a41086a2201200241f0096a41086a290300370300200241a8016a41106a2204200241f0096a41106a290300370300200241a8016a41186a2208200241f0096a41186a290300370300200241a8016a41206a2209200241f0096a41206a290300370300200241a8016a41286a220a200241f0096a41286a290300370300200220022f01ec013b0178200220022903d801370348200220022900dd0137004d200220022903f0093703a801200241146a41026a20002d00003a0000200241186a41086a2001290300370300200241186a41106a2004290300370300200241186a41186a2008290300370300200241186a41206a2009290300370300200241186a41286a200a290300370300200220022f01783b0114200220022903483703002002200229004d370005200220022903a8013703180240024020032802002208450d00200220032f0104220a3602ac02200220053602a802200220083602a4022002200641016a22163602a0024100450d010c030b200220053602a802200220033602a402200220063602a0022005211641010d020b024002400340200241a4016a41026a2218200241146a41026a22192d00003a0000200220022f01143b01a40120022002290300370390012002200229000537009501200241a8016a41286a221a200241186a41286a221b290300370300200241a8016a41206a221c200241186a41206a221d290300370300200241a8016a41186a221e200241186a41186a221f290300370300200241a8016a41106a2220200241186a41106a2221290300370300200241a8016a41086a2222200241186a41086a2223290300370300200220022903183703a80120082f01062203410a4d0d0141a80710002204450d02200441003b010620044100360200200441086a200241a0026a41a00710f80221032002419c026a41026a220c200841ca016a2d00003a0000200220082f00c8013b019c022002200841db016a290000370388022002200841e0016a29000037008d02200841cb016a2800002124200841cf016a2800002125200841d3016a2800002126200841d7016a2800002127200241a0026a41286a2206200841b0056a290300370300200241a0026a41206a220d200841a8056a290300370300200241a0026a41186a220e200841a0056a290300370300200241a0026a41106a220f20084198056a290300370300200241a0026a41086a221020084190056a29030037030020022008290388053703a0022003200841e8016a200841066a220b2f0100220141796a220041057410f8022128200441e8026a200841b8056a200041306c10f8022129200441f8066a20084194076a2001417a6a220941027410f8022111200b41063b0100200420003b010602402009450d00410021002011210303402003280200220120003b010420012004360200200341046a2103200041016a22002009490d000b0b200241f0096a41286a22002006290300370300200241f0096a41206a2203200d290300370300200241f0096a41186a2201200e290300370300200241f0096a41106a2209200f290300370300200241f0096a41086a222a2010290300370300200220022903a0023703f009200220022f019c023b01840220022002290388023703f0012002200229008d023700f5012002200c2d00003a008602200241ec016a41026a222b20022d0086023a0000200220022f0184023b01ec01200220022903f0013703d801200220022900f5013700dd01200241c0096a41286a222c2000290300370300200241c0096a41206a222d2003290300370300200241c0096a41186a222e2001290300370300200241c0096a41106a222f2009290300370300200241c0096a41086a2230202a290300370300200220022903f0093703c00902400240200a41064b0d00200c20182d00003a0000200220022f01a4013b019c02200220022903900137038802200220022900950137008d022006201a290300370300200d201c290300370300200e201e290300370300200f202029030037030020102022290300370300200220022903a8013703a002200841086a2203200a41016a22004105746a2003200a4105746a2203200b2f0100200a6b41057410f9021a2003201536000f2003201436000b2003201336000720032012360003200341026a200c2d00003a0000200320022f019c023b0000200341186a200229008d023700002003200229038802370013200841e8026a200a41306c6a220341306a2003200b2f0100200a6b41306c10f9021a200341286a2006290300370300200341206a200d290300370300200341186a200e290300370300200341106a200f290300370300200341086a2010290300370300200320022903a002370300200b200b2f010041016a22033b0100200841f8066a2201200a41027422096a41086a200120004102746a2201200341ffff037120006b41027410f9021a200120073602002000200b2f0100220b4b0d01200820096a41fc066a21030340200041016a22012000490d022003280200220920003b010420092008360200200341046a2103200121002001200b4d0d000c020b0b2028200a417a6a22004105746a2028200a41796a22094105746a2203200441066a22012f010020096b41057410f9021a200341186a2002290095013700002003201536000f2003201436000b2003201336000720032012360003200341026a20182d00003a0000200320022f01a4013b000020032002290390013700132029200a41306c6a220341e07d6a200341b07d6a220b20012f010020096b41306c10f9021a200341d87d6a201a290300370300200341d07d6a201c290300370300200341c87d6a201e290300370300200341c07d6a2020290300370300200341b87d6a2022290300370300200b20022903a801370300200120012f010041016a22033b01002011200a410274220c6a416c6a201120004102746a2209200341ffff037120006b41027410f9021a20092007360200200020012f0100220b4b0d002004200c6a41e0066a21030340200041016a22012000490d012003280200220920003b010420092004360200200341046a2103200121002001200b4d0d000b0b2002418c016a41026a2200202b2d00003a0000200241c8006a41086a22032030290300370300200241c8006a41106a2201202f290300370300200241c8006a41186a2209202e290300370300200241c8006a41206a220b202d290300370300200241c8006a41286a2207202c290300370300200220022f01ec013b018c01200220022903d801370378200220022900dd0137007d200220022903c009370348201b2007290300370300201d200b290300370300201f20092903003703002021200129030037030020232003290300370300201920002d00003a000020022002290348370318200220022903783703002002200229007d370005200220022f018c013b01140240024020082802002203450d00201641016a211620082f0104210a41002100200321080c010b41012100200521160b20262114202521132024211220272115200421072000450d000b200241a0026a2103202621142025211320242112202721152004210741a807210141a807100022000d040c060b2002419c026a41026a2204200241a4016a41026a2d00003a0000200220022f01a4013b019c02200220022903900137038802200220022900950137008d02200241a0026a41286a2209200241a8016a41286a290300370300200241a0026a41206a220b200241a8016a41206a290300370300200241a0026a41186a220c200241a8016a41186a290300370300200241a0026a41106a2206200241a8016a41106a290300370300200241a0026a41086a220d200241a8016a41086a290300370300200220022903a8013703a002200841086a2201200a41016a22004105746a2001200a4105746a22012003200a6b41057410f9021a2001201536000f2001201436000b2001201336000720012012360003200141026a20042d00003a0000200120022f019c023b0000200141186a200229008d0237000020012002290388023700132008200a41306c6a22034198036a200341e8026a2204200841066a22012f0100200a6b41306c10f9021a20034190036a200929030037030020034188036a200b29030037030020034180036a200c290300370300200341f8026a2006290300370300200341f0026a200d290300370300200420022903a002370300200120012f010041016a3b0100200841f8066a2203200a41027422046a41086a200320004102746a220320012f010020006b41027410f9021a20032007360200200020012f010022094b0d04200820046a41fc066a21030340200041016a22012000490d052003280200220420003b010420042008360200200341046a210320012100200120094d0d000c050b0b41a80741081019000b41f80641081019000b200241a0026a210341a807210141a80710002200450d020b200041003b010620004100360200200041086a200341a00710f8022103200020162802003602f806201620003602002016201628020441016a36020420002802f806220141003b010420012000360200200220022900053700f509200220022903003703f009200241a0026a41286a2204200241186a41286a290300370300200241a0026a41206a2208200241186a41206a290300370300200241a0026a41186a2209200241186a41186a290300370300200241a0026a41106a220a200241186a41106a290300370300200241a0026a41086a220b200241186a41086a290300370300200320002f010622014105746a220320022f01143b0000200341026a200241146a41026a2d00003a0000200220022903183703a0022003201536000f2003201436000b2003201336000720032012360003200341186a20022900f509370000200320022903f0093700132000200141306c6a22034190036a200429030037030020034188036a200829030037030020034180036a2009290300370300200341f8026a200a290300370300200341f0026a200b290300370300200341e8026a20022903a002370300200041f8066a200141016a22034102746a2007360200200020002f010641016a3b0106200720033b0104200720003602000b200241a00a6a240020170f0b200141081019000be40801097f230041106b22022400200241003602082002420137030041c59ec10041042002108e0141c99ec100410e2002108e010240024002400240024002400240024002400240024020022802042203200228020822046b41044f0d00200441046a22052004490d0420034101742206200520052006491b22074100480d042003450d0120022802002108200710002206450d072006200820072003200320074b1b10f8021a200810010c020b200441046a2105200228020021060c020b200710002206450d050b20022007360204200220063602000b200241086a22032005360200200620046a4101360000024002400240024020022802042207200328020022056b41034b0d00200541046a22042005490d0420074101742208200420042008491b22084100480d042008100021042007450d012004450d082004200620082007200720084b1b10f8021a200610010c020b200621040c020b2004450d060b20022008360204200220043602000b2003200541046a360200200420056a4101360000024002400240024020022802042205200328020022036b41034b0d00200341046a22062003490d0420054101742207200620062007491b22064100480d042006100021072005450d012007450d092007200420062005200520064b1b10f8021a200410010c020b200421070c020b2007450d070b20022006360204200220073602000b200241086a2205200341046a360200200720036a410036000002400240024002402002280204220420052802002206470d00200641016a22042006490d0420064101742203200420042003491b22044100480d042004100021052006450d012005450d0a2005200720042006200620044b1b10f8021a200710010c020b200228020021050c020b2005450d080b20022004360204200220053602000b200241086a2208200641016a2203360200200520066a41183a000041d89ec100210603400240024002400240200420036b41084f0d00200341086a22092003490d0520044101742207200920092007491b220a4100480d05200a100021072004450d012007450d0620072005200a20042004200a4b1b10f8021a200510010c020b200341086a2109200521070c020b2007450d040b2002200a360204200220073602000b20082009360200200720036a2006290000370000200641086a2802002109024002400240024020022802042203200828020022076b41044f0d00200741046a22042007490d0520034101742205200420042005491b22044100480d052003450d012002280200210a200410002205450d072005200a20042003200320044b1b10f8021a200a10010c020b20022802002105200321040c020b200410002205450d050b20022004360204200220053602000b2008200741046a2203360200200520076a20093600002006410c6a220641a09fc100470d000b200241106a24002003ad4220862005ad840f0b1018000b200a41011019000b200441011019000b200741011019000b200841011019000b200641011019000b200441011019000b9204010a7f230041206b22022400024002400240410610002203450d002002420637021420022003360210200241106a41bab6c10041061025200241086a2203200228021836020020022002290310370300200241b7b6c100410310252002280204210420022802002205200328020010c401210302402004450d00200510010b200241002003104620024100360218200242013703102002280200210620022802082203200241106a101b0240024002402003450d0020034105742107200241106a41086a280200210820022802102109200228021421052006210a0340200a210302400240024002402005200822046b41204f0d00200441206a22082004490d062005410174220a20082008200a491b220a4100480d06200a1000210b2005450d01200b450d07200b2009200a20052005200a4b1b10f8021a200910010c020b200441206a21080c020b200b450d050b200b2109200a21050b200341206a210a200920046a22042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200741606a22070d000b200241186a200836020020022005360214200220093602102002280204450d050c040b200241186a28020021082002280210210920022802040d030c040b1018000b200a41011019000b410641011019000b200610010b200241206a24002008ad4220862009ad840bec1703027f017e0f7f230041d0086b22022400024002402001450d00200220003602200c010b20024188f0c1003602200b20022001360224200241f8066a200241206a10a50102400240024002400240200228028007450d00200241286a200241f8066a41880110f8021a200241b0016a200241286a41880110f8021a20022903b001200241c4016a220120024184026a220310e601024020022903b0012204500d00200241f8066a2004427f7c10e701200241f8066a2001412010fa020d00200241186a20022802a80222012001200241b0026a28020041d8016c6a102e200228021c2205200228021822006b220141d8016e21064100210741042108410021090240200141d801490d002006410c6c220110002208450d06200621090b024020002005460d0041002107200821010340200220003602a004200241f8066a200241a0046a10e801200141086a200241f8066a41086a280200360200200120022903f806370200200741016a21072001410c6a21012005200041d8016a2200470d000b0b200241106a200820082007410c6c6a102e200241a0046a200228021020022802141045200241f8066a20022802a004220120022802a804106b024020022802a404450d00200110010b02402007450d002007410c6c21002008210103400240200141046a280200450d00200128020010010b2001410c6a2101200041746a22000d000b0b02402009450d00200810010b02402003200241f8066a412010fa02450d0041b18dc000410e1006200341201009200241f8066a412010090b20024184026a200241f8066a412010fa020d02200241ac026a2802002109200241b0016a41f8006a2802002103200241b0026a2802002107200241b8026a200241b0016a41f80010f8021a2003200741d8016c6a210020032101024002400240024002402007450d00200241a0046a41f8006a2105200241f8066a41086a2108200321010340200241b0036a200141f00010f8021a200141f0006a290300210420024198066a200141f8006a41e00010f8021a20044203510d02200241a0046a200241b0036a41f00010f8021a200241a0046a41f0006a2004370300200520024198066a41e00010f8021a2002200241a0046a3602f805200241f8066a200241f8056a10e80120082802002107024020022802fc06450d0020022802f80610010b200241f8066a200241a0046a41d80110f8021a200241f8056a200241f8066a200710e90120022802f8054101460d05024020022802fc052207450d002007200241f8056a41086a28020010060b200141d8016a22012000470d000b200021010b20012000470d010c020b200141d8016a22012000460d010b20024180086a2107200241f8066a41f8006a21050340200241f8066a200141f00010f8021a200141f0006a2903002104200241b0036a200141f8006a41e00010f8021a20044203510d01200241a0046a200241f8066a41f00010f8021a20024198066a200241b0036a41e00010f8021a200241f8066a200241a0046a41f00010f8021a200241f8066a41f0006a2004370300200520024198066a41e00010f8021a20071028200141d8016a22012000470d000b0b02402009450d00200310010b10ea0120022903b80210eb01200241f8066a10ec012002200241b8026a41106a280200220a36028c062002200241f8066a41106a28020022013602900620022002418c066a36029406200220024190066a3602f805200a2001470d0420022802c002210b200241086a200228028007220c200c200a41286c6a102e02400240200228020c2002280208220d6b41286e2201200a200a20014b1b220e450d004100210f034002400240200b200f41286c22076a22002d00002201200d20076a22072d0000470d000240024020014101460d0020014102470d01200041086a290300200741086a290300520d02200041186a2802002210200741186a280200470d0241002105200041106a28020022112108200741106a280200221221030340200520104f0d04200541016a22092005490d04024020112012460d0020082003412010fa020d040b200341206a2106200841206a2113200841286a2108200341286a21032009210520132903002006290300510d000c030b0b2000410c6a28020022062007410c6a280200470d0141002105200041046a28020022132108200741046a28020022102103410020064f0d020340200541016a22092005490d03024020132010460d0020082003412010fa020d030b200841206a2108200341206a21032009220520064f0d030c000b0b200b200d460d01200041016a200741016a412010fa02450d010b41939ec10041141006200241a0046a2000102020022802a0042205200241a0046a41086a22012802001009024020022802a404450d00200510010b200241a0046a2007102020022802a004220520012802001009024020022802a404450d00200510010b20002d000020072d00002201470d030b02400240024020014102460d0020014101470d012000410c6a28020022082007410c6a280200470d0541002101200041046a28020022032100200741046a28020022092107410020084f0d020340200141016a22052001490d03024020032009460d0020002007412010fa020d070b200041206a2100200741206a21072005220120084f0d030c000b0b200041086a290300200741086a290300520d04200041186a2802002209200741186a280200470d0441002101200041106a28020022062100200741106a280200221321070340200120094f0d02200141016a22052001490d02024020062013460d0020002007412010fa020d060b200741206a2108200041206a2103200041286a2100200741286a21072005210120032903002008290300510d000c050b0b200b200d460d00200041016a200741016a412010fa020d030b200f41016a220f200e490d000b0b200241a0046a41186a22014200370300200241a0046a41106a22004200370300200241a0046a41086a22074200370300200242003703a004200241a0046a100a200241b0036a41186a2001290300370300200241b0036a41106a2000290300370300200241b0036a41086a2007290300370300200220022903a0043703b0030240200241ec026a2201200241b0036a412010fa02450d0041b18dc000410e1006200141201009200241b0036a412010090b2001200241b0036a412010fa020d060240200a450d00200a41286c2100200c21010340024020012d00002207450d00024020074101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b024020024184076a280200450d00200c10010b0240200241b8026a41106a2802002200450d00200241b8026a41086a2802002101200041286c21000340024020012d00002207450d00024020074101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b0240200241c4026a280200450d00200241c0026a28020010010b200241d0086a240042010f0b418084c300104f000b0240024020022802fc052202450d0020024103460d01418883c300104f000b41b883c300104f000b41a083c300104f000b41d882c300104f000b200241b4046a4101360200200241ac046a4101360200200241013602b401200241dcd5c2003602b001200241e0c3c1003602a804200241013602a404200241e4d5c2003602a0042002200241b0016a3602b004200241a0046a41ecd5c2001071000b41f082c300104f000b200241a0046a41146a4100360200200241b0036a41146a4109360200200241b0036a410c6a410d36020020024198066a41146a410336020020024198066a410c6a410336020020024188f0c1003602b004200242013702a404200241d083c3003602a0042002410d3602b403200241b0b3c1003602a0062002410336029c06200241d883c300360298062002200241a0046a3602c0032002200241f8056a3602b803200220024194066a3602b0032002200241b0036a3602a80620024198066a41f083c3001071000b419884c300104f000b200141041019000bdf1801267f230041900d6b220324002003410036021041bef1c1004110200341106a41041003200320003703f00c200341106a41086a220442003703002003420037031041f0f1c100410d200341106a1002200341086a220520042903003703002003200329031037030020034110200341f00c6a41081003200442003703002003420037031041fdf1c1004111200341106a1002200520042903003703002003200329031037030020034110200141201003024002400240411010002204450d002003421037021420032004360210200341106a41dbf1c100411010252003280210210502400240024020032802142206200328021822046b41084f0d00200441086a22072004490d0420064101742208200720072008491b22084100480d042006450d01200810002209450d052009200520082006200620084b1b10f80221092005100120082106200921050c020b200441086a21070c010b200810002205450d03200821060b200520046a2000427f7c370000200341106a41086a220442003703002003420037031020052007200341106a1002200341086a22072004290300370300200320032903103703002003411020014120100302402006450d00200510010b2004420037030020034200370310418ef2c1004115200341106a1002200720042903003703002003200329031037030020034110200241201003200442003703002003420037031041f0f1c100410d200341106a100220072004290300370300200320032903103703000240200341104188f0c100410041001004417f460d00200342003703100240024020034110200341106a41084100100441016a41084d0d0020032903104200510d02200341106a41086a220442003703002003420037031041f0f1c100410d200341106a1002200341086a20042903003703002003200329031037030002400240200341104188f0c100410041001004417f460d002003420037031020034110200341106a41084100100441016a41084d0d032003290310427f7c21000c010b427f21000b41002109200341106a410041e00c10f7021a4100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f410021204100212141002122410021234100212441002125410021264100212741002108410021280340200341f00c6a42002000427f7c2000501b220010e701200341106a202822064103704105746a220441186a200341f00c6a41186a290200370000200441106a200341f00c6a41106a290200370000200441086a200341f00c6a41086a290200370000200420032902f00c370000200641016a21284100210541002107024003402006200641036e2201417d6c6a4102470d01200341106a20056a220441df006a2d000022082004411f6a2d000022027120082002722004413f6a2d000071722119200441de006a2d000022082004411e6a2d000022027120082002722004413e6a2d000071722118200441dd006a2d000022082004411d6a2d000022027120082002722004413d6a2d000071722117200441dc006a2d000022082004411c6a2d000022027120082002722004413c6a2d000071722116200441db006a2d000022082004411b6a2d000022027120082002722004413b6a2d000071722115200441da006a2d000022082004411a6a2d000022027120082002722004413a6a2d000071722114200441d9006a2d00002208200441196a2d00002202712008200272200441396a2d000071722113200441d8006a2d00002208200441186a2d00002202712008200272200441386a2d000071722112200441d7006a2d00002208200441176a2d00002202712008200272200441376a2d000071722111200441d6006a2d00002208200441166a2d00002202712008200272200441366a2d000071722110200441d5006a2d00002208200441156a2d00002202712008200272200441356a2d00007172210f200441d4006a2d00002208200441146a2d00002202712008200272200441346a2d00007172210e200441d3006a2d00002208200441136a2d00002202712008200272200441336a2d00007172210d200441d2006a2d00002208200441126a2d00002202712008200272200441326a2d00007172210c200441d1006a2d00002208200441116a2d00002202712008200272200441316a2d00007172210b200441d0006a2d00002208200441106a2d00002202712008200272200441306a2d00007172210a200441cf006a2d000022082004410f6a2d000022027120082002722004412f6a2d000071722109200441ce006a2d000022082004410e6a2d000022027120082002722004412e6a2d00007172211a200441cd006a2d000022082004410d6a2d000022027120082002722004412d6a2d00007172211b200441cc006a2d000022082004410c6a2d000022027120082002722004412c6a2d00007172211c200441cb006a2d000022082004410b6a2d000022027120082002722004412b6a2d00007172211d200441ca006a2d000022082004410a6a2d000022027120082002722004412a6a2d00007172211e200441c9006a2d00002208200441096a2d00002202712008200272200441296a2d00007172211f200441c8006a2d00002208200441086a2d00002202712008200272200441286a2d000071722120200441c7006a2d00002208200441076a2d00002202712008200272200441276a2d000071722121200441c6006a2d00002208200441066a2d00002202712008200272200441266a2d000071722122200441c5006a2d00002208200441056a2d00002202712008200272200441256a2d000071722123200441c4006a2d00002208200441046a2d00002202712008200272200441246a2d000071722124200441c3006a2d00002208200441036a2d00002202712008200272200441236a2d000071722125200441c2006a2d00002208200441026a2d00002202712008200272200441226a2d000071722126200441c1006a2d00002208200441016a2d00002202712008200272200441216a2d000071722127200441c0006a2d0000220820042d00002202712008200272200441206a2d000071722108200541800c460d01200341106a20052001410574200641096e41e0006c6b6a6a220441ff006a20193a0000200441fe006a20183a0000200441fd006a20173a0000200441fc006a20163a0000200441fb006a20153a0000200441fa006a20143a0000200441f9006a20133a0000200441f8006a20123a0000200441f7006a20113a0000200441f6006a20103a0000200441f5006a200f3a0000200441f4006a200e3a0000200441f3006a200d3a0000200441f2006a200c3a0000200441f1006a200b3a0000200441f0006a200a3a0000200441ef006a20093a0000200441ee006a201a3a0000200441ed006a201b3a0000200441ec006a201c3a0000200441eb006a201d3a0000200441ea006a201e3a0000200441e9006a201f3a0000200441e8006a20203a0000200441e7006a20213a0000200441e6006a20223a0000200441e5006a20233a0000200441e4006a20243a0000200441e3006a20253a0000200441e2006a20263a0000200441e1006a20273a0000200441e0006a20083a0000200541e0006a210520012106200741016a22074111490d000b0b202841d100470d000b200320193a008f0d200320183a008e0d200320173a008d0d200320163a008c0d200320153a008b0d200320143a008a0d200320133a00890d200320123a00880d200320113a00870d200320103a00860d2003200f3a00850d2003200e3a00840d2003200d3a00830d2003200c3a00820d2003200b3a00810d2003200a3a00800d200320093a00ff0c2003201a3a00fe0c2003201b3a00fd0c2003201c3a00fc0c2003201d3a00fb0c2003201e3a00fa0c2003201f3a00f90c200320203a00f80c200320213a00f70c200320223a00f60c200320233a00f50c200320243a00f40c200320253a00f30c200320263a00f20c200320273a00f10c200320083a00f00c200341106a41086a220442003703002003420037031041a3f2c1004111200341106a1002200341086a220520042903003703002003200329031037030020034110200341f00c6a41201003200442003703002003420037031041cef1c100410d200341106a10022005200429030037030020032003290310370300200341101008200341900d6a24000f0b41eac4c10041331042000b41eac4c10041331042000b4180a0c300104f000b411041011019000b1018000b200841011019000bf30402097f037e230041d0006b2202240002400240024002400240411010002203450d002002421037023420022003360230200241306a41dbf1c1004110102520022802302103024002400240024020022802342204200228023822056b41084f0d00200541086a22062005490d0520044101742207200620062007491b22074100480d052004450d01200710002208450d062008200320072004200420074b1b10f802210420031001200421030c020b200541086a21060c020b200710002203450d040b200721040b200320056a2001370000200241306a41086a220542003703002002420037033020032006200241306a1002200241206a41086a20052903003703002002200229033037032002400240200241206a41104188f0c100410041001004417f460d00200241c8006a4200370300200241306a41106a42003703002005420037030020024200370330200241206a4110200241306a4120410010042205417f460d012005411f4d0d01200241186a2205200241306a41186a2206290300370300200241106a2207200241306a41106a2208290300370300200241086a2209200241306a41086a220a2903003703002002200229033037030020062005290300220137030020082007290300220b370300200a2009290300220c37030020002002290300220d370000200041086a200c370000200041106a200b370000200041186a20013700002002200d3703302004450d060c050b20004200370000200041186a4200370000200041106a4200370000200041086a420037000020040d040c050b41eac4c10041331042000b411041011019000b1018000b200741011019000b200310010b200241d0006a24000ba41703067f027e047f230041d0006b220224000240024002400240024002400240024002400240024002400240024002400240024041da0110002203450d00200242da0137021420022003360210200241106a4102102702400240024002400240024002400240200128020022012903704202520d00200241186a220428020022032002280214470d03200341016a22052003490d1620034101742206200520052006491b22054100480d162003450d0120022802102107200510002206450d0a2006200720052003200320054b1b10f8021a200710010c020b200241106a41086a220428020022032002280214470d05200341016a22052003490d1520034101742206200520052006491b22054100480d152003450d0320022802102107200510002206450d0a2006200720052003200320054b1b10f8021a200710010c040b200510002206450d080b2002200536021420022006360210200241186a28020021030b200228021020036a41013a00002004200428020041016a3602000c030b200510002206450d060b2002200536021420022006360210200241186a28020021030b200228021020036a4181013a00002004200428020041016a360200200141086a200241106a10a401024002400240024020022802142207200428020022036b41c0004f0d00200341c0006a22042003490d1320074101742203200420042003491b22054100480d132007450d0120022802102103200510002206450d092006200320052007200720054b1b10f8021a200310010c020b20022802102106200721050c020b200510002206450d070b2002200536021420022006360210200241186a28020021030b200241106a41086a2207200341c0006a2204360200200620036a220341386a200141e4006a290000370000200341306a200141dc006a290000370000200341286a200141d4006a290000370000200341206a200141cc006a290000370000200341186a200141c4006a290000370000200341106a2001413c6a290000370000200341086a200141346a2900003700002003200129002c370000200129030021080240024002400240200520046b41074b0d00200441086a22032004490d1320054101742204200320032004491b22044100480d132004100021032005450d012003450d0a2003200620042005200520044b1b10f8021a200610010c020b200621030c020b2003450d080b2002200436021420022003360210200241186a28020021040b2007200441086a360200200320046a200837000002400240024002400240024002400240200141f0006a2903004201520d00200141f8006a2903002208420c882209420120094201561b22094200510d0f20014180016a290300200980210920022802142205200241186a28020022036b41024f0d01200341026a22042003490d1720054101742203200420042003491b22034100480d172005450d0520022802102106200310002204450d112004200620032005200520034b1b10f8021a200610010c060b02402002280214200241186a2802002203470d00200341016a22042003490d1720034101742205200420042005491b22054100480d172003450d0220022802102106200510002204450d102004200620052003200320054b1b10f8021a200610010c030b200228021021040c030b200228021021040c050b200510002204450d0d0b2002200536021420022004360210200241186a28020021030b200241186a200341016a360200200420036a41003a00000c030b200310002204450d0b0b2002200336021420022004360210200241186a28020021030b200241186a200341026a360200200420036a2009a741047420087aa7417f6a22034101200341014b1b2203410f2003410f491b723b00000b20014188016a200241106a101c0240024002400240200241186a28020022034102460d004101210120034103460d012003417e6a21034101210103402001220441016a22012003490d000b200441016a2201413f4d0d012001418080014f0d024102210341021000220a450d0d200a20014102744101723b00002002280218220141014b0d110c030b410021010b4101210341011000220a450d03200a20014102743a00002002280218220141014d0d010c0f0b024020014180808080044f0d004104210341041000220a450d0c200a20014102744102723600002002280218220141014b0d0f0c010b410110002204450d0c200441033a00004105210341051000220a450d0d200a20042d00003a000020041001200a20013600012002280218220141014b0d0e0b41d08ec200104f000b41da0141011019000b410141011019000b200541011019000b200541011019000b200541011019000b200441011019000b418cacc300104f000b200541011019000b200341011019000b410241011019000b410441011019000b410141011019000b410541011019000b200241186a2205410036020020022802102104200241086a200a200a20036a102e200241386a200228020c220b360200200241023602202002412c6a200441026a220436020020022001417e6a2201360224200220022802082203360234200220043602282002200241106a360230200241346a210c02400240024002400240024002402001450d000240200528020022014102460d0020022802102106200241346a2105200241186a2104200241386a21072003200b460d07024003402005200341016a360200200620016a20032d00003a00002004200428020041016a36020020014101460d01200141016a2101200528020022032007280200460d090c000b0b200241386a280200210b200241346a28020021030b200b20036b2201450d05200241306a280200220641046a28020022072002280224220d200228022022046a22056b20014f0d01200520016a22042005490d0720074101742205200420042005491b22044100480d072007450d022006280200210d200410002205450d082005200d20042007200720044b1b10f8021a200d10010c030b200241106a200c103f0c050b200628020021050c020b200410002205450d050b20062005360200200641046a20043602002002280224210d200228022021040b2005200420016a22016a200520046a200d10f9021a200220013602202001200241306a28020022062802082207460d00200b20046a200320076a6b2105200628020020076a2101200241386a2107200241346a2104200641086a21060340200428020022032007280200460d022004200341016a360200200120032d00003a00002006200628020041016a360200200141016a21012005417f6a22050d000b0b2002410036024820024201370340200241c0006a200c103f200228024421072002280240210b024020022802482201450d000240024002400240200241306a280200220541046a28020022062002280224220c200228022022036a22046b20014f0d00200420016a22032004490d0620064101742204200320032004491b22034100480d062006450d012005280200210c200310002204450d082004200c20032006200620034b1b10f8021a200c10010c020b200528020021040c020b200310002204450d060b20052004360200200541046a20033602002002280224210c200228022021030b2004200320016a22056a200420036a200c10f9021a200220053602202005200241306a2802002204280208220c460d00200c20036b21062004280200200c6a2103200441086a2105200b210403402001450d01200320042d00003a00002005200528020041016a360200200441016a2104200341016a210320062001417f6a2201470d000b0b2007450d00200b10010b0240200241286a22012802002002412c6a2802002203460d00200120033602000b024020022802242201450d00024020022802202205200241306a280200220641086a22042802002203460d002006280200220620036a200620056a200110f9021a200228022421010b2004200120036a3602000b200a1001200041086a200241106a41086a28020036020020002002290310370200200241d0006a24000f0b1018000b200441011019000b200341011019000bce0c05017f017e027f017e047f230041a0066b2203240020034188046a200141d80110f8021a20034180036a20034188046a10f70102402003280280034101470d00200329028403210420034190016a20034188026a41f80010f8021a200041086a200437020020004201370200200341a0066a24000f0b20034180036a41086a290300210420034188026a20034180036a41106a41f80010f8021a20034190016a20034188026a41f80010f8021a20032004370310410021050240024002400240200341106a41086a20034190016a41f80010f80222014100200329031022044201511b2206450d002006450d00024002400240200610f901220420062903202207520d002006200210f801450d0220004281808080303702000c010b2000410136020020004101410220072004541b3602040b200341c0006a10fa01200341a0066a24000f0b411310002202450d022003421337028c04200320023602880420034188046a41abf1c1004113102520034180036a41086a2202200328029004360200200320032903880437038003200620034180036a101e200228020021082003280284032109200328028003210a20034188046a41086a220b42003703002003420037038804200a200820034188046a10022002200b29030037030020032003290388043703800302400240024020034180036a41104188f0c100410041001004417f460d00200342003703880420034180036a411020034188046a41084100100441016a41084d0d0420032903880442017c210420090d010c020b420121042009450d010b200a10010b411310002202450d032003421337028c04200320023602880420034188046a41abf1c1004113102520034180036a41086a2202200328029004360200200320032903880437038003200620034180036a101e2002280200210a20032802840321082003280280032106200320043703880220034188046a41086a2209420037030020034200370388042006200a20034188046a10022002200929030037030020032003290388043703800320034180036a411020034188026a4108100302402008450d00200610010b200329031021040b20034188046a200341386a41d80010f8021a20034180036a20034188046a41086a41d00010f8021a20034188026a41186a2206200141186a29030037030020034188026a41106a200141106a29030037030020034188026a41086a200141086a2903003703002003200129030037038802024020044201520d0020034190016a41186a200629030037030020034190016a41106a20034188026a41106a29030037030020034190016a41086a20034188026a41086a290300370300200320032903880237039001410121050b20034188026a20034180036a41d00010f8021a20034180066a41186a220a20034190016a41186a29030037030020034180066a41106a220820034190016a41106a220129030037030020034180066a41086a220920034190016a41086a220229030037030020032003290390013703800620034180036a20034188026a41d00010f8021a200341e0056a41186a220b200a290300370300200341e0056a41106a220a2008290300370300200341e0056a41086a2208200929030037030020032003290380063703e00520034188046a20034180036a41d00010f8021a2006200b29030037030020034188026a41106a2209200a29030037030020034188026a41086a220a2008290300370300200320032903e005370388024102210602402005450d0020034190016a41186a20034188026a41186a290300370300200120092903003703002002200a290300370300200320032903880237039001410121060b20034192026a20022903003701002003419a026a2001290300370100200341a2026a200341a8016a290300370100200320063a008902200341003a008802200320032903900137018a02200341086a20034188046a20034188026a10cc02200328020c210620032802082101200341003a008804200320014100473a00890420034188046a10b401200310f0012003200328020441016a410120032802001b3602880441bef1c100411020034188046a41041003024002402001450d00200020013602040c010b200041003602040b20004100360200200041086a2006360200200341a0066a24000f0b41eac4c10041331042000b411341011019000b411341011019000bd40101037f230041306b2200240002400240024041bef1c10041104188f0c100410041001004417f460d00200041003602204101210141bef1c1004110200041206a41044100100441016a41044d0d022000280220210241bef1c100411010080c010b410021010b20002002410020011b36020c200041206a41086a220142003703002000420037032041c8f5c1004115200041206a1002200041106a41086a200129030037030020002000290320370310200041106a41102000410c6a41041003200041306a24000f0b41eac4c10041331042000bf8a90107037f017e057f037e187f0e7e027f23004190086b220124000240024002400240024041f2a1c100411310a702220241ff01714102460d002002410171450d00200141c0036a41086a22024200370300200142003703c003419ab6c100411d200141c0036a100220014190036a41086a2002290300370300200120012903c0033703900320014190036a41104188f0c100410041001004417f460d04200142103702bc06200120014190036a3602b806200141a0076a200141b8066a103420012802a0072203450d0120012902a4072104200141c0036a41086a22024200370300200142003703c003419ab6c100411d200141c0036a1002200141e0036a41086a2002290300370300200120012903c0033703e003200141e0036a41101008410610002202450d02200142063702a407200120023602a007200141a0076a41bab6c10041061025200141b8066a41086a220220012802a807360200200120012903a0073703b806200141b8066a41b7b6c1004103102520012802bc06210520012802b8062206200228020010c401210702402005450d00200610010b41002102200141e0046a410020071046024020012802e80422082004422088a7470d0020012802e00422092105200321070240410020084f0d000340200241016a22062002490d01024020092003460d0020052007412010fa020d030b200541206a2105200741206a2107200622022008490d000b0b024020012802e404450d00200910010b2004a7450d050c040b200141c3066a200141e0046a41086a280200360000200120012903e0043700bb06200141a0076a41086a200141bf066a290000370000200141013a00a007200120012900b8063700a107200141a0076a10e0022004a70d030c040b41d4f6c200104f000b41eac4c10041331042000b410641011019000b200310010b200141c0036a41086a22024200370300200142003703c00341c1f1c0004118200141c0036a100220014190036a41086a22052002290300370300200120012903c0033703900342002104024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0120012903a00721040b20024200370300200142003703c00341d9f1c0004115200141c0036a100220052002290300370300200120012903c003370390030240024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0320012903a007220a4200520d0141c8cdc200104f000b42e807210a0b200020047d200a82210402400240024002400240024041eef1c000411910a702220541ff017122074102470d0020044200520d010b4200210b200141c0036a41086a22024200370300200142003703c00341a0a5c100410d200141c0036a100220014190036a41086a22062002290300370300200120012903c003370390034200210a024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0a20012903a007210a0b20024200370300200142003703c0034187f2c0004114200141c0036a100220062002290300370300200120012903c00337039003024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0b20012903a007210b0b200141c0036a41086a22024200370300200142003703c003419bf2c0004114200141c0036a100220014190036a41086a2002290300370300200120012903c003370390030240024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0d20012903a00742017c210c0c010b4201210c0b2004502106200141a0076a41086a200c370300200141023a00a007200141a0076a10b4012001200c3703a007200141c0036a41086a22024200370300200142003703c003419bf2c0004114200141c0036a100220014190036a41086a22032002290300370300200120012903c0033703900320014190036a4110200141a0076a410810032001200a3703a00720024200370300200142003703c0034187f2c0004114200141c0036a100220032002290300370300200120012903c0033703900320014190036a4110200141a0076a4108100320014180036a41aff2c000411910a602024002400240200129038003a74101470d0020012001290388033703a00720024200370300200142003703c00341d9f1c0004115200141c0036a100220032002290300370300200120012903c0033703900320014190036a4110200141a0076a410810030c010b20060d010b200141c0036a41086a22024200370300200142003703c00341f0f1c100410d200141c0036a100220014190036a41086a22032002290300370300200120012903c0033703900342002104024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0e20012903a00721040b200120043703a00720024200370300200142003703c00341c1f1c0004118200141c0036a100220032002290300370300200120012903c0033703900320014190036a4110200141a0076a410810030b200a200b7d2006200541017120074102461b10c101200141c0036a41086a22024200370300200142003703c00341c8f2c0004112200141c0036a100220014190036a41086a2002290300370300200120012903c0033703900302400240024020014190036a41104188f0c100410041001004417f460d00200142103702bc06200120014190036a3602b806200141a0076a200141b8066a103620012802a007220d450d1220012802a407210e4101210f200d4101200d1b2110200141a8076a2802004100200d1b22020d010c020b4100210d4101210f4100410141001b21104100410041001b2202450d010b2002410574211120102109410021080340411210002202450d04200142123702a407200120023602a007200141a0076a41daf2c00041121025200141b8066a41086a2202200141a0076a41086a2205280200360200200120012903a0073703b8062009200141b8066a101e2002280200211420012802bc06211520012802b806210620014190036a41086a2203420037030020014200370390032006201420014190036a1002200141e0036a41086a2216200329030037030020012001290390033703e00302400240200141e0036a41104188f0c100410041001004417f460d00200141c0036a41186a22174200370300200141c0036a41106a22184200370300200141c0036a41086a22194200370300200142003703c003200141e0036a4110200141c0036a4120410010042207417f460d052007411f4d0d05200141a0076a41186a22122017290300370300200141a0076a41106a2213201829030037030020052019290300370300200120012903c0033703a007200141a0036a41186a221a20122903002204370300200141a0036a41106a221b2013290300220a370300200141a0036a41086a221c2005290300220c3703002002200c370300200141b8066a41106a221d200a370300200141b8066a41186a221e2004370300200120012903a00722043703b806200120043703a003200141e0046a41186a221f201e290300370300200141e0046a41106a2220201d290300370300200141e0046a41086a22072002290300370300200120012903b8063703e0042003420037030020014200370390032006201420014190036a10022019200329030037030020012001290390033703c003200141c0036a4110100820014180046a41186a2203201f29030037030020014180046a41106a2214202029030037030020014180046a41086a22212007290300370300200120012903e00437038004200141e8056a41186a22222003290300370300200141e8056a41106a22232014290300370300200141e8056a41086a2224202129030037030020012001290380043703e80502402015450d00200610010b200320222903003703002014202329030037030020212024290300370300200120012903e80537038004200120083602e004410610002206450d08200142063702a407200120063602a007200141a0076a41bab6c1004106102520022005280200360200200120012903a0073703b806200141b8066a200141e0046a4104102520012802bc06210302400240024020012802b8062206200228020022144188f0c100410041001004417f470d00201242003703002013420037030020054200370300200142003703a00720030d010c020b201742003703002018420037030020194200370300200142003703c00320062014200141c0036a4120410010042214417f460d092014411f4d0d09201220172903003703002013201829030037030020052019290300370300200120012903c0033703a007201a20122903002204370300201b2013290300220a370300201c2005290300220c3703002002200c370300201d200a370300201e2004370300200120012903a00722043703b806200120043703a003201f201e2903003703002020201d29030037030020072002290300370300200120012903b8063703e004200141e0036a41186a2219201f290300370300200141e0036a41106a2214202029030037030020162007290300370300200120012903e0043703e003201f2019290300220437030020202014290300220a37030020072016290300220c3703002005200c3703002013200a37030020122004370300200120012903e00322043703e004200120043703a0072003450d010b200610010b200141a0076a20014180046a412010fa02450d01200141003602b806200141b8066a10c501410610002205450d0c200142063702bc06200120053602b806200141b8066a41bab6c1004106102520072002280200360200200120012903b8063703e004200141e0046a41b7b6c1004103102520012802e404210520012802e0042203200728020010c401210602402005450d00200310010b200620084d0d01200120083602e003410610002205450d11200142063702bc06200120053602b806200141b8066a41bab6c1004106102520072002280200360200200120012903b8063703e004200141e0046a200141e0036a4104102520012802e404210220012802e0042205200728020020014180046a10c6012002450d0120051001200941206a21092008200f6a2108201141606a22110d020c030b20014180046a41186a200141e0046a41186a29030037030020014180046a41106a200141e0046a41106a29030037030020014180046a41086a200141e0046a41086a290300370300200120012903e004370380042015450d00200610010b200941206a21092008200f6a2108201141606a22110d000b0b200d450d00200e450d00201010010b200141c0036a41086a22024200370300200142003703c00341a285c1004116200141c0036a100220014190036a41086a2002290300370300200120012903c003370390030240024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0820012903a00722044200510d0f4200212520002004824200520d180c010b42002125200042e807824200520d170b41082119200141c0036a41086a22022025370300200120253703c00341b885c1004115200141c0036a100220014190036a41086a2002290300370300200120012903c003370390030240024002400240024020014190036a41104188f0c100410041001004417f460d00200142103702bc06200120014190036a3602b806200141a0076a200141b8066a103720012802a0072219450d1420012902a4072226422088a722140d010c020b420021264200422088a72214450d010b2019201441f8006c6a2108200141a0076a2019280250109102201941f8006a2102024002400240024020012802b0072205450d00200141f0026a20012903a007200141a0076a41086a290300200141b8076a350200420010fc02200141f0026a41086a290300210420012903f002210c024020012802b407450d00200510010b4100210620022008470d010c020b4200210c420021044100210620022008460d010b200141b0076a2109200141b8076a2112200141b4076a211341012107201921030340200141a0076a200241d0006a2802001091020240024020092802002205450d00200141e0026a20012903a007200141a0076a41086a2903002012350200420010fc02200141e0026a41086a290300210a20012903e002210b2013280200450d01200510010c010b4200210b4200210a0b2004200a200c200b562004200a562004200a511b22051b2104200c200b20051b210c2006200720051b21062003200220051b2103200741016a2107200241f8006a22022008470d000b2003450d010b200620144f0d1520192014417f6a220741f8006c6a220541c0006a290300210b200541c8006a2903002127200541d0006a2903002128200541d8006a2903002129200541206a290300212a200541286a290300212b200541306a290300212c200541386a290300212d2005290300212e2005290308212f200529031021302019200641f8006c6a220241186a22062900002131200541f0006a2903002104200541e8006a290300210a200541e0006a290300210c2006200541186a2903003700002002290010213220022030370010200229000821302002202f3700082002290000212f2002202e370000200241386a2205290000212e2005202d370000200241306a2205290000212d2005202c370000200241286a2205290000212c2005202b370000200241206a2205290000212b2005202a370000200241d8006a2029370000200241d0006a2205280000210820052028370000200241c8006a2205290000212820052027370000200241c0006a220529000021272005200b370000200241e0006a200c370000200241e8006a200a370000200141a8076a200a370300200241f0006a2004370000200141b0076a20043703002001200c3703a007200141b8066a41c8006a2028370300200141b8066a41c0006a2027370300200141b8066a41386a202e370300200141b8066a41306a202d370300200141b8066a41286a202c370300200141b8066a41206a202b370300200141b8066a41186a2031370300200120323703c806200120303703c0062001202f3703b8062001202642ffffffff0f832007ad422086843702a407200120193602a007200141153602e404200141b885c1003602e004200141a0076a200141e0046a101d2026a7210602402007450d00201441f8006c41887f6a210520192102034020021028200241f8006a2102200541887f6a22050d000b0b02402006450d00201910010b411310002202450d16200142133702a407200120023602a007200141a0076a41cd85c1004113102520012802a0072103024020012802a407220720012802a80722056b41034b0d00200541046a22022005490d2e20074101742206200220022006491b22064100480d2e2007450d03200610002202450d182002200320062007200720064b1b10f8021a200310010c040b20032102200721060c030b2014450d00201441f8006c210520192102034020021028200241f8006a2102200541887f6a22050d000b0b2026a7450d18201910010c180b200610002202450d140b200220056a2008360000200141c0036a41086a22074200370300200142003703c0032002200541046a2209200141c0036a100220014190036a41086a2007290300370300200120012903c0033703900341002107024020014190036a41104188f0c100410041001004417f460d00200120014190036a3602e004200141103602e404200142003703a807200142003703a0072001410020014190036a4110200141a0076a41104100100422052005417f461b2205411020054110491b3602e8042005410f4d0d11200141a0076a41086a2205290300210420012903a007210a200141a0076a200141e0046a103620012802a0072207450d112005280200210320012802a4072112200141c0036a41086a22054200370300200142003703c00320022009200141c0036a1002200141e0036a41086a2005290300370300200120012903c0033703e003200141e0036a411010082006450d160c150b20060d140c150b200141a0036a41186a200141a0076a41186a290000370300200141a0036a41106a200141a0076a41106a290000370300200141a0036a41086a200141a0076a41086a290000370300200120012900a0073703a00341eac4c10041331042000b411241011019000b200141a0036a41186a200141a0076a41186a290000370300200141a0036a41106a200141a0076a41106a290000370300200141a0036a41086a200141a0076a41086a290000370300200120012900a0073703a00341eac4c10041331042000b410641011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b410641011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b410641011019000b41c4d6c200104f000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41dcd6c20020062014104e000b411341011019000b200641011019000b200210010b0240024002402007450d0002402003450d00200341057421052007210203402002200a200410e102200241206a2102200541606a22050d000b0b200141c8076a2004370300200141c0076a200a370300200141b8076a2003360200200141b4076a2012360200200141a0076a41106a2007360200200141ac076a2008360200200141a0076a41086a41003a0000200141043a00a007200141a0076a10b401200141c0036a41086a22024200370300200142003703c00341e085c1004116200141c0036a100220014190036a41086a2002290300370300200120012903c0033703900320014190036a41104188f0c100410041001004417f460d01200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0420012903a007210a0c020b200141b8066a10a0010c020b42e807210a0b200141a0076a200141b8066a41d00010f8021a42002104200141c0036a41086a22024200370300200142003703c00341f685c1004115200141c0036a100220014190036a41086a2002290300370300200120012903c00337039003024020014190036a41104188f0c100410041001004417f460d00200142003703e00420014190036a4110200141e0046a41084100100441016a41084d0d0320012903e00421040b200141e0046a200a20007c200141a0076a4100200410920220012802e0044101470d0020012802e404200141e0046a41086a2802001006200141e0046a211a200141a0036a212020014180046a2116200141c0036a211e200141e0036a21180c120b200120003703a003200141c0036a41086a22022025370300200120253703c003418b86c1004113200141c0036a100220014190036a41086a2002290300370300200120012903c003370390034100210502400240024020014190036a41104188f0c100410041001004417f460d00200141003602a00720014190036a4110200141a0076a41044100100441016a41044d0d0120012802a00721050b200141c0036a41086a22024200370300200142003703c003419e86c1004119200141c0036a100220014190036a41086a2002290300370300200120012903c0033703900341002106024020014190036a41104188f0c100410041001004417f460d00200141003602a00720014190036a4110200141a0076a41044100100441016a41044d0d0220012802a00721060b200141003a00ec03200120053602e003200120063602e4032001200141a0036a3602e80302400240200520064f0d002001200541016a22023602e003200141a8076a210302400340200141a0076a200510930220032802002207410d470d01200220064f0d022001200241016a22073602e00320022105200721020c000b0b20012903a0072104200141b8066a200141a0076a410c6a41dc0010f8021a200141b0076a22022007360200200120043703a807200120053602a007200141b4076a200141b8066a41dc0010f80221050240200420012903a003520d0020014180046a41086a2202200141a0076a41086a290300370300200120012903a00737038004200141e0046a200541dc0010f8021a200141b8066a41086a2205200229030037030020012001290380043703b806200141a0076a200141e0046a41dc0010f8021a41f00010002233450d07203320012903b80637030020332007360210203341086a2005290300370300203341146a200141a0076a41dc0010f8021a200141e8056a41086a200141e0036a41086a290300370300200120012903e0033703e80520012d00f4050d0920012802e805220220012802ec054f0d092001200241016a3602e805200141a8076a21050340200141a0076a200210930220052802002207410d470d0320012802e805220220012802ec054f0d0a2001200241016a3602e8050c000b0b200141e0036a410c6a41013a0000200210280b410021344108213341082116410021020c080b20012903a0072104200141b8066a200141a0076a410c6a41dc0010f8021a200141b0076a22052007360200200120043703a807200120023602a007200141b4076a200141b8066a41dc0010f802210202400240200420012802f005290300520d0020014180046a41086a200141a0076a41086a290300370300200120012903a00737038004200141e0046a200241dc0010f8021a41002106410d21032007410d470d010c080b41012106200141e8056a410c6a41013a000020051028410d2107410d2103410d410d460d070b200141a0076a41106a2119200141a0076a41146a2114200141ac076a211f203321122033211641012105410121020340200141b8066a41086a220820014180046a41086a221329030037030020012001290380043703b806200141a0076a200141e0046a41dc0010f8021a024002400240024020022005470d00200541016a22092005490d1920054101742220200920092020491b2234ad42f0007e2204422088a70d192004a722094100480d192005450d01200910002233450d0a203320122009200541f0006c2205200520094b1b10f8021a201210010c020b200521340c020b200910002233450d080b20332112203321160b2016200241f0006c6a220520012903b806370300200541086a2008290300370300200541106a2007360200200541146a200141a0076a41dc0010f8021a200241016a2102200641ff01710d0820012802e805220620012802ec0522094f0d082001200641016a22053602e80502400340200141a0076a2006109302200141a0076a41086a220828020022072003470d01200520094f0d0a2001200541016a22073602e80520052106200721050c000b0b20012903a0072104200141b8066a201f41dc0010f8021a2019200736020020082004370300200120063602a0072014200141b8066a41dc0010f802210502402004200141e8056a41086a280200290300520d0020132008290300370300200120012903a00737038004200141e0046a200541dc0010f8021a41002106203421050c010b0b200141f4056a41013a00002019102841f000211b2016200241f0006c22026a210f20020d080c090b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41f00041081019000b200941081019000b4101213441f000211b20332216410141f0006c22026a210f20020d010c020b41f000211b2016200241f0006c22026a210f2002450d010b200141a0076a41086a2121200141e0046a41086a211a200141a0076a4104722105200141e0046a410c6a211c200141c0056a210d200141e0046a41d8006a2110200141a9076a210e0340201641106a28020021022016290208210420162802002109200141a0076a201641146a41dc0010f8021a2016201b6a21162002410d460d0120014180046a200141a0076a41dc0010f8021a201a2002360200200120043703e004201c20014180046a41dc0010f8021a200120093602c805200141b8066a200910950220012802b8062112024002400240200141b8066a41086a22062802002202450d00200241057421034200210a2012210242002104420021264200212842002125420021270340200141d0026a200210b001200141d0026a41086a290300210b20012903d002210c20022900002129200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a29000037000020052029370000200120093602a007200141c0026a200c200b200141a0076a1099022207411874411875220841077620077341016aad423886423887420010fc02200b20047c200c200a7c220a200c54ad7c21044200200141c0026a41086a290300220c200841004822071b20287c420020012903c002220b20071b222820267c2226202854ad7c2128200c420020071b20277c200b420020071b220c20257c2225200c54ad7c2127200241206a2102200341606a22030d000b20012802bc06450d020c010b420021254200212742002126420021284200210a4200210420012802bc06450d010b201210010b4200210b200141c0036a41086a22024200370300200142003703c00341d9f0c1004116200141c0036a1002200141e0036a41086a22082002290300370300200120012903c0033703e003024002400240024002400240200141e0036a41104188f0c100410041001004417f460d00200142003703a807200142003703a007200141e0036a4110200141a0076a4110410010042207417f460d022007410f4d0d022021290300210c20012903a007210b0c010b4200210c0b200d2d00002112024002400240200a4202882004423e868422292004420288222a84500d002029200a85202a20048584500d004100210702400340200141b0026a200a2004200741046a41fe007110ff02200741026a210720012903b0022229200141b0026a41086a290300222a84500d012029200a85202a2004858450450d000b0b200141a0026a200a2004200741fe007110ff0220012903a002200141a0026a41086a2903008421294200212a2007450d012029420052ad2129034020014180026a200a200441002007417e6a2203200320074b1b220741ff007110ff0220014190026a2029420186222c420184222b202a4201862029423f8884222a202b202a10fc02202c202b2001290390022001290380025620014190026a41086a290300222920014180026a41086a290300222d562029202d511b1b212920070d000c030b0b4200212a200a200484420052ad21290c010b2029420052ad21290b02400240200b420288200c423e86842204200c420288220a84500d002004200b85200a200c8584500d004100210702400340200141f0016a200b200c200741046a41fe007110ff02200741026a210720012903f0012204200141f0016a41086a290300220a84500d012004200b85200a200c858450450d000b0b200141e0016a200b200c200741fe007110ff0220012903e001200141e0016a41086a2903008421044200210a2007450d012004420052ad21040340200141c0016a200b200c41002007417e6a2203200320074b1b220741ff007110ff02200141d0016a2004420186222c420184222b200a4201862004423f8884220a202b200a10fc02202c202b20012903d00120012903c00156200141d0016a41086a2903002204200141c0016a41086a290300222d562004202d511b1b210420070d000b2029202a84500d040c030b4200210a200b200c84420052ad21042029202a8450450d020c030b2004420052ad21042029202a8450450d010c020b41eac4c10041331042000b024020124102460d00024020124101470d000340202a212a2029212b2004200a844200510d0c200141a0016a20252027202b202a10fb02200141b0016a202620282004200a10fb024101210720012903b001222920012903a001222c54200141b0016a41086a290300220c200141a0016a41086a290300220b54200c200b5122031b0d04202c202954200b200c5420031b0d0320014190016a2029200c2004200a10fc0220014180016a202c200b202b202a10fc022025200129038001220c7d220b202720014180016a41086a2903007d2025200c54ad7d220c84500d03202820014190016a41086a2903007d212c20262001290390012225542103202620257d212920042125200a2127200b2104200c210a202b2126202a21282029202c2003ad7d222a8450450d000c040b0b0340200141f0006a202620282029202a10fb022004220b200a222b844200510d0a200141f0006a41086a29030021042001290370210a200141e0006a20252027200b202b10fb0241012107200a2001290360222c542004200141e0006a41086a290300220c542004200c5122031b0d03202c200a54200c20045420031b0d02200141d0006a200a20042029202a10fc02200141c0006a202c200c200b202b10fc022025200129034022047d220a2027200141c0006a41086a2903007d2025200454ad7d220c84500d022028200141d0006a41086a2903007d212c202620012903502204542103202620047d210420292125202a2127200a2129200c212a200b2126202b21282004202c2003ad7d220a8450450d000c030b0b2025202656202720285620272028511b21070c010b410021070b200120073a00cf054200210b20024200370300200142003703c00341f685c1004115200141c0036a100220014190036a41086a22222002290300370300200120012903c00337039003024020014190036a41104188f0c100410041001004417f460d00200142003703a00720014190036a4110200141a0076a41084100100441016a41084d0d0920012903a007210b20012802c80521090b200141a0076a200910950220012802a4072107200141d0056a410c6a222320012802a0072203202128020022094105746a360200200141d0056a41086a22202003360200200141d0056a41146a2217200141cf056a360200200141d0056a41106a2224200141c8056a360200200120073602d405200120033602d00502402009450d002020200341206a360200200141b8066a41186a2213200341186a2900002204370300200141b8066a41106a2219200341106a290000220a3703002006200341086a290000220c370300200141e8056a41086a2207200c370300200141e8056a41106a2214200a370300200141e8056a41186a221f20043703002001200329000022043703b806200120043703e805200520012903b806370000200541086a221d2006290300370000200541106a221e2019290300370000200541186a22152013290300370000200120012802c8053602a007200141a0076a10990221030340200141c0036a41186a2209201f290300370300200141c0036a41106a2212201429030037030020022007290300370300200120012903e8053703c003200141e0036a41186a22112009290300370300200141e0036a41106a2209201229030037030020082002290300370300200120012903c0033703e0030240024002400240024002402003411874411875221241004820172802002d00004573450d00200141a0036a41186a22182011290300370300200141a0036a41106a22112009290300370300200141a0036a41086a22092008290300370300200120012903e0033703a003200141a0076a41186a2018290300370300200141a0076a41106a201129030037030020212009290300370300200120012903a0033703a007411110002209450d03200142113702bc06200120093602b806200141b8066a41f384c1004111102520072006280200360200200120012903b8063703e805200141a0076a200141e8056a101e2007280200211120012802ec05211820012802e805210920024200370300200142003703c00320092011200141c0036a100220222002290300370300200120012903c0033703900320014190036a41104188f0c100410041001004417f460d01200142003703b80620014190036a4110200141b8066a41084100100441016a41084d0d0220012903b806210a20024200370300200142003703c00320092011200141c0036a100220082002290300370300200120012903c0033703e003200141e0036a411010084201210c2018450d050c040b20012802d805220320012802dc05460d062020200341206a3602002013200341186a29000022043703002019200341106a290000220a3703002006200341086a290000220c3703002007200c3703002014200a370300201f20043703002001200329000022043703b806200120043703e805200520012903b806370000201d2006290300370000201e201929030037000020152013290300370000200120012802e0052802003602a007200141a0076a10990221030c050b4200210c20180d020c030b41eac4c10041331042000b411141011019000b200910010b411110002209450d04200142113702bc06200120093602b806200141b8066a41f384c1004111102520072006280200360200200120012903b8063703e805200141a0076a200141e8056a101e2007280200211120012802ec05211820012802e80521092001200b201241077620037341016aad4238864238877e20007c2204200a4200200ca71b220a200a2004541b3703b80620024200370300200142003703c00320092011200141c0036a100220082002290300370300200120012903c0033703e003200141e0036a4110200141b8066a4108100302402018450d00200910010b202028020022032023280200460d012020200341206a3602002013200341186a29000022043703002019200341106a290000220a3703002006200341086a290000220c3703002007200c3703002014200a370300201f20043703002001200329000022043703b806200120043703e805200520012903b806370000201d2006290300370000201e201929030037000020152013290300370000200120242802002802003602a007200141a0076a10990221030c000b0b024020012802d405450d0020012802d00510010b20012802c80510960220012802c805210702400240024002400240024020012d00cf05450d00200141a0076a410c6a22062007360200202141023a0000200141043a00a007200141a0076a10b40120102903002204500d01200141b8066a200141e0046a41e80010f8021a200141e0036a200420007c2204109402200141a0076a200141b8066a41e80010f8021a200141e8056a202141d00010f8021a20012802c80521062008280200220720012802e403470d04200741016a22032007490d1220074101742209200320032009491b2212ad42d8007e220a422088a70d12200aa722034100480d122007450d0220012802e0032113200310002209450d0a200920132003200741d8006c2219201920034b1b10f8021a201310010c030b200141a0076a410c6a2007360200202141033a0000200141043a00a007200141a0076a10b401200120012802c80541016a3602a00720024200370300200142003703c003418b86c1004113200141c0036a100220082002290300370300200120012903c0033703e003200141e0036a4110200141a0076a41041003201a10a0012016200f470d050c040b20012802c8052107200141a0076a201a41d00010f8021a200141003b01b806200141386a200141a0076a200141b8066a10cc022001280238210320062007360200200e2003453a0000202141053a0000200141043a00a007200141a0076a10b401200120012802c80541016a3602a00720024200370300200142003703c003418b86c1004113200141c0036a100220082002290300370300200120012903c0033703e003200141e0036a4110200141a0076a410410032016200f470d040c030b200310002209450d070b200120123602e403200120093602e0030b20012802e003200741d8006c6a200141e8056a41d00010f80221032008200741016a360200200341d0006a2006360200411710002207450d04200142173702a407200120073602a007200141a0076a41b786c1004117102520012802a007210702400240024020012802a4072203202128020022066b41084f0d00200641086a22092006490d1020034101742212200920092012491b22094100480d102003450d01200910002212450d092012200720092003200320094b1b10f802210320071001200321070c020b200321090c010b200910002207450d070b200720066a20043700002001200641086a3602a407200120073602a007200141e0036a200141a0076a101a02402009450d00200710010b20012802e0032103024020082802002207450d00200741d8006c210620032107034002402007280200410d460d00200710280b200741d8006a2107200641a87f6a22060d000b0b024020012802e403450d00200310010b200120012802c80541016a3602a00720024200370300200142003703c003418b86c1004113200141c0036a100220082002290300370300200120012903c0033703e003200141e0036a4110200141a0076a410410032016200f470d010b0b200f21160b02402016200f460d00200141a0076a41106a2105200141a0076a41146a21030340200141e0046a41086a2207201641086a290300370300200120162903003703e004201641106a2802002102200141a0076a201641146a41dc0010f8021a2002410d460d0120014180046a41086a22062007290300370300200120012903e00437038004200141b8066a200141a0076a41dc0010f8021a20052002360200200141a0076a41086a200629030037030020012001290380043703a0072003200141b8066a41dc0010f8021a20051028201641f0006a2216200f470d000b0b02402034450d00203310010b200141a0076a200010940220012802a4072102200120012802a007220520012802a807220641d8006c6a22073602f405200120053602f005200120023602ec05200120053602e8050240024002402006450d00200141e8056a41086a2203200541d8006a220236020020052802002106200141a0076a200541046a41cc0010f8021a2006410e460d01200541d0006a2102200141a0076a4104722108200141a9076a2109034020022802002102200141e0046a200141a0076a41cc0010f8021a200141a0076a200141e0046a41cc0010f8021a024002402006410d470d0020012802f005220520012802f4052207460d052003200541d8006a220236020020052802002106200141a0076a200541046a41cc0010f8021a2006410e470d010c040b20014180046a200141a0076a41cc0010f8021a200120063602a007200820014180046a41cc0010f8021a200141003b01b806200141306a200141a0076a200141b8066a10cc0220012802302105200141a0076a410c6a200236020020092005453a0000200141a0076a41086a41053a0000200141043a00a007200141a0076a10b40120032802002205200141e8056a410c6a2802002207460d042003200541d8006a220236020020052802002106200141a0076a200541046a41cc0010f8021a2006410e460d030b200541d0006a21020c000b0b20052107200521020b20022007460d090c080b2005220220052207470d070c080b411141011019000b411741011019000b200341081019000b200941011019000b41ecd6c200104f000b41ecd6c200104f000b41eac4c10041331042000b200141a0076a4104722108200141f0056a2103200141f4056a210903402003200241d8006a220636020020022802002105200141a0076a200241046a41d40010f8021a2005410e460d01200141b8066a200141a0076a41d40010f8021a200120053602a0072008200141b8066a41d40010f8021a2006210202402005410d460d00200141a0076a102820092802002107200328020021020b20022007470d000b0b024020012802ec05450d0020012802e80510010b200141a0036a2120200141c0036a211e200141e0036a211820014180046a2116200141e0046a211a0b200010e202200141a0076a410472211b200141a0076a4105722111200141a0076a41206a2105200141e0046a4104722122200141e0046a410c6a210f200141d0076a2123200141cc076a212402400240024002400240024002400240024002400240024002400340200141a0076a109f0220012802a0072206410820061b2102200141a0076a41086a210920012802a4072103410d21070240024002400240024002400240024002402006450d00410d210720092802002208450d0020022903002104201841186a2212200241206a290000370000201841106a2213200241186a290000370000201841086a2219200241106a29000037000020182002290008370000410d210720042000520d002008417f6a2214ad42287e2204422088a70d022004a7221f417f4c0d0202400240201f450d00201f1000221d0d010c060b4108211d0b2001200241286a3602a00720012002200841286c6a3602a407200141286a200141a0076a10c902200128022821150240024002402014200128022c22074f0d0020144101742208200720072008491b2208ad42287e2204422088a70d1a2004a722214100480d1a2014450d01202110002217450d082017201d2021201f201f20214b1b10f8021a201d10010c020b201d2117201421080c010b202110002217450d060b20172015200741286c10f802211420092007360200200120083602a407200120143602a007200141a0076a10a50202402008450d00201410010b200141e8056a41186a2012290000370300200141e8056a41106a2013290000370300200141e8056a41086a2019290000370300200120182900003703e805411810002207450d03200142183702a407200120073602a007200141a0076a4188a3c10041181025200141b8066a41086a22072009280200360200200120012903a0073703b806200141e8056a200141b8066a101e2007280200211420012802bc06211720012802b806210820094200370300200142003703a00720082014200141a0076a1002200141c0036a41086a221f2009290300370300200120012903a0073703c003200141c0036a41104188f0c100410041001004417f460d01200142103702d4052001200141c0036a3602d005200141a0076a200141d0056a103820012802a0072207410d460d06201a201b41cc0010f802211d201f4200370300200142003703c00320082014200141c0036a100220014190036a41086a201f290300370300200120012903c0033703900320014190036a41101008200141b8066a201d41cc0010f8021a2016200141b8066a41cc0010f8021a02402017450d00200810010b20202018290000370000202041186a2012290000370000202041106a2013290000370000202041086a20192900003700000b2006450d070c060b200141b8066a201a41cc0010f8021a02402017450d00200810010b410d210720060d050c060b102c000b411841011019000b201f41081019000b202141081019000b41eac4c10041331042000b2003450d00200210010b2007410d460d01200120073602e0042022201641cc0010f8021a200141e8056a41186a2219202041186a290000370300200141e8056a41106a2214202041106a290000370300200141e8056a41086a221f202041086a290000370300200120202900003703e805200141a0076a109e024100211220012802a0072217410820171b211d20012802a40721214100211302402009280200410020171b221541286c2206450d004100211341002112201d2102034020052002290000370000200141a0076a41186a2019290300370300200141a0076a41106a20142903003703002009201f290300370300200541086a200241086a290000370000200541106a200241106a290000370000200541186a200241186a290000370000200120012903e8053703a007411b10002207450d042001421b3702bc06200120073602b806200141b8066a419faec100411b1025200141e0036a41086a2207200141b8066a41086a280200360200200120012903b8063703e003200141a0076a200141e0036a10af0220012802e403210320012802e0032208200728020010a702210702402003450d00200810010b0240200741ff01714102460d00201320074101716a211320122007417f734101716a21120b200241286a2102200641586a22060d000b0b201220136a210202402017450d002021450d00201d10010b201520026b210202400240024020012802e0044105470d00200141e0046a41086a2d000041ff01714106470d00200f28020021072023200236020020242012360200200141a0076a41286a2013360200201120012903e805370000201141086a201f290300370000201141106a2014290300370000201141186a2019290300370000200141003a00a407200141063a00a007200141a0076a10b40120120d0120020d01200141a0076a410c6a2007360200200941043a0000200141043a00a007200141a0076a10b40120071096020c010b201e20012903e805370000201e41186a2019290300370000201e41106a2014290300370000201e41086a201f2903003700002023200236020020242012360200200141a0076a41286a2013360200201120012903e805370000201141086a201f290300370000201141106a2014290300370000201141186a2019290300370000200141013a00a407200141063a00a007200141a0076a10b4012013200220126a4b0d010b200141e0046a10a0010c010b411c10002207450d062001421c3702a407200120073602a007200141a0076a41a0a3c100411c1025200141b8066a41086a22072009280200360200200120012903a0073703b806200141e8056a200141b8066a101e2007280200210620012802bc06210320012802b806210720094200370300200142003703a00720072006200141a0076a1002200141c0036a41086a22062009290300370300200120012903a0073703c003200141c0036a4110100802402003450d00200710010b420021044200210a02402012450d0020094200370300200142003703a00741bca3c100411e200141a0076a100220062009290300370300200120012903a0073703c0030240200141c0036a41104188f0c100410041001004417f460d00200142003703a007200141c0036a4110200141a0076a41084100100441016a41084d0d0720012903a007210a0c010b4200210a0b200141b8066a200141e0046a41d00010f8021a20094200370300200142003703a00741f0f1c100410d200141a0076a100220062009290300370300200120012903a0073703c0030240200141c0036a41104188f0c100410041001004417f460d00200142003703a007200141c0036a4110200141a0076a41084100100441016a41084d0d0420012903a00721040b20094200370300200142003703a00741e085c1004116200141a0076a1002200141e0036a41086a22072009290300370300200120012903a0073703e00302400240200141e0036a41104188f0c100410041001004417f460d00200142003703a007200141e0036a4110200141a0076a41084100100441016a41084d0d0620012903a007210c0c010b42e807210c0b200141a0076a200141b8066a41d00010f8021a200141e0036a200c20047c200141a0076a4102410120022012721b200a10920220012802e0034101470d0020012802e4032202450d000b20072802002105419ac9c100410f10062002200510060b200141a0076a10c70120012802b0072211450d0b200141e0046a41086a2202200141a0076a41086a2207290300370300200141a0036a41086a2205200141a0076a411c6a280200360200200120012903a0073703e004200120012902b4073703a003200141b8066a41086a2002290300370300200141cc066a20012903a003370200200141b8066a411c6a2005280200360200200120113602c806200120012903e00422043703b806200141b8066a41106a21020240024020042000520d0020012903c006210a20014180046a2002102f2007200a370300200141a0076a41106a200129038004370300200141b8076a20014180046a41086a280200360200200141023a00a007200141a0076a10e002200a20047c2000510d010c0c0b20012903c00620047c2000520d0b0b200141e8056a2002102f200141083a00a0072001418b046a200141e8056a41086a2208280200360000200120012903e80537008304200141a0076a41086a220920014187046a29000037000020012001290080043700a107200141a0076a10b401200141cc066a28020021170240200141b8066a41186a28020041286c2202450d00201120026a212041002106201121050340200141a0076a41186a2202200541186a290300370300200141a0076a41106a2212200541106a2903003703002009200541086a290300370300200120052903003703a007200541206a2903002104200120063602e003410e10002207450d072001420e37028404200120073602800420014180046a41d79bc100410e1025200820014180046a41086a28020036020020012001290380043703e805200141e8056a200141e0036a410410252008280200211320012802ec05211920012802e8052103412010002207450d08200720012903a007370000200741186a22142002290300370000200741106a221f2012290300370000200741086a2212200929030037000041c00010002202450d0920022007290000370000200241186a2014290000370000200241106a201f290000370000200241086a20122900003700002007100120022004370020200320132002412810032002100102402019450d00200310010b200641016a2106200541286a22052020470d000b2017450d0a0c090b4100210620170d080c090b411b41011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411c41011019000b410e41011019000b412041011019000b41c00041011019000b201110010b02400240410e10002202450d002001420e3702a407200120023602a007200141a0076a41d79bc100410e102520014188046a220220012802a807360200200120012903a0073703800420014180046a41b7b6c1004103102520012802840421052001280280042207200228020010c401211202402005450d00200710010b024002400240201220064d0d00200621020340410e10002205450d022001420e3702a407200120053602a007200141a0076a41d79bc100410e102520014180046a41086a2205200141a0076a41086a2209280200360200200120012903a0073703800420014180046a41b7b6c1004103102520012802840421072001280280042208200528020010c401210302402007450d00200810010b0240200320024d0d00200120023602e805410e10002207450d042001420e3702a407200120073602a007200141a0076a41d79bc100410e102520052009280200360200200120012903a0073703800420014180046a200141e8056a4104102520012802840421072001280280042203200528020010082007450d00200310010b2012200241016a2202470d000b0b410e10002202450d032001420e3702a407200120023602a007200141a0076a41d79bc100410e102520014180046a41086a220220012802a807360200200120012903a0073703800420014180046a41b7b6c100410310252002280200210520012802840421072001280280042102200120063602a00720022005200141a0076a4104100302402007450d00200210010b200141e0036a41086a22024200370300200142003703e00341e59bc100411d200141e0036a1002200141c0036a41086a2002290300370300200120012903e0033703c003200141c0036a411010080c050b410e41011019000b410e41011019000b410e41011019000b410e41011019000b200141cc066a280200450d00201110010b200141e0036a41086a22024200370300200142003703e00341b9c2c0004114200141e0036a1002200141c0036a41086a2002290300370300200120012903e0033703c00302400240200141c0036a41104188f0c100410041001004417f460d00200142003703a007200141c0036a4110200141a0076a41084100100441016a41084d0d0a20012903a00722044200510d094200212520002004824200520d0e0c010b4200212520004201824200520d0d0b200141e0036a41086a22022025370300200120253703e00341cdc2c000410c200141e0036a1002200141c0036a41086a22052002290300370300200120012903e0033703c00302400240200141c0036a41104188f0c100410041001004417f460d00200142003703a807200142003703a007200141c0036a4110200141a0076a4110410010042207417f460d082007410f4d0d08200141a8076a290300210420012903a007210c0c010b4200210c420021040b200141b8076a2004370300200141a0076a41106a200c370300200141a0076a41086a41013a0000200141093a00a007200141a0076a10b40120024200370300200142003703e00341d9c2c0004112200141e0036a100220052002290300370300200120012903e0033703c003200141c0036a41104188f0c100410041001004417f460d09200142103702bc062001200141c0036a3602b806200141a0076a200141b8066a103b20012802a0072212450d05200120012902a407220a3702ec05200120123602e80541002103200141003602f005200aa72120200a422088a72205450d0a200141a0076a41096a2111200141a0056a211f20014180056a211e200141b8066a41086a2109200141e0046a41186a2115200141d8076a2121200141d0076a2116200141cc076a2122410021134100210341002114410021020340024002400240024002402014450d0020024102742107201220134102746a21190340200220054f0d03200141b8066a201220076a2206280200220810b90120012903b8064201520d02200141e0046a200941e00010f8021a200c20012903e004220b542004200141e0046a41086a290300220a542004200a511b450d05201320026a220320054f0d04201920076a2006280200360200200741046a2107410121032005200241016a2202470d000c120b0b201220024102746a21070340200220054f0d02200141b8066a2007280200220810b90120012903b8064201520d01200141e0046a200941e00010f8021a200c20012903e004220b5a2004200141e0046a41086a290300220a5a2004200a511b0d04200741046a2107410121032005200241016a2202470d000c100b0b2013417f6a2113201441016a2114200241016a22022005470d030c0f0b41b08dc20020022005104e000b41c08dc20020032005104e000b200241016a2102411210002207450d02200142123702a407200120073602a007200141a0076a4197e5c0004112102520012802a007211d02400240024020012802a4072206200141a0076a41086a221728020022076b41034b0d00200741046a22192007490d0420064101742218201920192018491b22184100480d042006450d01201810002219450d062019201d20182006200620184b1b10f8021a201d10010c020b201d2119200621180c010b201810002219450d040b201920076a2008360000200141e0036a41086a22064200370300200142003703e0032019200741046a200141e0036a1002200141c0036a41086a221d2006290300370300200120012903e0033703c003200141c0036a4110100802402018450d00201910010b201e200141e0046a41106a290300201529030010e102411410002207450d04200142143702a407200120073602a007200141a0076a41eeefc1004114102520014180046a41086a22072017280200360200200120012903a00737038004201f20014180046a101e20072802002119200128028404211820012802800421074200212620064200370300200142003703e00320072019200141e0036a1002201d2006290300370300200120012903e0033703c003024002400240200141c0036a41104188f0c100410041001004417f460d00200142003703a807200142003703a007200141c0036a4110200141a0076a4110410010042206417f460d082006410f4d0d082017290300212720012903a00721262004200a7d2104200c200b54ad21282018450d020c010b420021272004200a7d2104200c200b54ad21282018450d010b200710010b200420287d2104200c200b7d210c201f2026200b7c22282027200a7c2028202654ad7c10c2021a2021200a3703002016200b370300201741023a0000202220083602002011201f290000370000201141086a201f41086a290000370000201141106a201f41106a290000370000201141186a201f41186a290000370000200141093a00a007200141a0076a10b4012013417f6a2113201441016a211420022005470d000c0c0b0b1018000b411241011019000b201841011019000b411441011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41d8acc200104f000b41eac4c10041331042000b41002105200141003602f005200142043703e8054104211241002120410021030b410021140b200141f0056a200520146b360200200141e8056a10a00202402020450d00201210010b0240200341ff01710d00200141e0036a41086a22024200370300200142003703e00341ebc2c000410d200141e0036a1002200141c0036a41086a2002290300370300200120012903e0033703c00302400240200141c0036a41104188f0c100410041001004417f460d00200141003602a007200141c0036a4110200141a0076a41044100100441016a41044d0d0420013502a007210a0c010b4200210a0b200141186a200c2004200a420010fc02200141086a2001290318200141186a41086a29030042c0843d420010fb02200141a0076a41086a41033a0000200141b8076a2004200141086a41086a290300220a2001290308220b200c56200a200456200a2004511b22021b2226370300200141a0076a41106a200c200b20021b220a370300200141093a00a007200420267d200c200a54ad7d2104200c200a7d210c200141a0076a10b4010b200141b8076a2004370300200141a0076a41106a200c370300200141a0076a41086a41043a0000200141093a00a007200141a0076a10b401200120043703a8072001200c3703a007200141e0036a41086a22024200370300200142003703e00341cdc2c000410c200141e0036a1002200141c0036a41086a2002290300370300200120012903e0033703c003200141c0036a4110200141a0076a411010030b200141e0036a41086a22022025370300200120253703e00341d0b0c0004111200141e0036a1002200141c0036a41086a2002290300370300200120012903e0033703c003200141c0036a4110100820014190086a24000f0b41eac4c10041331042000bcd1405037f017e067f037e047f230041d0016b22012400200141b0016a41086a22024200370300200142003703b00141a3f2c1004111200141b0016a100220014190016a41086a22032002290300370300200120012903b0013703900120014190016a4110100820024200370300200142003703b00141c8f5c1004115200141b0016a100220032002290300370300200120012903b0013703900120014190016a41101008200141f0f1c100410d10a602200129030821042001280200210520024200370300200142003703b00141fdf1c1004111200141b0016a100220032002290300370300200120012903b00137039001024002400240024002400240024020014190016a41104188f0c100410041001004417f460d00200141c8016a4200370300200141b0016a41106a420037030020024200370300200142003703b00120014190016a4110200141b0016a4120410010042202417f460d022002411f4d0d02200141f0006a41186a2206200141b0016a41186a2203290300370300200141f0006a41106a2207200141b0016a41106a2208290300370300200141f0006a41086a2209200141b0016a41086a2202290300370300200120012903b00137037020024200370300200142003703b00141fdf1c1004111200141b0016a100220014190016a41086a220a2002290300370300200120012903b0013703900120014190016a41101008200320062903003703002008200729030037030020022009290300370300200120012903703703b00120014190016a41186a2003290300220b37030020014190016a41106a2008290300220c370300200a2002290300220d370300200141106a41086a200d370300200141106a41106a200c370300200141106a41186a200b370300200120012903b001220b370390012001200b3703100c010b200141b0016a41186a200141f0006a41186a290300370300200141b0016a41106a200141f0006a41106a2903003703002002200141f0006a41086a290300370300200120012903703703b001200141106a41186a4200370300200141106a41106a4200370300200141106a41086a4200370300200142003703100b4108210720014190016a41086a2202420037030020014200370390014190f3c100410d20014190016a1002200141b0016a41086a200229030037030020012001290390013703b0014100210202400240200141b0016a41104188f0c100410041001004417f460d00200142103702742001200141b0016a36027020014190016a200141f0006a10ea022001280290012207450d05200129029401210b20014190016a41086a2202420037030020014200370390014190f3c100410d20014190016a1002200141b0016a41086a200229030037030020012001290390013703b001200141b0016a41101008200b422088a72102200ba721090c010b410021090b200141b0016a41086a22034200370300200142003703b001418ef2c1004115200141b0016a100220014190016a41086a2003290300370300200120012903b001370390010240024020014190016a41104188f0c100410041001004417f460d00200141c8016a4200370300200141b0016a41106a420037030020034200370300200142003703b00120014190016a4110200141b0016a4120410010042203417f460d032003411f4d0d03200141f0006a41186a220a200141b0016a41186a2208290300370300200141f0006a41106a220e200141b0016a41106a2206290300370300200141f0006a41086a220f200141b0016a41086a2203290300370300200120012903b00137037020034200370300200142003703b001418ef2c1004115200141b0016a100220014190016a41086a22102003290300370300200120012903b0013703900120014190016a411010082008200a2903003703002006200e2903003703002003200f290300370300200120012903703703b00120014190016a41186a2008290300220b37030020014190016a41106a2006290300220c37030020102003290300220d370300200141306a41086a200d370300200141306a41106a200c370300200141306a41186a200b370300200120012903b001220b370390012001200b3703300c010b200141b0016a41186a200141f0006a41186a290300370300200141b0016a41106a200141f0006a41106a2903003703002003200141f0006a41086a290300370300200120012903703703b001200141306a41186a4200370300200141306a41106a4200370300200141306a41086a4200370300200142003703300b200141f0006a41186a22034200370300200141f0006a41106a22084200370300200141f0006a41086a2206420037030020014200370370200141f0006a100a200141d0006a41186a2003290300370300200141d0006a41106a2008290300370300200141d0006a41086a200629030037030020012001290370370350200141b0016a41186a220a200141106a41186a290300370300200141b0016a41106a220e200141106a41106a290300370300200141b0016a41086a220f200141106a41086a290300370300200120012903103703b001200342003703002008420037030020064200370300200142003703700240200141b0016a41202004420020051b2204427f7c200141f0006a1016450d0020014190016a41186a2205200329030037030020014190016a41106a2210200829030037030020014190016a41086a2211200629030037030020012001290370370390012003200529030037030020082010290300370300200620112903003703002001200129039001370370200a2003290300370300200e2008290300370300200f2006290300370300200120012903703703b001024020022009470d00200241016a22032002490d0420024101742208200320032008491b2209ad42287e220b422088a70d04200ba722034100480d0402402002450d00200310002208450d07200820072003200241286c2206200620034b1b10f802210320071001200321070c010b200310002207450d060b2007200241286c6a220341003a0000200341196a200141c8016a290300370000200341116a200141c0016a290300370000200341096a200141b8016a290300370000200320012903b001370001200341216a200128009001360000200341256a20014194016a2f00003b0000200341276a20014196016a2d00003a0000200241016a21020b2000200129031037001420002004370300200020012903503700342000412c6a200141106a41186a290300370000200041246a200141106a41106a2903003700002000411c6a200141106a41086a2903003700002000413c6a200141d0006a41086a290300370000200041c4006a200141d0006a41106a290300370000200041cc006a200141d0006a41186a290300370000200041ec006a200141306a41186a290300370000200041e4006a200141306a41106a290300370000200041dc006a200141306a41086a29030037000020002001290330370054200041106a20023602002000410c6a200936020020002007360208200141d0016a24000f0b41eac4c10041331042000b41eac4c10041331042000b1018000b41eac4c10041331042000b200341081019000b8e0301027f23004180026b22022400024002402001450d00200220003602000c010b20024188f0c1003602000b2002200136020420024188016a200210a6010240200228029001450d00200241086a20024188016a41f80010f8021a20024188016a200241086a41f80010f8021a20022903880120024188016a41146a200241dc016a10e601024020024188016a41106a2802002200450d002002280290012101200041286c21000340024020012d00002203450d00024020034101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b024020024194016a280200450d0020024190016a28020010010b20024180026a240042010f0b2002411c6a4101360200200241146a41013602002002410136028401200241fcd5c20036028001200241e0c3c1003602102002410136020c200241e4d5c200360208200220024180016a360218200241086a41ecd5c2001071000baf0902087f027e230041206b22022400200241003602182002420137031041a09fc1004105200241106a1064410c200241106a106541b0e8c200210303402003280200200341046a280200200241106a1064200241086a200328020811010020022802082104200228020c2205200241106a10652003410c6a210302402005450d002005412c6c2106410021070340200420076a220541046a280200200541086a280200200241106a1064200541106a2802002108024002402005410c6a2802004101470d002008200541186a280200200241106a10630c010b2008200541146a280200200241106a10630b200541206a280200210802402005411c6a2802004101470d002008200541286a280200200241106a106320062007412c6a2207470d010c020b2008200541246a280200200241106a106320062007412c6a2207470d000b0b200341c0e9c200470d000b410f200241106a106541d8752105200241186a2108024002400240024002400340200541ecf3c2006a280200200541f0f3c2006a280200200241106a1064200541f4f3c2006a200241106a1067024002400240024002400240024002400240200541a0f4c2006a22042802004102470d00200228021420082802002207470d01200741016a22042007490d0b20074101742206200420042006491b22064100480d0b2007450d0320022802102103200610002204450d0d2004200320062007200720064b1b10f8021a200310010c040b200228021420082802002207470d01200741016a22062007490d0a20074101742203200620062003491b22034100480d0a2007450d0520022802102109200310002206450d0d2006200920032007200720034b1b10f8021a200910010c060b200228021021040c030b200228021021060c050b200610002204450d090b2002200636021420022004360210200828020021070b2008200741016a360200200420076a41003a0000200541d8006a22050d030c040b200310002206450d070b2002200336021420022006360210200828020021070b2008200741016a360200200620076a41013a00002004200241106a1069200541d8006a22050d000b0b41e3f5c1004104200241106a1064410d200241106a106541947d2105200241186a21060340200541d8f6c2006a280200200541dcf6c2006a280200200241106a1064200541e4f6c2006a280200200541e8f6c2006a280200200241106a1064024002400240024020022802142204200628020022076b41024f0d00200741026a22082007490d0520044101742207200820082007491b22074100480d052004450d0120022802102103200710002208450d062008200320072004200420074b1b10f8021a200310010c020b200228021021080c020b200710002208450d040b2002200736021420022008360210200628020021070b2006200741026a360200200820076a200541ecf6c2006a2f01003b00002005411c6a22050d000b200241186a28020021072002280214210820022802102105200241003602182002420137031020052007200241106a108e012002350218210a2002350210210b02402008450d00200510010b200241206a2400200a422086200b840f0b1018000b200741011019000b200641011019000b200341011019000bf306010a7f230041c0056b22022400024002402001450d00200220003602100c010b20024188f0c1003602100b20022001360214200241d8036a200241106a10a7010240024002400240024002400240024020022903c8044203510d00200241186a200241d8036a41d80110f8021a200241f0016a200241186a41d80110f8021a2002200241f0016a3602d803200241c8036a200241d8036a10e80120022802cc03210320022802c803210420022802d0032105200241086a10f00120022802082106200228020c2107411410002201450d01200242143702dc03200220013602d803200241d8036a419df3c1004114102520022802d803210102400240024020022802dc03220820022802e00322006b41044f0d00200041046a22092000490d052008410174220a20092009200a491b220a4100480d052008450d01200a1000220b450d06200b2001200a20082008200a4b1b10f802210820011001200821010c020b200041046a21092008210a0c010b200a10002201450d040b200120006a2007410020061b360000200241003602e003200242013703d80320042005200241d8036a108e0120022802dc03210820022802e003210620022802d8032100200241d8036a41086a22074200370300200242003703d80320012009200241d8036a1002200241b0056a41086a2007290300370300200220022903d8033703b005200241b0056a411020002006100302402008450d00200010010b0240200a450d00200110010b02402003450d00200410010b200241d8036a200241f0016a41d80110f8021a200241b0056a200241d8036a200510e90120022802b4052201200141004720022802b00541014622001b2108410110002101024002402000450d002001450d06200141013a0000410210002200450d07200020012d00003a00000c010b2001450d07200141003a0000410210002200450d08200020012d00003a00000b20011001200020083a0001200241c0056a24002000ad428080808020840f0b20024184026a4101360200200241fc016a41013602002002410136021c20024184d6c200360218200241e0c3c1003602f801200241013602f401200241e4d5c2003602f0012002200241186a36028002200241f0016a41ecd5c2001071000b411441011019000b1018000b200a41011019000b410141011019000b410241011019000b410141011019000b410241011019000b7f01037f230041106b220124004100210202400240024041bef1c10041104188f0c100410041001004417f460d002001410036020c4101210241bef1c10041102001410c6a41044100100441016a41044d0d02200128020c21030c010b0b2000200336020420002002360200200141106a24000f0b41eac4c10041331042000bf90c04037f017e0a7f017e230041d0016b2202240010ea01200241186a41086a220342003703002002420037031841f0f1c100410d200241186a100220024190016a41086a220420032903003703002002200229031837039001420021050240024002400240024020024190016a41104188f0c100410041001004417f460d002002420037031820024190016a4110200241186a41084100100441016a41084d0d01200229031821050b200510eb0120044200370300200242003703900141c8f5c100411520024190016a1002200241c0016a41086a200429030037030020022002290390013703c00102400240024002400240024002400240200241c0016a41104188f0c100410041001004417f460d00410021062002410036021841042107200241c0016a4110200241186a41044100100441016a41044d0d0a20022802182208450d012008ad420c7e2205422088a70d022005a722044100480d02200410002207450d0b200241186a41086a2109200721034100210a0340411410002204450d042002421437021c20022004360218200241186a419df3c100411410252002280218210b024002400240200228021c220c200928020022046b41034b0d00200441046a22062004490d06200c410174220d20062006200d491b220d4100480d06200c450d01200d10002206450d0b2006200b200d200c200c200d4b1b10f8021a200b10010c020b200b2106200c210d0c010b200d10002206450d090b200620046a200a360000200241c0016a41086a220b4200370300200242003703c0012006200441046a220e200241c0016a10022009200b290300370300200220022903c00137031802400240024002400240200241186a41104188f0c100410041001004417f460d00200242103702a4012002200241186a3602a001200241106a200241a0016a10352002280210450d0c20022802142204417f4c0d0a2004450d0120041000220c450d0f200c4100200410f7021a0c020b410021044101210c4100210b200a41016a210a200d0d020c030b4101210c0b200241a0016a41086a220f200f280200220f2004410020022802a00120022802a401200c2004200f1004220f200f417f461b220f200f20044b1b6a3602002004200f4b0d08200c450d09200b4200370300200242003703c0012006200e200241c0016a100220024190016a41086a200b290300370300200220022903c0013703900120024190016a411010082004ad22054220862005842205422088a7210b2005a72104200a41016a210a200d450d010b200610010b2003200c360200200341086a200b360200200341046a20043602002003410c6a21032008200a470d000b200821060c010b41002106410421070b200241086a200720072006410c6c6a102e200241186a2002280208200228020c1045200241a0016a200228021822042002280220106b0240200228021c450d00200410010b02402006450d002006410c6c21032007210403400240200441046a280200450d00200428020010010b2004410c6a2104200341746a22030d000b2006450d00200710010b200241186a41186a200241a0016a41186a290300370300200241186a41106a2204200241a0016a41106a290300370300200241186a41086a2203200241a0016a41086a290300370300200220022903a00137031820024190016a41086a220642003703002002420037039001418ef2c100411520024190016a1002200241c0016a41086a200629030037030020022002290390013703c001200241c0016a4110200241186a41201003200241186a10ec01200241003602a801200242013703a001200241186a41146a200241a0016a101e2002290318200241a0016a109c01200241cc006a200241a0016a101e200241ec006a200241a0016a101e200241a0016a2003101f20023502a801210520023502a00121102002280220210a024020042802002204450d00200441286c2103200a21040340024020042d00002206450d00024020064101470d00200441086a280200450d01200441046a2802001001200441286a2104200341586a22030d020c030b200441146a280200450d00200441106a28020010010b200441286a2104200341586a22030d000b0b0240200241246a280200450d00200a10010b200241d0016a240020054220862010840f0b1018000b411441011019000b102c000b200c10010b41eac4c10041331042000b200d41011019000b41eac4c10041331042000b200441011019000b41eac4c10041331042000b200441041019000bd60d03027f037e0b7f230041b0046b22022400200242003703d002200241d0026a20004188f0c10020011b20014108200141084922001b220310f8021a0240024020000d00200120036b41074d0d0020022903d0022104200241d0026a41086a22014200370300200242003703d00241a0a5c100410d200241d0026a1002200241d8016a41086a22002001290300370300200220022903d0023703d80142002105024002400240200241d8016a41104188f0c100410041001004417f460d00200242003703d002200241d8016a4110200241d0026a41084100100441016a41084d0d0120022903d00221050b20014200370300200242003703d00241daa3c1004115200241d0026a100220002001290300370300200220022903d0023703d80102400240200241d8016a41104188f0c100410041001004417f460d00200242003703d002200241d8016a4110200241d0026a41084100100441016a41084d0d0320022903d002210641182101411810002207450d010c050b42052106411821014118100022070d040b200141081019000b41eac4c10041331042000b41eac4c10041331042000b200241e4026a4101360200200241dc026a4101360200200241013602dc012002418cd6c2003602d801200241e0c3c1003602d802200241013602d402200241e4d5c2003602d0022002200241d8016a3602e002200241d0026a41ecd5c2001071000b200742023703082007410036020020072004200620057c220520052004541b37031002400240024002400240024002400240024041e00110002208450d00200720016a2100410021034100210920082101024002400340200720036a220a41086a29030022044203510d01200a2903002105200141a0016a200a41106a29030037020020014198016a200437020020014190016a4100360200200141f8006a4202370200200120053e0200200141e0016a2101200941016a2109200341186a22034118470d000c020b0b200a41186a21000b2007411820006b6a2101024003402001450d01200141686a210120002903082104200041186a210020044203520d000b0b200710014100210b20082009410041202009676b10d601200941e0016c220141e0016d210c024002402001450d00200cad42d8017e2204422088a70d072004a722004100480d0720001000220d450d03200820016a22032008460d010c040b4108210d4100210c200820016a22032008470d030b200320082201470d030c040b41e00141081019000b200041081019000b200241d8026a210a4100210b20082101200d210002400340200241d8016a200141f80010f8021a200141f8006a2903002104200241f8006a20014180016a41e00010f8021a20044203510d01200241d0026a200241d8016a41f80010f8021a200241086a200a41f00010f8021a2000200241086a41f00010f802220041f0006a2004370300200041f8006a200241f8006a41e00010f8021a200041d8016a2100200b41016a210b200141e0016a22012003470d000b200320032201470d010c020b2003200141e0016a2201460d010b200241e0036a2100200241d0026a4180016a210a0340200241d0026a200141f80010f8021a200141f8006a2903002104200241086a20014180016a41e00010f8021a20044203510d01200241d8016a200241d0026a41f80010f8021a200241f8006a200241086a41e00010f8021a200241d0026a200241d8016a41f80010f8021a200241d0026a41f8006a2004370300200a200241f8006a41e00010f8021a20001028200141e0016a22012003470d000b0b20081001200241003602e001200242013703d801200b200241d8016a101b0240200b450d00200b41d8016c210e200241d8016a41086a220f280200210120022802dc012103200d210a03402002200a360208200241d0026a200241086a10e80120022802d00221080240024002400240200320016b200241d0026a41086a28020022094f0d00200120096a22002001490d0620034101742207200020002007491b22104100480d062003450d0120022802d8012111201010002207450d072007201120102003200320104b1b10f8021a201110010c020b200120096a210020022802d80121070c020b201010002207450d050b200220103602dc01200220073602d801201021030b200f2000360200200720016a2008200910f8021a024020022802d402450d00200810010b200a41d8016a210a20002101200e41a87e6a220e0d000b0240200b450d00200b41d8016c2103200d4188016a2101034020011028200141d8016a2101200341a87e6a22030d000b0b200c450d040c030b200241e0016a280200210020022802d8012107200c0d020c030b1018000b201041011019000b200d10010b200241b0046a24002000ad4220862007ad840bd21102097f057e230041b0016b22022400024002402001450d00200220003602000c010b20024188f0c1003602000b20022001360204200241086a200210a50102400240024002400240024002400240024020022802102203450d0020024188016a280200210420024184016a2802002105200241186a2802002106200241146a2802002107200228028001210820024200370308200241086a200228020022092002280204220141082001410849220a1b220010f8021a2002200120006b22013602042002200920006a22003602000240200a0d002002290308210b20024200370308200241086a20002001410820014108491b220910f8021a2002200120096b3602042002200020096a360200200141074d0d0002400240024002402004450d002008280288010d002008290390014202520d002002290308210c200829039801210d41012100200841f0006a2903004202520d01200241086a41086a220142003703002002420037030841a0a5c100410d200241086a100220024190016a41086a2209200129030037030020022002290308370390014200210e024020024190016a41104188f0c100410041001004417f460d002002420037030820024190016a4110200241086a41084100100441016a41084d0d072002290308210e0b200142003703002002420037030841daa3c1004115200241086a100220092001290300370300200220022903083703900120024190016a41104188f0c100410041001004417f460d022002420037030820024190016a4110200241086a41084100100441016a41084d0d072002290308210f200d200b423c7c580d030c080b02402006450d00200641286c2100200321010340024020012d00002209450d00024020094101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b02402007450d00200310010b02402004450d00200441d8016c210020084188016a2101034020011028200141d8016a2101200041a87e6a22000d000b0b421c210b4101210941eca0c100210a2005450d0c200810010c0c0b4224210b41a0b0c100210a0c070b4205210f200d200b423c7c560d050b0240200d200f200e7c220b5a0d004201210e0c070b410221000c050b2002411c6a4101360200200241146a4101360200200241013602940120024194d6c20036029001200241e0c3c1003602102002410136020c200241e4d5c200360208200220024190016a360218200241086a41ecd5c2001071000b200241a4016a41013602002002419c016a4101360200200241013602ac0120024194d6c2003602a801200241e0c3c100360298012002410136029401200241e4d5c200360290012002200241a8016a3602a00120024190016a41ecd5c2001071000b41eac4c10041331042000b41eac4c10041331042000b4225210b41c4b0c100210a0b2002200b37020c2002200a3602084200210e20004102460d002006450d020c010b024020044102490d0020082802e0024101470d0020082802e8024103470d00421e210b41ba8cc000210a20060d010c020b02402006450d00200641286c2100200321010340024020012d00002209450d00024020094101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b200e50210902402007450d00200310010b200b200b20091b210f200441d8016c210020084188016a2101034020011028200141d8016a2101200041a87e6a22000d000b02402005450d00200810010b200241086a41086a220142003703002002420037030841daa3c1004115200241086a100220024190016a41086a20012903003703002002200229030837039001024002400240024020024190016a41104188f0c100410041001004417f460d002002420037030820024190016a4110200241086a41084100100441016a41084d0d022002290308210b0c010b4205210b0b427f200b200b7c220e200e200b541b220b4200510d01410041aebdc100200d200b80220d200c5122011b210a02402009450d004102410120011b21094231210b0c050b200f423120011b210b200d200c5221090c040b41eac4c10041331042000b41a485c300104f000b200641286c2100200321010340024020012d00002209450d00024020094101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b02402007450d00200310010b200441d8016c210020084188016a2101034020011028200141d8016a2101200041a87e6a22000d000b02402005450d00200810010b200b42ffffffff0f83210b410121090b20024100360210200242013703084101100021010240024002400240024002400240024020094102470d002001450d02200242818080801037020c20022001360208200141003a0000428080808010210b0c010b2001450d02200242818080801037020c20022001360208200141013a0000410210002100024020094101470d002000450d04200020012d00003a000020011001200242828080802037020c20022000360208200041013a0001200a200ba7200241086a108e01200241106a350200422086210b200228020821010c010b2000450d04200020012d00003a000020011001200242828080802037020c20022000360208200041003a000102400240200228020c2209417e6a41074b0d0020094101742201410a2001410a4b1b22044100480d07200410002201450d082001200020042009200920044b1b10f8022109200010012002200436020c200220093602080c010b200021010b200241106a410a3602002001200b3700024280808080a001210b0b200241b0016a2400200b2001ad840f0b410141011019000b410141011019000b410241011019000b410241011019000b1018000b200441011019000bb90302077f037e230041e0006b22022400200241c0006a41086a220342003703002002420037034041a3f2c1004111200241c0006a1002200241086a2204200329030037030020022002290340370300024002400240200241104188f0c100410041001004417f460d00200241d8006a4200370300200241c0006a41106a4200370300200342003703002002420037034020024110200241c0006a4120410010042203417f460d022003411f4d0d02200241206a41186a2203200241c0006a41186a2204290300370300200241206a41106a2205200241c0006a41106a2206290300370300200241206a41086a2207200241c0006a41086a22082903003703002002200229034037032020042003290300220937030020062005290300220a37030020082007290300220b370300200241086a200b370300200241106a200a370300200241186a2009370300200220022903202209370340200220093703000c010b200241186a4200370300200241106a420037030020044200370300200242003703000b200241c0006a200210f501200235024821092002350240210a200241e0006a2400200a2009422086840f0b41eac4c10041331042000b6501017f0240412010002202450d00200042a080808080043702042000200236020020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a2900003700000f0b412041011019000bc80c05027f017e017f017e077f230041a0076b22022400024002402001450d00200220003602080c010b20024188f0c1003602080b2002200136020c200241c8056a200241086a10a701024002400240024002400240024002400240024020022903b8064203510d00200241106a200241c8056a41d80110f8021a200241e8016a200241106a41d80110f8021a2002200241e8016a3602c004200241c8056a200241c0046a10e80120022802d0052100024020022802cc05450d0020022802c80510010b200241c8056a200241e8016a41d80110f8021a200241c0046a200241c8056a10f701024002400240024020022802c0044101470d004100210320022802c8044115470d01024020022802c4042201418987c200460d002001418987c200411510fa020d020b410221030c010b200241c0036a200241c0046a41086a41800110f8021a410021030240200241c0036a41086a410020022903c0034201511b2201450d002001450d002001200010f8010d00200110f9012104200141206a410020011b220529030022062004540d0041022103200620044280027c580d020b200241f0036a10fa010b200241003602d005200242013703c80502400240024020034101460d0020034102470d01410110002207450d0620024281808080103702cc05200220073602c805200741023a00000c020b41012100410110002201450d030c090b410110002207450d0520024281808080103702cc05200220073602c805200741003a00000b42808080801021040c080b02400240200420065a0d0041042109200241c8056a41086a210a410021074100210c410021080340200a2004370300200220013602c805200241c0046a200241c8056a10fb0102402008200c470d00200c41016a2203200c490d0c200c410174220b20032003200b491b220bad420c7e2206422088a70d0c2006a722034100480d0c02400240200c450d0020031000220d450d0a200d20092003200c410c6c220c200c20034b1b10f802210320091001200321090c010b200310002209450d090b200b210c0b200920076a220320022903c004370200200341086a200241c0046a41086a2802003602002007410c6a2107200841016a2108200442017c22042005290300540d000c020b0b4100210c41042109410021080b410c1000220a450d05200220013602c805200220052903003703d005200241c0046a200241c8056a10fb01200a41086a200241c0046a41086a280200360200200a20022903c004370200200241f0036a10fa01200241003602d005200242013703c8052000ad210441012103410121004101100022010d060b200020001019000b200241fc016a4101360200200241f4016a4101360200200241013602142002419cd6c200360210200241e0c3c1003602f001200241013602ec01200241e4d5c2003602e8012002200241106a3602f801200241e8016a41ecd5c2001071000b410141011019000b410141011019000b200341041019000b410c41041019000b20024281808080103702cc05200220013602c805200120003a0000410910002200450d02200020012d00003a0000200110012002428980808090013702cc05200220003602c805200020043700012008200241c8056a101b02402008450d0020092008410c6c6a21002009210103402001280200200141086a280200200241c8056a108e012001410c6a22012000470d000b0b4101200241c8056a101b200a280200200a280208200241c8056a108e01024002400240024020022802cc052200200241c8056a41086a28020022016b41084f0d00200141086a22072001490d0520004101742205200720072005491b22054100480d052000450d0120022802c805210b200510002207450d072007200b20052000200020054b1b10f8021a200b10010c020b20022802c80521070c020b200510002207450d050b200220053602cc05200220073602c8050b200241c8056a41086a200141086a2200360200200720016a427f3700002000ad422086210420034101470d0002402008450d002008410c6c21002009210103400240200141046a280200450d00200128020010010b2001410c6a2101200041746a22000d000b0b0240200c450d00200910010b0240200a41046a280200450d00200a28020010010b200a10010b200241a0076a240020042007ad840f0b1018000b410941011019000b200541011019000bdb1405017f037e017f037e057f230041a0046b2202240002400240200129037022034202520d00200220014188016a41d00010f8021a420021030c010b200241f0006a41206a200141286a280200360200200241f0006a41186a200141206a290200370300200241f0006a41106a200141186a290200370300200241f0006a41086a200141106a29020037030020022001290208370370200241d0016a200141e4006a290000370300200241c8016a200141dc006a29000037030020024198016a41286a200141d4006a29000037030020024198016a41206a200141cc006a29000037030020024198016a41186a200141c4006a29000037030020024198016a41106a2001413c6a29000037030020024198016a41086a200141346a2900003703002002200129002c3703980120012903002105200241d8016a41106a200141f0006a220641106a290300370300200241d8016a41086a200641086a290300370300200220062903003703d80120014180016a2903002107200129037821084200210920024190026a41086a22064200370300200242003703900241f0f1c100410d20024190026a1002200241086a200629030037030020022002290390023703004200210402400240024002400240024002400240200241104188f0c100410041001004417f460d0020024200370390022002411020024190026a41084100100441016a41084d0d0120022903900221040b024020034201520d002008500d022004200720072004541b2203200320077d2008827d21090b20024190026a200910e7012002418c026a41026a220620022d0092023a0000200241086a220a20024190026a41136a2900003703002002410d6a220b20024190026a41186a290000370000200220022f0190023b018c022002200229009b023703002002290093022103200241f0016a410d6a220c200b290000370000200241f0016a41086a220b200a290300370300200220022903003703f001200220053703900220024190026a41086a20014188016a41d00010f802210a20024183036a2003370000200241f8026a200241e8016a290300370300200241f0026a200241d8016a41086a29030037030020024182036a20062d00003a00002002418b036a20022903f00137000020024193036a200b29030037000020024190026a4188016a200c290000370000200220022903d8013703e802200220022f018c023b018003200241f0006a41086a28020021062002280274210120022d0070210b200241fc036a41026a220c20022d00733a0000200241e0036a41086a220d20024184016a290200370300200241e0036a410d6a220e20024189016a290000370000200220022f00713b01fc032002200241fc006a2902003703e003024002400240200b4101470d002002200141067610ce0220022802082001413f7122014d0d012002419c046a41026a220b2002280200220e20014105746a220141026a2d00003a000020024180046a41086a220c200141136a29000037030020024180046a410d6a220d200141186a290000370000200220012f00003b019c042002200129000b37038004200128000721062001280003210102402002280204450d00200e10010b200241026a200b2d0000220b3a0000200241136a200c2903002203370000200241186a200d2900002204370000200241dc036a41026a200b3a0000200241d0006a41086a2003370300200241d0006a410d6a20043700002002200636000720022001360003200220022f019c04220b3b01002002200229038004220337000b2002200b3b01dc03200220033703504100210b0c020b200241026a200c2d0000220b3a0000200241136a200d2903002203370000200241186a200e2900002204370000200241dc036a41026a200b3a0000200241d0006a41086a2003370300200241d0006a410d6a20043700002002200636000720022001360003200220022f01fc03220b3b0100200220022903e003220337000b2002200b3b01dc03200220033703504100210b0c010b02402002280204450d00200228020010010b4101210b41152106418987c20021010b200241d8036a41026a220c200241dc036a41026a2d00003a0000200241c0036a41086a220d200241d0006a41086a290300370300200241c0036a41106a200241d0006a41106a290300370300200220022f01dc033b01d803200220022903503703c003024002400240200b450d002000200136020420004101360200200041086a20063602000c010b200241b3036a200d290300370000200241b8036a200241cd036a290000370000200220022f01d8033b01a003200220063600a703200220013600a303200220022903c0033700ab032002200c2d00003a00a20320024100360208200242013703002002290390022103410810002201450d0420024108360204200241086a22062006280200220b41086a360200200220013602002001200b6a2003370000200a2002101c02400240024002400240024002400240024020022903e8024201520d00200241f0026a2903002203420c882204420120044201561b22044200510d0f200241f8026a29030020048021042002280204220b200241086a28020022016b41024f0d01200141026a22062001490d0e200b4101742201200620062001491b22014100480d0e200b450d052002280200210c200110002206450d112006200c2001200b200b20014b1b10f8021a200c10010c060b0240200228020420062802002201470d00200141016a22062001490d0e2001410174220b20062006200b491b220b4100480d0e2001450d022002280200210c200b10002206450d102006200c200b20012001200b4b1b10f8021a200c10010c030b200228020021060c030b200228020021060c050b200b10002206450d0d0b2002200b36020420022006360200200241086a28020021010b200241086a200141016a360200200620016a41003a00000c030b200110002206450d0b0b2002200136020420022006360200200241086a28020021010b200241086a200141026a360200200620016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b20024180036a2002101e200228020421012002280200220b200241086a28020020024198016a200241a0036a100f210602402001450d00200b10010b2006450d01200041ccb7c10036020420004101360200200041086a411a3602000b200a10fa01200241a0046a24000f0b200241d0006a41186a200241a0036a41186a290300370300200241d0006a41106a200241a0036a41106a290300370300200241d0006a41086a200241a0036a41086a290300370300200220022903a00337035020022903900221042002200a41d00010f8021a420121030c070b41eac4c10041331042000b41a090c200104f000b410841011019000b1018000b418cacc300104f000b200b41011019000b200141011019000b200041086a2003370300200041306a2004370300200041106a2002290350370300200041186a200241d0006a41086a290300370300200041206a200241d0006a41106a290300370300200041286a200241d0006a41186a290300370300200041386a200241d00010f8021a20004100360200200241a0046a24000bf00904057f017e017f087e230041c0006b22022400024002400240411410002203450d002002421437023420022003360230200241306a41eeefc10041141025200241206a41086a22032002280238360200200220022903303703202000200241206a101e20032802002104200228022421052002280220210642002107200241306a41086a220842003703002002420037033020062004200241306a1002200320082903003703002002200229033037032002400240200241206a41104188f0c100410041001004417f460d002002420037033820024200370330200241206a4110200241306a4110410010042203417f460d012003410f4d0d01200241386a2903002109200229033021072005450d040c030b4200210920050d020c030b41eac4c10041331042000b411441011019000b200610010b4200210a200241306a41086a22034200370300200242003703304188f0c100411b200241306a1002200241206a41086a2206200329030037030020022002290330370320024002400240024002400240200241206a41104188f0c100410041001004417f460d002002420037033820024200370330200241206a4110200241306a4110410010042204417f460d022004410f4d0d02200241386a290300210b2002290330210c0c010b4200210c4200210b0b200342003703002002420037033041a3f0c100411b200241306a1002200620032903003703002002200229033037032002400240200241206a41104188f0c100410041001004417f460d002002420037033820024200370330200241206a4110200241306a4110410010042203417f460d032003410f4d0d03200241386a290300210d2002290330210a0c010b4200210d0b4200210e2002200a200d2001ad420010fc02200241306a41086a220342003703002002420037033041bef0c100411b200241306a1002200241206a41086a200329030037030020022002290330370320200241086a290300210f2002290300210d02400240200241206a41104188f0c100410041001004417f460d002002420037033820024200370330200241206a4110200241306a4110410010042203417f460d042003410f4d0d04200241386a29030021102002290330210e0c010b420021100b41eff0c100210302402007200e200d200c7c220a7c220c5420092010200f200b7c200a200d54ad7c220d7c200c200e54ad7c220e542009200e511b0d0020002007200a7d2009200d7d2007200a54ad7d10aa0142002107200241306a41086a220342003703002002420037033041d9f0c1004116200241306a1002200241206a41086a2003290300370300200220022903303703204100210302400240200241206a41104188f0c100410041001004417f460d002002420037033820024200370330200241206a4110200241306a4110410010042206417f460d062006410f4d0d06200241386a290300210e200229033021070c010b4200210e0b2007200a7d2209200756200e200d7d2007200a54ad7d220a200e56200a200e511b0d00200220093703102002200a370318200241306a41086a220642003703002002420037033041d9f0c1004116200241306a1002200241206a41086a200629030037030020022002290330370320200241206a4110200241106a411010030b200241c0006a240020030f0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b8c0203047f017e017f230041206b220124000240411310002202450d002001421337021420012002360210200141106a41abf1c10041131025200141086a220220012802183602002001200129031037030020002001101e20022802002103200128020421042001280200210042002105200141106a41086a220642003703002001420037031020002003200141106a1002200220062903003703002001200129031037030002400240200141104188f0c100410041001004417f460d002001420037031020014110200141106a41084100100441016a41084d0d01200129031021050b02402004450d00200010010b200141206a240020050f0b41eac4c10041331042000b411341011019000b880301017f0240024002400240024002400240024002400240024020002802002201410b4b0d0020010e0c0a010a0a0a02030405060a070a0b20002d00044102470d092000410c6a280200450d09200041086a28020010010f0b200041086a10290f0b200041086a2d000022014105460d0520014102470d072000410c6a220028020010fa01200028020010010f0b200041086a2802004102470d06200041106a280200450d062000410c6a28020010010f0b200041086a2d00004102470d052000410c6a220028020010fa01200028020010010f0b20002d00044102470d042000410c6a220028020010fa01200028020010010f0b20002802044102490d032000410c6a280200450d03200041086a28020010010f0b200041086a2d000022014102490d0220014102470d01200041306a280200450d022000412c6a28020010010f0b2000410c6a220028020010fa01200028020010010f0b0240200041106a280200450d002000410c6a28020010010b2000411c6a280200450d00200041186a28020010010f0b0bcc0102057f017e2001280200210202400240412010002203450d0020032002290000370000200341186a2204200241186a290000370000200341106a2205200241106a290000370000200341086a2206200241086a2900003700002001290308210741c00010002202450d0120022003290000370000200241186a2004290000370000200241106a2005290000370000200241086a200629000037000020031001200042c0808080800537020420002002360200200220073700200f0b412041011019000b41c00041011019000ba40803067f017e017f230041d0006b22022400024002402001450d00200220003602180c010b20024188f0c1003602180b2002200136021c200241c0006a200241186a10fd010240024002400240024020022802402203450d0020022802442104200241106a20032003200241c8006a280200220541286c6a102e200228021421062002280210210102400240034020062001460d0120012d00002100200141286a2207210120004102470d00200741606a2903002108200241086a200741686a28020022012001200741706a28020041286c6a102e20022002280208200228020c102e200241286a2002280200200228020410442002200229022c3703400240200228022822090d00200721010c010b0b200241346a2002290340370200200241286a41146a200241c0006a41086a280200360200200220093602302002200837032802402005450d00200541286c2100200321010340024020012d00002207450d00024020074101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b200241286a41086a21002004450d01200310010c010b410021092002410036023002402005450d00200541286c2100200321010340024020012d00002207450d00024020074101470d00200141086a280200450d01200141046a2802001001200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010010b200141286a2101200041586a22000d000b0b200241286a41086a210002402004450d0020031001410021090b0b20024100360248200242013703404101100021010240024002400240024002402009450d002001450d07200141013a0000200242818080801037024420022001360240200241c0006a2000102220022802442206200241c0006a41086a28020022076b41084f0d01200741086a22002007490d0820064101742201200020002001491b22034100480d082006450d0220022802402105200310002201450d0a2001200520032006200620034b1b10f8021a200510010c030b2001450d08200141003a0000200242818080801037024420022001360240410121000c040b200741086a2100200228024021010c020b200310002201450d070b20022003360244200220013602400b200241c8006a2000360200200120076a2008370000200241346a280200450d00200910010b200241d0006a24002000ad4220862001ad840f0b2002413c6a4101360200200241346a410136020020024101360224200241a4d6c200360220200241e0c3c1003602302002410136022c200241e4d5c2003602282002200241206a360238200241286a41ecd5c2001071000b410141011019000b1018000b410141011019000b200341011019000bdb190a027f027e117f027e017f027e037f017e077f017e230041d0026b22022400200241086a2001103a024002400240024002400240024002402002280208450d00200228020c2203ad220442287e2205422088a70d042005a72206417f4c0d04024002400240024002402006450d00200610002207450d0a20030d010c020b410821072003450d010b200241c7016a2108200241f8006a41116a2109200241b8016a41106a2106200241b8016a410172210a200241106a410172210b200141046a210c20024188026a41026a210d200241b8016a41076a210e20024180026a210f410021100340200c2802002111200241003a00b801200241b8016a200128020022122011410047221310f8021a20112013490d06200c201120136b22143602002001201220136a22133602000240024002400240024002400240024002400240024002402011450d004104211220022d00b801221141034b0d0b024020110e0400040203000b20022001103a2002280200450d0b20022802042211417f4c0d142011450d08201110002215450d1620154100201110f7021a0c090b410421120c0a0b200241b8016a2014412020144120491b22116a41004100412020116b2011411f4b1b10f7021a200241b8016a2013201110f8021a200c201420116b3602002001201320116a3602002014411f4d0d04200241c0026a41026a200241b8016a41026a2d00003a000020024188026a41086a200841086a29000037030020024188026a41106a200841106a2d00003a0000200220022f00b8013b01c0022002200829000037038802200241b8016a41036a2800002116200e2900002117410121110c050b200242003703b801200241b8016a20132014410820144108491b221510f8021a200c201420156b22113602002001201320156a2215360200201441074d0d0120022903b8012118200241b8016a201141c000201141c000491b22136a4100410041c00020136b2013413f4b1b10f7021a200241b8016a2015201310f8021a200c201120136b3602002001201520136a3602002011413f4d0d0120024188026a41086a200841086a29000037030020024188026a41106a200841106a29000037030020024188026a41186a200841186a29000037030020024188026a41206a200841206a29000037030020024188026a41286a200841286a29000037030020024188026a41306a200841306a2d00003a0000200220022f00b8013b01c00220022008290000370388022002200241b8016a41026a2d00003a00c202200241b8016a41036a2800002119200e290000211a410121112018211b0c020b200241b8016a2001103920022802b8012211450d0720022902bc012105200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2006290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a2903003703002002200d2d00003a00b201200220022f0088023b01b001200220022903b801370378410021122011211c0c060b410021110b200241b8016a41086a221320024188026a41086a290300370300200620024188026a41106a290300370300200241b8016a41186a221420024188026a41186a290300370300200241b8016a41206a221520024188026a41206a290300370300200241b8016a41286a221d20024188026a41286a290300370300200241b8016a41306a221e20024188026a41306a2d00003a0000200220022d00c2023a00ca02200220022f01c0023b01c80220022002290388023703b8012011450d05200241f8006a41086a2013290300370300200241f8006a41106a2006290300370300200241f8006a41186a2014290300370300200241f8006a41206a2015290300370300200241f8006a41286a201d290300370300200241f8006a41306a201e2d00003a0000200220022d00ca023a00b201200220022f01c8023b01b001200220022903b801370378410221122019211c201a2105201b211f0c050b410021110b200241c8026a41026a2214200241c0026a41026a2d00003a0000200241b8016a41086a221320024188026a41086a290300370300200620024188026a41106a2d00003a0000200220022f01c0023b01c80220022002290388023703b8012011450d03200241f8006a41086a2013290300370300200241f8006a41106a20062d00003a0000200220022f01c8023b01b001200220022903b801370378200220142d00003a00b2012009411f6a200241b8016a411f6a290000370000200941186a200241b8016a41186a290000370000200941106a2006290000370000200941086a2013290000370000200920022900b801370000410121122016211c201721050c020b410121150b20152001280200200c2802002214201120142011491b221310f8022115200c280200221d2013490d0d200c201d20136b3602002001200128020020136a3602000240201420114f0d00201510010c020b2015450d012011ad22054220862005842105200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2006290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a290300370300200220022f0088023b01b001200220022903b8013703782002200d2d00003a00b201410321122015211c0b0b200d20022d00b2013a0000200241b8016a41086a2211200241f8006a41086a22142903003703002006200241f8006a41106a2215290300370300200241b8016a41186a2213200241f8006a41186a221d290300370300200241b8016a41206a221e200241f8006a41206a290300370300200241b8016a41286a2220200241f8006a41286a290300370300200241b8016a41306a2221200241f8006a41306a290300370300200220022f01b0013b018802200220022903783703b80120124104460d02200241f4006a41026a2222200d2d00003a0000200241386a41086a22232011290300370300200241386a41106a22242006290300370300200241386a41186a22252013290300370300200241386a41206a2226201e290300370300200241386a41286a221e2020290300370300200241386a41306a22202021290300370300200220022f0188023b0174200220022903b80137033820112005370300200a20022f01743b0000200a41026a20222d00003a000020062002290338370000200641086a2023290300370000200641106a2024290300370000200641186a2025290300370000200641206a2026290300370000200641286a201e290300370000200641306a2020290300370000200220123a00b8012002201c3602bc01200f201f370300200241106a200241b8016a10d60220022d00102112200241b8016a411f6a221e200b411f6a2900003700002013200b41186a2900003703002006200b41106a2900003703002011200b41086a2900003703002002200b2900003703b80120124103460d03200241f8006a411f6a2220201e290000370000201d20132903003703002015200629030037030020142011290300370300200220022903b80137037802402004422088a722112004a7470d00201141016a22132011490d062011410174221e20132013201e491bad221842287e2227422088a70d062027a722134100480d06024002402011450d0020131000221e450d0a201e20072013201141286c2211201120134b1b10f802211120071001201121070c010b201310002207450d090b20044280808080708320188421040b20072004422088a741286c6a221120123a0000201141206a2020290000370000201141196a201d290300370000201141116a2015290300370000201141096a20142903003700002011200229037837000120044280808080107c2104201041016a22102003490d000b0b2007450d022000200437020420002007360200200241d0026a24000f0b200241033a0010200241b8016a411f6a200b411f6a290000370000200241b8016a41186a200b41186a290000370300200241b8016a41106a200b41106a290000370300200241b8016a41086a200b41086a2900003703002002200b2900003703b8010b02402004422088a72206450d00200641286c2111200721060340024020062d0000220b450d000240200b4101470d00200641086a280200450d01200641046a2802001001200641286a2106201141586a22110d020c030b200641146a280200450d00200641106a28020010010b200641286a2106201141586a22110d000b0b2004a7450d00200710010b20004100360200200241d0026a24000f0b1018000b20132011107a000b201341081019000b102c000b200641081019000b201141011019000b2013201d107a000bc004020b7f017e230041206b22022400200210ff0120024100360218200242013703102002280200210320022802082204200241106a101b0240024002400240024002402004450d002003200441286c6a2105200241106a41086a22062802002107200228021421082003210403400240024002400240200820076b41204f0d00200741206a22092007490d062008410174220a20092009200a491b220a4100480d062008450d012002280210210b200a1000220c450d07200c200b200a20082008200a4b1b10f8021a200b10010c020b200741206a21092002280210210c2008210a0c020b200a1000220c450d050b2002200a3602142002200c3602100b20062009360200200c20076a220741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a29000037000020072004290000370000200441206a290300210d0240024002400240200a20096b41084f0d00200941086a22072009490d06200a4101742208200720072008491b22084100480d0620081000210b200a450d01200b450d08200b200c2008200a200a20084b1b10f8021a200c10010c020b200941086a2107200c210b200a21080c020b200b450d060b200220083602142002200b3602100b20062007360200200b20096a200d3700002005200441286a2204470d000b2002280204450d050c040b200241186a28020021072002280210210b20022802040d030c040b1018000b200a41011019000b200841011019000b200310010b200241206a24002007ad422086200bad840b940101047f230041206b220124000240410e10002202450d002001420e37021420012002360210200141106a41d79bc100410e1025200141086a2202200128021836020020012001290310370300200141b7b6c100410310252001280204210320012802002204200228020010c401210202402003450d00200410010b2000410020021041200141206a24000f0b410e41011019000bd10102027f027e230041206b22022400200241106a41086a220342003703002002420037031041daa3c1004115200241106a1002200241086a200329030037030020022002290310370300024002400240200241104188f0c100410041001004417f460d002002420037031020024110200241106a41084100100441016a41084d0d02200229031021040c010b420521040b200241106a427f200420047c220520052004541b1088012002350218210420023502102105200241206a240020052004422086840f0b41eac4c10041331042000b5201027e02402003450d0020022802000d002001280224220342002003290308220420023502047d220520052004562005507222021b37030820004105410420021b3602000f0b41ff80c10041f4031042000bbe0702067f017e230041b0016b22042400024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241146a2802002105200241246a2802002106200241346a2802002107200441106a200120022802044120108302024002400240024020042802102208450d00200441186a2802002103200428021421092005450d01200441106a20012006200710830220042802102205450d032004290214210a2003417f4a0d020c080b410521020c0a0b410021052003417f4c0d060b20012802002802002102024002402003450d002003100022010d01200341011019000b410121010b200441003602182004200336021420042001360210200441106a200820031025200441086a20042802183602002004200429031037030020022802000d062002417f360200200441c8006a41186a2203200241c4006a290000370300200441c8006a41106a22012002413c6a290000370300200441c8006a41086a200241346a2900003703002004200229002c370348200441106a200241046a200441c8006a10df010240024020042802104101470d00200441186a2802002103200441106a41106a28020021012004420037028401200441e8bdc000360280012003200141306c6a41e8026a2103200441c8006a20044180016a10cb01200441c8006a10cc010c010b200441f8006a200441106a41346a280200360200200441c8006a41286a2004413c6a290200370300200441e8006a200441346a29020037030020032004412c6a2902003703002001200441246a290200370300200441c8006a41086a2004411c6a2902003703002004200429021437034820044180016a41186a410036020020044180016a41106a420037030020044180016a41086a420037030020044180016a41286a42003703002004420037038001200441e8bdc0003602a401200441c8006a20044180016a10e20121030b20044180016a41086a200441086a28020036020020042004290300370380012004200a37024c20042005360248200441106a200341246a20044180016a200441c8006a10e00102402004280210450d0020042802142203450d00200441186a280200450d00200310010b2002200228020041016a360200410421022009450d080c070b4105210220090d060c070b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b102c000b108402000b200810010b20002002360200200441b0016a24000b880202027f027e230041206b220424002004200128021c29031842002003ad420010fc02024020042903084200510d0020004100360200200441206a24000f0b2001280224220542002005290308220620042903007d220720072006562007507222051b37030802402005450d0020004100360200200441206a24000f0b2004410036021820044201370310200441106a200310270240024020012802202802082002200428021022032004280218100b2201417e460d0020010d0120002004290310370200200041086a200441106a41086a280200360200200441206a24000f0b2000410036020002402004280214450d00200310010b200441206a24000f0b41d08dc200104f000b900101017f230041c0006b220024002000411036020c200041fb9dc100360208200041286a410c6a410e360200200041246a4102360200200041106a410c6a41023602002000410136022c2000418489c20036021820004102360214200041a4aec3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41b4aec3001071000b810301067f230041306b220424000240024002402003450d0020022802000d00200441206a2001200228020441201083020240024020042802202203450d00200428022421052004200128020028020022022002412c6a2003200441206a41086a220228020010860220042802002206450d01200441106a41086a200441086a2207280200360200200420042903003703102002200728020036020020042004290300370320200141106a21020240200141146a280200450d00200228020010010b20022004290320370200200241086a200441206a41086a28020036020041002101410121072005450d040c030b20004105360200200441306a24000f0b41002107410021080240200141186a22092802002202450d00410021010340200141016a22012002490d000b200220016b21080b200920083602004101210120050d010c020b41ff80c10041f4031042000b200310010b02402007200645720d002004280204450d00200610010b2000410036020020002001360204200441306a24000b860401087f230041306b220524000240200128020022064100480d00200641ffffffff07460d002001200641016a36020002400240200141046a200210de012206450d0020062802282107200541286a2108200641246a22092106034020062802002106200820093602002005200636022420052007360220200541086a200541206a10a10120052802082206200528020c410c6c6a210b4180012107417f210a024003400240024002402006200b460d002006450d0002402003200628020020062802082209200420092004491b10fa02220c450d002007410c6a2107417f4101200c4100481b2209450d020c030b2007410c6a21074100417f4101200920044b1b20092004461b22090d020c010b2005200541206a10a1012005280204210a0c030b200528022420076a2206450d04024002402006280200450d00200541206a2006102b0c010b200541003602200b200541106a41086a2206200541206a41086a28020036020020052005290320370310200041086a2006280200360200200020052903103702000c050b2006410c6a2106200a41016a210a20094101460d000b0b20052802202206450d01200828020021092006417f6a21072005280224200a4102746a4190026a21060c000b0b20002001280210200220032004200141146a28020028020c1103000b20012001280200417f6a360200200541306a24000f0b10c602000bec0804017f017e077f037e230041a0016b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d06200241286a2903002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a280200210920044180016a20012002280204200241146a2802001083020240024002402004280280012203450d00200428028401210a20044180016a20044180016a41086a220b280200220241202002412049220c1b22026a41004100412020026b2002411f4b1b10f7021a20044180016a2003200210f8021a02400240200c0d00200441106a41186a20044180016a41186a290000370300200441106a41106a20044180016a41106a290000370300200441106a41086a200b29000037030020042004290080013703100240200a450d00200310010b20044180016a2001200620071083022004280280012203450d0220044188016a2207280200210220042802840121062004420037038801200442003703800120044180016a20032002411020024110491b10f8021a2002410f4d0d012007290300210d200429038001210e02402006450d00200310010b20044180016a200120082009108302200428028001450d02200441306a41086a20044180016a41086a2802003602002004200429038001370330200141186a22062802002203450d03410021020340200241016a22022003490d000b200320026b21020c040b200a450d01200310010c010b2006450d00200310010b20004105360200200441a0016a24000f0b410021020b2006200236020041012102024020012802242203290308220f200f20052005501b2205540d00200341086a2206200f20057d3703002003290310210f200441c0006a41186a200341186a29030037030020042005370348200420053703402004200f3703502004280230210320042802382107200441e0006a41186a2001280200280200220241c4006a290000370300200441e0006a41106a2002413c6a290000370300200441e0006a41086a200241346a2900003703002004200229002c37036020044180016a41186a200441106a41186a29030037030020044180016a41106a200441106a41106a29030037030020044180016a41086a200441106a41086a2903003703002004200429031037038001200441086a2002200441e0006a20044180016a200e200d200441c0006a20032007200141106a108802200428020821022006200429034820062903007c370300200241004721020b02402004280234450d00200428023010010b2000410036020020002002360204200441a0016a24000f0b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000be20702027f027e230041a0016b220a240002400240024020012802182001280228220b28028001470d0041a6b8c1002103412921010c010b200642002006290308220c200b2903707d220d200d200c56200d5072220b1b3703080240200b450d0041cfb8c1002103412321010c010b2001280200220b4100480d01200b41ffffffff07460d012001200b41016a360200024002400240200141046a200310de01220b450d00200b280218450d00200a41186a200b41186a102b200a280218450d01200a41086a41086a200a41186a41086a280200360200200a200a2903183703080c020b200a41003602180b200a41086a20012802102003200141146a2802002802101104000b20012001280200417f6a360200200a413c6a4100360200200a412c6a41b084c300360200200a41186a41086a4200370300200a41cc006a200341086a290000370200200a41d4006a200341106a290000370200200a41dc006a200341186a290000370200200a4208370234200a2001360228200a41e8bdc00036021c200a4100360218200a2003290000370244200a200141286a280200360240200a200141186a28020041016a360230024002402004200584500d00200a200641002001412c6a200320042005200a41186a10e302200a2802002203450d00200a28020421010c010b02400240200a2802102203450d00200a280208210b200a41f4006a200241086a290000370200200a41fc006a200241106a290000370200200a4184016a200241186a290000370200200a200229000037026c200141286a2802002102200a200a41186a360268200b2003200720082009200a41e8006a2002200610e40241ff01714108470d010b200a41e8006a41086a2206200a41186a41086a220b290300370300200a4190016a41086a2202200a41f4006a280200360200200a200a290318370368200a200a29026c37039001200a41386a2802002107200a41186a411c6a2802002103200a413c6a280200210820062002280200360200200a200a29039001370368200b2006280200360200200a200a2903683703182001200a41186a10c702200a2003200841d8006c6a360224200a2003360220200a200736021c200a20033602182001411c6a200a41186a10170240200a28020c450d00200a28020810010b410021030c020b41f2b8c1002103412421010b200a4190016a41086a200a41186a410472220641086a280200360200200a200629020037039001200a41e8006a200a4190016a10cf01200a41e8006a10d0010240200a41386a280200450d00200a41346a28020010010b200a28020c450d00200a28020810010b2000200136020420002003360200200a41a0016a24000f0b10c602000be80805017f017e037f037e047f23004190016b220424000240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d06200241286a2903002105200241346a2802002103200241c4006a2802002106200241d4006a2802002107200241e4006a2802002108200441c8006a20012002280204200241146a2802001083020240024002402004280248450d00200441086a41086a200441c8006a41086a220228020036020020042004290348370308200441c8006a200120032006108302024020042802482203450d0020022802002102200428024c21062004420037035020044200370348200441c8006a20032002411020024110491b10f8021a02402002410f4d0d00200441d0006a29030021092004290348210a02402006450d00200310010b200441c8006a2001200720081083022004280248450d01200441186a41086a200441c8006a41086a28020036020020042004290348370318200141186a22062802002203450d03410021020340200241016a22022003490d000b200320026b21020c040b2006450d00200310010b200428020c450d00200428020810010b2000410536020020044190016a24000f0b410021020b200620023602000240024020012802242202290308220b200b20052005501b2205540d00200241086a2203200b20057d3703002002290310210b200441286a41186a200241186a29030037030020042005370330200420053703282004200b3703382004280208210620042802102107200428021821082004280220210c200441f0006a41186a220d2001280200280200220241c4006a29000037030020044180016a220e2002413c6a290000370300200441f0006a41086a220f200241346a2900003703002004200229002c370370200441c8006a2002200441f0006a200a2009200441286a200620072008200c108a0241012102024020042d00484101460d00200d200441e1006a290000370300200e200441d9006a290000370300200f200441d1006a29000037030020042004290049370370410021020b2003200441286a41086a29030020032903007c3703002002450d010b41012102200428021c450d090c080b200441c8006a41186a200441f0006a41186a290300370300200441c8006a41106a200441f0006a41106a290300370300200441c8006a41086a200441f0006a41086a29030037030020042004290370370348200441c8006a200141106a101e41002102200428021c0d070c080b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b200428021810010b0240200428020c450d00200428020810010b200041003602002000200236020420044190016a24000bbf1103027f027e057f230041c0026b220a2400024020012802182001280228220b28028001470d00200041013a0000200041086a4124360200200041046a41c5b9c100360200200a41c0026a24000f0b200542002005290308220c200b2903787d220d200d200c56200d5072220b1b3703080240200b450d00200041013a0000200041086a4125360200200041046a41e9b9c100360200200a41c0026a24000f0b200a41306a41186a220b4200370300200a41306a41106a220e4200370300200a41306a41086a220f4200370300200a420037033020062007200a41306a100d200a41d8016a41186a200b290300370300200a41d8016a41106a200e290300370300200a41d8016a41086a200f290300370300200a200a2903303703d801200b4200370300200e4200370300200f4200370300200a420037033020082009200a41306a100d200a41a0016a41186a200b290300370300200a41a0016a41106a200e290300370300200a41a0016a41086a200f290300370300200a200a2903303703a001200a410036029802200a420137039002200a4190026a200a41d8016a41201025200a4190026a200a41a0016a41201025200a4190026a2001412c6a221041201025200a280298022111200a280290022112200b4200370300200e4200370300200f4200370300200a420037033020122011200a41306a100d200a41106a41186a200b290300370300200a41106a41106a200e290300370300200a41106a41086a200f290300370300200a200a2903303703100240200a28029402450d00201210010b024002402001280200220b4100480d00200b41ffffffff07460d002001200b41016a360200024002400240200141046a200a41106a10de01220b450d00200b280218450d00200a41306a200b41186a102b200a280230450d01200a41a0016a41086a200a41306a41086a280200360200200a200a2903303703a0010c020b200a41003602300b200a41a0016a2001280210200a41106a200141146a2802002802101104000b20012001280200417f6a360200200a2802a801210b0240200a2802a401450d00200a2802a00110010b0240200b450d00200041013a0000200041086a4117360200200041046a418ebac100360200200a41c0026a24000f0b200a41d4006a4100360200200a41c4006a41b084c300360200200a41306a41086a4200370300200a41e4006a200a41106a41086a290300370200200a41ec006a200a41206a290300370200200a41f4006a200a41106a41186a290300370200200a420837024c200a41e8bdc000360234200a4100360230200a200a29031037025c200a2001360240200a200141286a280200220b360258200a200141186a28020041016a3602480240024002400240024020032004844200510d00200a41086a200541012010200a41106a20032004200a41306a10e3020240200a280208220b450d00200a28020c2101200041013a0000200041086a2001360200200041046a200b3602000c020b200141286a280200210b0b200a410036028801200a420137038001200a41ac016a200241086a290000370200200a41b4016a200241106a290000370200200a41bc016a200241186a290000370200200a20022900003702a401200a200a41306a3602a00102402006200720082009200a4180016a200a41a0016a200b200510e40241ff01714108470d00200a4190016a41086a200a4180016a41086a280200360200200a200a2903800137039001200a2802300d06200a417f360230200a41d8016a41186a2205200a41106a41186a290300370300200a41d8016a41106a220b200a41106a41106a290300370300200a41d8016a41086a220e200a41106a41086a290300370300200a200a2903103703d801200a41a0016a200a41306a410472200a41d8016a10df01200a2802a0014101470d02200a41a0016a41086a2802002105200a41a0016a41106a280200210b200a420037029402200a41e8bdc00036029002200a41d8016a200a4190026a10cb01200a41d8016a10cc014118210e2005200b41306c6a41e8026a220b41186a2105200b280218220f0d030c040b200041013a0000200041086a4126360200200041046a41a5bac100360200200a28028401450d00200a2802800110010b200a41d8016a41086a200a41306a410472220141086a280200360200200a20012902003703d801200a41a0016a200a41d8016a10cf01200a41a0016a10d0010240200a41d0006a280200450d00200a41cc006a28020010010b200a41c0026a24000f0b200a4188026a200a41d4016a280200360200200a41d8016a41286a200a41cc016a290200370300200a41f8016a200a41c4016a2902003703002005200a41bc016a290200370300200b200a41b4016a290200370300200e200a41ac016a290200370300200a200a2902a4013703d801200a4190026a41186a4100360200200a4190026a41106a4200370300200a4190026a41086a4200370300200a4190026a41286a4200370300200a420037039002200a41e8bdc0003602b4024118210e200a41d8016a200a4190026a10e201220b41186a2105200b280218220f450d010b200b411c6a280200450d00200f10010b2005200a29039001370200200541086a200a4190016a41086a280200360200200a200a28023041016a360230200a41a0016a41086a220b200a41306a41086a220f290300370300200a41d8016a41086a2206200a41ac016a280200360200200a200a2903303703a001200a200a2902a4013703d801200a41d0006a2802002107200a41306a411c6a2802002105200a41d4006a2802002108200b2006280200360200200a200a2903d8013703a001200f200b280200360200200a200a2903a0013703302001200a41306a10c702200a2005200841d8006c6a36023c200a2005360238200a2007360234200a20053602302001411c6a200a41306a1017200041003a0000200041196a200a41106a200e6a290300370000200041116a200a41206a290300370000200041096a200a41106a41086a2903003700002000200a290310370001200a41c0026a24000f0b10c602000b108402000bf00102027f027e230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d01200228020421032004200128021c2903104200200241146a2802002202ad420010fc02024020042903084200520d002001280224220542002005290308220620042903007d220720072006562007507222051b37030820050d00200128020c2002102720012802202802082003200128020c22022802002002280208100b2202417e460d0020020d03200141013a00280b20004105360200200441106a24000f0b41ff80c10041f4031042000b41ff80c10041f4031042000b41d08dc200104f000b5e01027f230041106b220424002004200128020041046a10f501200141106a21050240200141146a280200450d00200528020010010b20052004290300370200200541086a200441086a28020036020020004104360200200441106a24000b1600200041003602002000200141086a2802003602040ba70202057f027e230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200141086a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042102200128020421072004200128021c29032042002005ad420010fc0220042903084200520d002001280224220842002008290308220920042903007d220a200a200956200a507222081b37030820080d00200141206a2802002802082002200720066a2005100c2202417e460d0020020d04410421030b20002003360200200441106a24000f0b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41e88dc200104f000b1600200041003602002000200141186a2802003602040ba70202057f027e230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200141186a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042102200128021021072004200128021c29032042002005ad420010fc0220042903084200520d002001280224220842002008290308220920042903007d220a200a200956200a507222081b37030820080d00200141206a2802002802082002200720066a2005100c2202417e460d0020020d04410421030b20002003360200200441106a24000f0b41ff80c10041f4031042000b41ff80c10041f4031042000b41ff80c10041f4031042000b41e88dc200104f000bac0402077f027e230041c0006b2202240002400240024002400240411310002203450d002002421337023420022003360230200241306a41cd85c1004113102520022802302103024002400240024020022802342204200228023822056b41044f0d00200541046a22062005490d0520044101742207200620062007491b22074100480d052004450d01200710002208450d062008200320072004200420074b1b10f802210420031001200421030c020b200541046a21060c020b200710002203450d040b200721040b200320056a2001360000200241306a41086a220542003703002002420037033020032006200241306a1002200241086a20052903003703002002200229033037030002400240200241104188f0c100410041001004417f460d00200220023602102002411036021420024200370338200242003703302002410020024110200241306a41104100100422052005417f461b2205411020054110491b3602182005410f4d0d01200241306a41086a220529030021092002290330210a200241306a200241106a103620022802302206450d0120022002290234370320200020093703082000200a3703002005200241206a41086a2802003602002002200229032037033020002006360210200020022903303702142000411c6a20052802003602002004450d060c050b2000410036021020040d040c050b41eac4c10041331042000b411341011019000b1018000b200741011019000b200310010b200241c0006a24000ba80d03027f017e077f230041f0016b22052400200541086a41086a2206420037030020054200370308419e86c1004119200541086a1002200541f0006a41086a200629030037030020052005290308370370410021060240024002400240024002400240024002400240200541f0006a41104188f0c100410041001004417f460d002005410036028001200541f0006a411020054180016a41044100100441016a41044d0d0102402005280280012206450d00200541086a2006417f6a1093022005280210410d460d0120054180016a200541086a41e80010f8021a200529038001210720054180016a41086a10a00120072001580d01200041f887c10036020420004101360200200041086a41c700360200200210a001200541f0016a24000f0b410021060b2005200641016a360270200541086a41086a2208420037030020054200370308419e86c1004119200541086a100220054180016a41086a22092008290300370300200520052903083703800120054180016a4110200541f0006a4104100320052001370380012009200241d00010f802210a200520043703d801200520033a00e001411a10002202450d022005421a37020c20052002360208200541086a41ce86c100411a102520052802082109024002400240200528020c2202200528021022086b41034b0d00200841046a220b2008490d042002410174220c200b200b200c491b220c4100480d042002450d01200c1000220b450d07200b2009200c20022002200c4b1b10f8021a200910010c020b2009210b2002210c0c010b200c1000220b450d050b200b20086a200636000020054100360210200542013703082005290380012101410810002202450d032005410836020c200541086a41086a22092009280200220941086a36020020052002360208200220096a2001370000200a200541086a101c024002400240024002400240024002400240024002400240024002400240200541e0016a2d000022024101460d0020024102470d01200528020c200541106a2802002202470d03200241016a22092002490d102002410174220d20092009200d491b220d4100480d102002450d082005280208210e200d10002209450d162009200e200d20022002200d4b1b10f8021a200e10010c090b200528020c200541106a2802002202470d01200241016a22092002490d0f2002410174220d20092009200d491b220d4100480d0f2002450d042005280208210e200d10002209450d142009200e200d20022002200d4b1b10f8021a200e10010c050b200528020c200541106a2802002202470d02200241016a22092002490d0e2002410174220d20092009200d491b220d4100480d0e2002450d092005280208210e200d10002209450d152009200e200d20022002200d4b1b10f8021a200e10010c0a0b200528020821090c040b200528020821090c060b200528020821090c080b200d10002209450d0f0b2005200d36020c20052009360208200541106a28020021020b200541106a200241016a360200200920026a41013a00000c060b200d10002209450d0d0b2005200d36020c20052009360208200541106a28020021020b200541106a200241016a360200200920026a41023a00000c030b200d10002209450d0b0b2005200d36020c20052009360208200541106a28020021020b200541106a200241016a360200200920026a41003a00000b200541d8016a29030021010240024002400240200528020c2209200541086a41086a28020022026b41084f0d00200241086a220d2002490d0520094101742202200d200d2002491b22024100480d052009450d012005280208210e20021000220d450d09200d200e20022009200920024b1b10f8021a200e10010c020b2005280208210d0c020b20021000220d450d070b2005200236020c2005200d360208200541106a28020021020b200541086a41086a2209200241086a360200200d20026a20013700002009280200210d200528020c210e200528020821022009420037030020054200370308200b200841046a200541086a1002200541f0006a41086a200929030037030020052005290308370370200541f0006a41102002200d10030240200e450d00200210010b0240200c450d00200b10010b200a10a0012005418c016a200636020020054189016a20033a000020054188016a41013a0000200541043a00800120054180016a10b4012000410036020020002006360204200541f0016a24000f0b41eac4c10041331042000b1018000b411a41011019000b410841011019000b200c41011019000b200241011019000b200d41011019000b200d41011019000b200d41011019000bdd0702077f027e230041e0026b220224000240024002400240024002400240411a10002203450d002002421a3702c401200220033602c001200241c0016a41ce86c100411a102520022802c0012103024002400240024020022802c401220420022802c80122056b41044f0d00200541046a22062005490d0520044101742207200620062007491b22074100480d052004450d01200710002208450d082008200320072004200420074b1b10f802210420031001200421030c020b200541046a21060c020b200710002203450d060b200721040b200320056a2001360000200241c0016a41086a22054200370300200242003703c00120032006200241c0016a1002200241086a2005290300370300200220022903c00137030002400240200241104188f0c100410041001004417f460d002002200236021020024110360214200242003703c0012002410020024110200241c0016a41084100100422052005417f461b22054108200541084922051b36021820050d0520022903c0012109200241c0016a200241106a103820022802c001210520024194026a200241c0016a41047241cc0010f8021a2005410d460d05200241f4006a20024194026a41cc0010f8021a20022005360220200241206a410472200241f4006a41cc0010f8022106200241003a00c00120022802102002280214200241c0016a4101200241186a22052802001004210720052005280200200741016a220741014b6a220136020020074102490d0120022d00c001220741034f0d01200242003703c001200241106a41086a2208410020022802102002280214200241c0016a41082001100422052005417f461b2205410820054108491b20082802006a360200200541074d0d0420022903c001210a20022802202105200241c0016a200641cc0010f8021a20024194026a41066a2206200241206a41066a2d00003a000020024194026a41046a2201200241206a41046a2f00003b010020022002280020360294022005410d460d05200241206a200241c0016a41cc0010f8021a200241f4006a41066a220820062d00003a0000200241f4006a41046a220620012f01003b0100200220022802940236027420002005360208200020093703002000410c6a200241206a41cc0010f8021a200041e0006a20073a0000200041d8006a200a37030020002002280274360061200041e5006a20062f01003b0000200041e7006a20082d00003a00002004450d080c070b2000410d36020820040d060c070b200241206a10a00141eac4c10041331042000b411a41011019000b1018000b200241206a10a0010b41eac4c10041331042000b200741011019000b200310010b200241e0026a24000bb30a04087f017e067f017e230041f0026b2202240002400240024002400240411710002203450d002002421737029c02200220033602980220024198026a41b786c100411710252002280298022104024002400240024002400240200228029c02220520022802a00222036b41084f0d00200341086a22062003490d0320054101742207200620062007491b22074100480d032005450d01200710002208450d072008200420072005200520074b1b10f80221082004100120072105200821040c020b200341086a21060c010b200710002204450d05200721050b200420036a2001370000200241c8016a41086a22034200370300200242003703c80120042006200241c8016a1002200241106a41086a2003290300370300200220022903c801370310024002400240024002400240024002400240200241106a41104188f0c100410041001004417f460d00200242103702242002200241106a360220200241086a200241206a10352002280208450d08200228020c2209ad220142d8007e220a422088a70d0b200aa72203417f4c0d0b2003450d0120031000220b450d0e20090d020c030b20004100360208200042083702002005450d0f0c0e0b4108210b2009450d010b200241c8016a410472210c200241286a21034100210d0340200241003a0098022002280220200228022420024198026a410120032802001004210720032003280200200741016a220741014b6a36020020074102490d040240024020022d0098022207450d0020074101470d0620024198026a200241206a1038200228029802410d460d05200241c8016a20024198026a41d00010f8021a200241003602ec022003410020022802202002280224200241ec026a41042003280200100422072007417f461b2207410420074104491b20032802006a360200200741034d0d0420022802ec02210e20022802c8012108200241fc006a200c41cc0010f8021a20024198026a200241fc006a41cc0010f8021a2008410d460d06200241306a20024198026a41cc0010f8021a20024198026a200241306a41cc0010f8021a2008410e470d010c070b20024198026a200241306a41cc0010f8021a410d21080b200241c8016a20024198026a41cc0010f8021a02402001422088a722072001a7470d00200741016a220f2007490d0820074101742210200f200f2010491bad220a42d8007e2211422088a70d082011a7220f4100480d08024002402007450d00200f10002210450d0b2010200b200f200741d8006c22072007200f4b1b10f8022107200b10012007210b0c010b200f1000220b450d0a0b200142808080807083200a8421010b200b2001422088a741d8006c6a22072008360200200741046a200241c8016a41cc0010f8021a200741d0006a200e36020020014280808080107c2101200d41016a220d2009490d000b0b200b450d04200241c8016a41086a22034200370300200242003703c80120042006200241c8016a100220024198026a41086a2003290300370300200220022903c8013703980220024198026a41101008200020013702042000200b36020020050d0b0c0c0b200241c8016a10280b20024198026a200241fc006a41cc0010f8021a0b20024198026a200241306a41cc0010f8021a0b02402001422088a72202450d00200241d8006c2103200b2102034002402002280200410d460d00200210280b200241d8006a2102200341a87f6a22030d000b0b2001a7450d00200b10010b41eac4c10041331042000b1018000b200f41081019000b102c000b411741011019000b200741011019000b200341081019000b200410010b200241f0026a24000b9d0301077f230041306b22022400024002400240024002400240411310002203450d002002421337022420022003360220200241206a41e886c1004113102520022802202103024002400240024020022802242204200228022822056b41044f0d00200541046a22062005490d0520044101742207200620062007491b22074100480d052004450d01200710002208450d072008200320072004200420074b1b10f802210420031001200421030c020b200541046a21060c020b200710002203450d050b200721040b200320056a2001360000200241206a41086a220542003703002002420037032020032006200241206a1002200241086a2005290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103620022802202205450d0320002002290224370204200020053602002004450d060c050b200041003602082000420137020020040d040c050b411341011019000b1018000b41eac4c10041331042000b200741011019000b200310010b200241306a24000ba707010b7f230041d0006b220124000240024002400240411a10002202450d002001421a37020c20012002360208200141086a41ce86c100411a10252001280208210202400240024002400240200128020c2203200128021022046b41044f0d00200441046a22052004490d0420034101742206200520052006491b22064100480d042003450d01200610002207450d072007200220062003200320064b1b10f802210320021001200321020c020b200441046a21050c020b200610002202450d050b200621030b200220046a2000360000200141c0006a41086a220442003703002001420037034020022005200141c0006a1002200141306a41086a200429030037030020012001290340370330200141306a4110100802402003450d00200210010b411310002202450d022001421337020c20012002360208200141086a41e886c1004113102520012802082106024002400240200128020c2204200128021022026b41034b0d00200241046a22032002490d0320044101742205200320032005491b22054100480d032004450d01200510002203450d072003200620052004200420054b1b10f8021a200610010c020b20062103200421050c010b200510002203450d050b200320026a2000360000200141c0006a41086a22044200370300200142003703402003200241046a200141c0006a1002200141306a41086a200429030037030020012001290340370330200141306a4110100802402005450d00200310010b200141086a2000109502200128020c2108200128020821090240024020012802102202450d0020024105742107200141086a410472210320092102034020032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a29000037000020012000360208411010002204450d022001421037024420012004360240200141c0006a41fb86c10041101025200141306a41086a2204200141c0006a41086a220528020036020020012001290340370330200141086a200141306a1097022004280200210a2001280234210b2001280230210620054200370300200142003703402006200a200141c0006a10022004200529030037030020012001290340370330200141306a411010080240200b450d00200610010b200241206a2102200741606a22070d000b0b02402008450d00200910010b200141d0006a24000f0b411041011019000b1018000b411a41011019000b411341011019000b200641011019000b200541011019000b8d0201047f20002802002001108901024002400240024002400240200141046a2802002202200141086a28020022036b41204f0d00200341206a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d030b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a2000411c6a290000370000200141106a200041146a290000370000200141086a2000410c6a290000370000200120002900043700000f0b1018000b200341011019000b3400200041db9fc10036020420004100360200200041146a410f360200200041106a4184d7c200360200200041086a42093702000b890201057f230041206b2201240002400240411010002202450d002001421037021420012002360210200141106a41fb86c10041101025200141086a220220012802183602002001200129031037030020002001109702200228020021032001280204210420012802002100200141106a41086a220542003703002001420037031020002003200141106a10022002200529030037030020012001290310370300410021020240200141104188f0c100410041001004417f460d00200141003a001020014110200141106a41014100100441016a41014d0d0220012d001021020b02402004450d00200010010b200141206a240020020f0b411041011019000b41eac4c10041331042000b4b00200041ddf5c10036020420004100360200200041206a41063602002000411c6a4188dfc200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b130020004106360204200041e0e3c2003602000bd71b05037f027e057f047e027f230041e0006b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a2203410b4b0d0002400240024020030e0c0008050602090a070b040c01000b2002200141086a10920120004101360200200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b4102210320012d000422044102460d0b4103210320044103470d2d200241186a200141046a220141196a290000370300200241106a200141116a290000370300200241086a200141096a290000370300200220012900013703000c0c0b2002200141086a10930120004105360200200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b200141086a2903004202520d2c20004100360200200041086a4202370300200041106a200141106a290300370300200241e0006a24000f0b200141086a280200417e6a220341044b0d2c024020030e05001b191a18000b41012103200141386a2903002105200141306a29030021062001410c6a2d00004101470d1f0c200b41022103200141086a22042d000022074102460d0f4103210320074103460d0e4104210320074104470d2c20042d000141004721010c100b200141086a2d0000417e6a220841094b0d2c4102210341002109024020080e0a35001d211b242522261c350b2001410c6a28020022094108762107410321030c220b20012d000422034102460d074103210420034103470d2c200241d2006a200141046a220341036a2d00003a0000200241086a200141186a2900003703002002410d6a2001411d6a290000370000200220032f00013b01502002200141106a290000370300200141256a2d00004100472107200141286a280200210a2001410c6a2800002103200141086a280000210b0c080b41022104200141086a28020022034102460d0820034103470d2c410121072001410c6a2d00004101470d0e0c0f0b2002200141086a10940120004106360200200041c0006a200241386a290300370300200041386a200241306a290300370300200041306a200241286a290300370300200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b2002200141086a10950120004107360200200041286a200241206a290300370300200041206a200241186a290300370300200041186a200241106a290300370300200041106a200241086a290300370300200041086a2002290300370300200241e0006a24000f0b20012802044102470d2a2002200141086a102b2000428980808020370300200041086a2002290200370200200041106a200241086a280200360200200241e0006a24000f0b41022104200141086a22032d000022074102460d054103210420074103470d2a200141306a2903002105200141286a2903002106200141386a290300210c200241c0006a2001410c6a102b200241d0006a200141186a102b2002410b6a200241c0006a41086a280200360000200241176a200241d0006a41086a280200360000200220022903403700032002200229035037000f4200210d4200210e0c060b200241d0006a200141086a102b2002410b6a200241d0006a41086a280200360000200220022903503700030b20002002290300370005200020033a0004200020022f00503b00252000410c3602002000410d6a200241086a290300370000200041156a200241106a2903003700002000411d6a200241186a290300370000200041276a200241d2006a2d00003a0000200241e0006a24000f0b200141086a280200210b41d00010002203450d2820032001410c6a280200109101410221040b200020022f01503b0005200020043a0004200020073a0025200020022f01403b0126200041083602002000410c6a2003360200200041086a200b360200200041106a2002290300370200200041286a200a360200200041076a200241d2006a2d00003a0000200041186a200241086a2903003702002000411d6a2002410d6a290000370000200241e0006a24000f0b410121072001410c6a2d00004101470d070c080b200241176a200341186a290000370000200241106a200341116a290000370300200241086a200341096a29000037030020022003290001370300200141c0006a290300210e200141386a290300210c200141c8006a290300210f200141286a3100002106200241d0006a2001412c6a102b200241d0006a41086a3502004220862002290350220d4220888421052006200d4220868421064200210d0b200020022903003700092000410b360200200041c0006a200e370300200041386a200d200c84370300200041306a2005370300200041286a2006370300200041086a20043a0000200041c8006a200f370300200041116a200241086a290300370000200041196a200241106a290300370000200041206a200241176a290000370000200241e0006a24000f0b200141106a29030021050c010b200241d4006a200441066a2f00003b0100200241086a200141206a290000370300200241106a200141286a2d00003a00002002200441026a2800003602502002200141186a290000370300200141106a2900002105200141096a2d000021010b200020013a00092000200228025036010a20004103360200200041086a20033a0000200041106a2005370300200041186a20022903003703002000410e6a200241d4006a2f01003b0100200041206a200241086a290300370300200041286a200241106a290300370300200241e0006a24000f0b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722103200141246a280000210a200141206a280000210b200141186a2900002106200141146a2800002110410021070b200141c8006a290300210c200141c0006a290300210d410321040c020b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722103200141246a280000210a200141206a280000210b200141186a2900002106200141146a2800002110410021070b0b200020033b000d200041023602002000410f6a20034110763a0000200041c8006a200c370300200041c0006a200d370300200041286a2005370200200041246a200a360200200041206a200b360200200041186a2006370200200041146a20103602002000410c6a20073a0000200041086a2004360200200041386a200141386a290300370300200041306a200141306a290300370300200041106a200141106a280000360200200241e0006a24000f0b2001410c6a28020022034108762104410621010c030b200241106a200141206a2903003703002002200141186a2903003703082002200141106a2802003602002001410c6a28020022034108762104200141286a290300210c410421010c080b2001410c6a28020022034108762104410521010c010b2002200141186a2903003703082002200141106a29030037030041032101410021030b0c050b2001410c6a28020022094108762107200141186a2903002106200141206a2802002110200141106a2903002205a7210b2005422088a7210a410621030c180b2001410c6a28020022094108762107410b21030c060b410121092001410c6a2d00004101470d090c0a0b200141286a3500002001412c6a31000042208684210c2001410d6a2f00002001410f6a2d0000411074722104200141246a2800002107200141206a280000210a200141186a290000210d200141146a280000210b410021030b200220073602142002200a3602102002200d3703082002200b3602042002200141106a280000360200410221010b2000410a360200200041386a2005370300200041306a2006370300200041086a2001360200200041106a2002290300370300200041286a200c3703002000410c6a2004410874200341ff017172360200200041186a200241086a290300370300200041206a200241106a290300370300200241e0006a24000f0b2001410c6a28020022094108762107410521030c010b2001410c6a28020022094108762107410921030b0c0f0b200141106a2903002205a7210b2005422088a7210a410721030c0e0b200141106a2903002205a7210b2005422088a7210a410821030c0d0b41002109200141096a2d00004100472111410a21030c0e0b200141286a3500002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722107200141246a2800002104200141206a2800002110200141186a2900002106200141146a280000210a410021090b200141106a280000210b410421030c0b0b41d8ccc200104f000b41a881c300104f000b41c0ccc200104f000b41acd5c200104f000b41a8ccc200104f000b418cabc200104f000b41c4aec300104f000b4180e8c200104f000b4188a8c200104f000b41d00041081019000b0b0b200020113a0009200020022f01003b010a20004104360200200041186a2006370300200041086a20033a0000200041286a2005370200200041246a2004360200200041206a20103602002000410c6a2007410874200941ff017172360200200041106a200aad422086200bad84370300200241e0006a24000bfb0503077f027e057f230041206b22022400024002400240411310002203450d002002421337021420022003360210200241106a41cd85c10041131025200228021021040240024002400240024020022802142205200228021822036b41044f0d00200341046a22062003490d0320054101742207200620062007491b22084100480d032005450d01200810002207450d072007200420082005200520084b1b10f802210520041001200521040c020b200341046a2106200521080c010b200810002204450d050b200420036a20003600002002410036021820024201370310200141086a29030021092001290300210a411010002203450d032003200a37000020032009370008200242908080808002370214200220033602102001280210210b200141186a2802002203200241106a101b024002402003450d002003410574210c200241106a41086a28020021072002280210210d20022802142100200b210e0340200e210302400240024002402000200722056b41204f0d00200541206a22072005490d072000410174220e20072007200e491b220e4100480d07200e1000210f2000450d01200f450d08200f200d200e20002000200e4b1b10f8021a200d10010c020b200541206a21070c020b200f450d060b200f210d200e21000b200341206a210e200d20056a22052003290000370000200541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a290000370000200c41606a220c0d000b200241186a2007360200200220003602142002200d3602100c010b200241186a2802002107200228021421002002280210210d0b200241106a41086a220342003703002002420037031020042006200241106a1002200241086a20032903003703002002200229031037030020024110200d2007100302402000450d00200d10010b02402008450d00200410010b0240200141146a280200450d00200b10010b200241206a24000f0b1018000b200e41011019000b411341011019000b411041011019000b200841011019000bb80704037f027e0c7f037e23004190016b22012400200141f0006a41086a220242003703002001420037037041ddc6c1004115200141f0006a1002200141106a41086a2002290300370300200120012903703703100240024002400240024002400240024002400240200141106a41104188f0c100410041001004417f460d00200142103702242001200141106a360220200141086a200141206a10352001280208450d05200128020c2203ad220442287e2205422088a70d082005a72202417f4c0d082002450d01200210002206450d0920030d020c030b2000410036020020014190016a24000f0b410821062003450d010b200141206a41086a22072802002108200128022421092001280220210a200141f0006a41186a210b200141f0006a41106a210c4100210d0340200b4200370300200c4200370300200141f0006a41086a220e42003703002001420037037020074100200a2009200141f0006a41202008100422022002417f461b2202412020024120491b20086a22083602002002411f4d0d02200141d0006a41186a220f200b290300370300200141d0006a41106a2210200c290300370300200141d0006a41086a2211200e290300370300200120012903703703502001420037037020074100200a2009200141f0006a41082008100422022002417f461b2202410820024108491b20086a2208360200200241074d0d0220012903702105200141306a41186a2202200f290300370300200141306a41106a220f2010290300370300200141306a41086a2210201129030037030020012001290350370330200b2002290300370300200c200f290300370300200e20102903003703002001200129033037037002402004422088a72004a72202470d00200241016a220f2002490d0520024101742210200f200f2010491bad221242287e2213422088a70d052013a7220f4100480d05024002402002450d00200f10002210450d0820102006200f200241286c22022002200f4b1b10f802210220061001200221060c010b200f10002206450d070b20044280808080708320128421040b20062004422088a741286c6a22022001290370370300200e2903002112200c2903002113200b290300211420022005370320200241186a2014370300200241106a2013370300200241086a201237030020044280808080107c2104200d41016a220d2003490d000b0b2006450d01200020043702042000200636020020014190016a24000f0b2004a7450d00200610010b41eac4c10041331042000b1018000b200f41081019000b102c000b200241081019000be90604037f027e0b7f027e230041f0006b22012400200141d0006a41086a220242003703002001420037035041f1a2c1004117200141d0006a1002200141106a41086a2002290300370300200120012903503703100240024002400240024002400240024002400240200141106a41104188f0c100410041001004417f460d00200142103702242001200141106a360220200141086a200141206a10352001280208450d05200128020c2203ad220442287e2205422088a70d082005a72202417f4c0d082002450d01200210002206450d0920030d020c030b20004100360200200141f0006a24000f0b410821062003450d010b200141206a41086a22072802002108200128022421092001280220210a200141d0006a41186a210b200141d0006a41106a210c4100210d03402001420037035020074100200a2009200141d0006a41082008100422022002417f461b2202410820024108491b20086a2208360200200241074d0d0220012903502105200b4200370300200c4200370300200141d0006a41086a220e42003703002001420037035020074100200a2009200141d0006a41202008100422022002417f461b2202412020024120491b20086a22083602002002411f4d0d02200141306a41186a2202200b290300370300200141306a41106a220f200c290300370300200141306a41086a2210200e29030037030020012001290350370330200b2002290300370300200c200f290300370300200e20102903003703002001200129033037035002402004422088a72004a72202470d00200241016a220f2002490d0520024101742210200f200f2010491bad221142287e2212422088a70d052012a7220f4100480d05024002402002450d00200f10002210450d0820102006200f200241286c22022002200f4b1b10f802210220061001200221060c010b200f10002206450d070b20044280808080708320118421040b20062004422088a741286c6a22022005370300200241206a200b290300370300200241186a200c290300370300200241106a200e2903003703002002200129035037030820044280808080107c2104200d41016a220d2003490d000b0b2006450d012000200437020420002006360200200141f0006a24000f0b2004a7450d00200610010b41eac4c10041331042000b1018000b200f41081019000b102c000b200241081019000b930401097f230041206b2201240020002802002102024002400240024002400240024002400240024020002802082200413f4b0d0041012103410110002204450d05200420004102743a00004101210520000d010c020b02402000418080014f0d0041022103410210002204450d06200420004102744101723b00000c010b024020004180808080044f0d0041042103410410002204450d07200420004102744102723600000c010b410110002205450d07200541033a000041052103410510002204450d08200420052d00003a000020051001200420003600010b200041027421062003210503402002280200210702400240024002402003200522006b41044f0d00200041046a22052000490d0620034101742208200520052008491b22084100480d062003450d01200810002209450d072009200420082003200320084b1b10f802210320041001200321040c020b200041046a21050c020b200810002204450d050b200821030b200241046a2102200420006a20073600002006417c6a22060d000b0b200141106a41086a220042003703002001420037031041d9c2c0004112200141106a1002200141086a2000290300370300200120012903103703002001411020042005100302402003450d00200410010b200141206a24000f0b1018000b200841011019000b410141011019000b410241011019000b410441011019000b410141011019000b410541011019000bee0402097f017e230041206b2201240020014100360218200142013703102000280200210220002802082200200141106a101b024002400240024002402000450d002002200041286c6a2103200141106a41086a220428020021002001280214210503400240024002400240200520006b41204f0d00200041206a22062000490d0720054101742207200620062007491b22074100480d072005450d0120012802102108200710002209450d082009200820072005200520074b1b10f8021a200810010c020b200041206a210620012802102109200521070c020b200710002209450d060b20012007360214200120093602100b20042006360200200920006a220041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a29000037000020002002290000370000200241206a290300210a0240024002400240200720066b41084f0d00200641086a22002006490d0720074101742205200020002005491b22054100480d072005100021082007450d012008450d092008200920052007200720054b1b10f8021a200910010c020b200641086a210020072105200921080c020b2008450d070b20012005360214200120083602100b20042000360200200820066a200a3700002003200241286a2202470d000c020b0b200141186a280200210020012802142105200128021021080b200141106a41086a220242003703002001420037031041ddc6c1004115200141106a1002200141086a2002290300370300200120012903103703002001411020082000100302402005450d00200810010b200141206a24000f0b1018000b200741011019000b200541011019000bea0403057f027e037f230041206b2201240020014100360218200142013703102000280200210220002802082200200141106a101b024002400240024002402000450d002002200041306c6a2103200141106a41086a280200210420012802102105200128021421000340200241086a2903002106200229030021070240024002400240200020046b41104f0d00200441106a22082004490d0720004101742209200820082009491b22094100480d0720091000210a2000450d01200a450d08200a200520092000200020094b1b10f8021a200510010c020b200441106a21080c020b200a450d060b200a2105200921000b200520046a22042006370008200420073700000240024002400240200020086b41204f0d00200841206a22042008490d0720004101742209200420042009491b22094100480d0720091000210a2000450d01200a450d09200a200520092000200020094b1b10f8021a200510010c020b200841206a21040c020b200a450d070b200a2105200921000b200520086a220841186a200241286a290000370000200841106a200241206a290000370000200841086a200241186a2900003700002008200241106a290000370000200241306a22022003470d000b200141186a200436020020012000360214200120053602100c010b200141186a280200210420012802142100200128021021050b200141106a41086a220242003703002001420037031041eec7c1004113200141106a1002200141086a2002290300370300200120012903103703002001411020052004100302402000450d00200510010b200141206a24000f0b1018000b200941011019000b200941011019000b8207010a7f230041206b2203240020034100360218200342013703102002280200210402400240410410002205450d0020034284808080c000370214200320053602102005200436000020022802042106410810002204450d0120042005280000360000200510012003428880808080013702142004200636000420032004360210200241086a2802002105200241106a2802002204200341106a101b02400240024002402004450d0020044105742107200341106a41086a220828020021042003280214210903400240024002400240200920046b41204f0d00200441206a22062004490d062009410174220a20062006200a491b220b4100480d062009450d012003280210210c200b1000220a450d07200a200c200b20092009200b4b1b10f8021a200c10010c020b200441206a21062003280210210a0c020b200b1000220a450d050b2003200b3602142003200a360210200b21090b20082006360200200a20046a220441086a200541086a290000370000200441106a200541106a290000370000200441186a200541186a2900003700002004200529000037000020062104200541206a2105200741606a22070d000b0b200241146a28020021052002411c6a2802002204200341106a101b024002402004450d00200441057421074100200341106a41086a220828020022046b21092003280214210603400240024002400240200620096a41204f0d00200441206a220a2004490d072006410174220b200a200a200b491b220b4100480d072006450d012003280210210c200b1000220a450d09200a200c200b20062006200b4b1b10f8021a200c10010c020b2003280210210a0c020b200b1000220a450d070b2003200b3602142003200a360210200b21060b2008200441206a220b360200200a20046a220441086a200541086a290000370000200441106a200541106a290000370000200441186a200541186a29000037000020042005290000370000200941606a2109200b2104200541206a2105200741606a22070d000c020b0b200341186a280200210b200328021421062003280210210a0b200341106a41086a220542003703002003420037031020002001200341106a1002200341086a20052903003703002003200329031037030020034110200a200b100302402006450d00200a10010b200341206a24000f0b1018000b200b41011019000b200b41011019000b410441011019000b410841011019000b7501027f230041206b220324000240410410002204450d0020042002360000200341106a41086a220242003703002003420037031020002001200341106a1002200341086a2002290300370300200320032903103703002003411020044104100320041001200341206a24000f0b410441011019000bf00403057f017e047f230041206b2201240020014100360218200142013703102000280200210220002802082200200141106a101b024002400240024002402000450d002002200041286c6a2103200141106a41086a22042802002100200128021421050340200229030021060240024002400240200520006b41084f0d00200041086a22072000490d0720054101742208200720072008491b22084100480d072005450d012001280210210920081000220a450d08200a200920082005200520084b1b10f8021a200910010c020b200041086a21072001280210210a200521080c020b20081000220a450d060b200120083602142001200a3602100b20042007360200200a20006a20063700000240024002400240200820076b41204f0d00200741206a22002007490d0720084101742205200020002005491b22054100480d072005100021092008450d012009450d092009200a20052008200820054b1b10f8021a200a10010c020b200741206a210020082105200a21090c020b2009450d070b20012005360214200120093602100b20042000360200200920076a220741086a200241106a290000370000200741106a200241186a290000370000200741186a200241206a2900003700002007200241086a290000370000200241286a22022003470d000c020b0b200141186a280200210020012802142105200128021021090b200141106a41086a220242003703002001420037031041f1a2c1004117200141106a1002200141086a2002290300370300200120012903103703002001411020092000100302402005450d00200910010b200141206a24000f0b1018000b200841011019000b200541011019000bf50104017f017e017f017e230041206b2203240042002104200341086a22054200370300200342003703002001200220031002200341106a41086a200529030037030020032003290300370310024002400240200341106a41104188f0c100410041001004417f460d0020034200370300200341106a4110200341084100100441016a41084d0d0220032903002106200341086a22054200370300200342003703002001200220031002200341106a41086a200529030037030020032003290300370310200341106a41101008420121040c010b0b2000200437030020002006370308200341206a24000f0b41eac4c10041331042000be00101037f230041206b22022400200241086a22034200370300200242003703002000200120021002200241106a41086a20032903003703002002200229030037031002400240200241106a41104188f0c100410041001004417f460d00200241003a0000200241106a4110200241014100100441016a41014d0d0120022d00002103200241086a22044200370300200242003703002000200120021002200241106a41086a200429030037030020022002290300370310200241106a41101008200241206a240020030f0b200241206a240041020f0b41eac4c10041331042000bc504020d7f017e230041c0006b22032400200128020022042001280208220541047422066a2107200128020421080240024002400240024002402005450d00200341306a41017221094100210a200341306a41026a210b200341206a410172220c41076a210d0340200b2004200a6a220141036a2d00003a00002003200141016a2f00003b013020012d0000220e41ac01460d022003410c6a41026a220f200b2d00003a0000200320032f01303b010c200141046a2902002110200341306a410c6a2001410c6a280200360200200920032f010c3b0000200941026a200f2d00003a00002003200e3a003020032010370234200341206a200341306a200210a9022003200c2900003703102003200d29000037001720032d0020220e411a470d052006200a41106a220a470d000c040b0b200422012007470d010c020b200141106a22012007460d010b03400240024020012d0000220a4109460d00200a41ac01470d010c030b200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a22012007470d000b0b02402008450d00200410010b2000411a3a00000c010b200020032903103700012000200e3a0000200041086a20032900173700000240200541047441706a200a460d00200141186a2101034002400240200141786a220a2d0000220b4109460d00200b41ac01470d010c030b200128020041ffffffff0371450d002001417c6a28020010010b200141106a2101200a41106a2007470d000b0b2008450d0020041001200341c0006a24000f0b200341c0006a24000be84903057f017e027f230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220441aa014b0d00024020040eab0100020304057576777806070879090a0b7a0c0d0e0f1011127b7c13147d7e7f15161780011881018201191a1b1c83011d1e1f840120212223850186012487018801252689018a012728292a2b2c8b018c012d8d018e018f012e90012f910130313233920193013494019501960135363738393a97013b3c3d980199019a013e3f409b0141424344454647489c01499d014a9e019f014ba001a1014c4d4e4fa201505152a3015354a401a50155565758595a5b5ca601a7015da8015e5fa901aa016061ab0162636465666768696a6b6c6d6e6f7071727374000b200341013a0008200241046a200341086a410110250cab010b200341003a0008200241046a200341086a410110250caa010b20012d00012104200341023a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca9010b20012d00012104200341033a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca8010b20012d00012104200341043a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca7010b200341053a0008200241046a200341086a410110250ca6010b2003410f3a0008200241046a200341086a410110250ca5010b200141046a2802002104200341103a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca5010b0b200141046a280200210420012d00012106200341113a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000b200320063a00082005200341086a410110250ca3010b2003411b3a0008200241046a200341086a410110250ca2010b200141046a2802002104200341203a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca2010b0b200141046a2802002104200341213a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca1010b0b200141046a2802002104200341233a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca0010b0b200141046a2802002104200341243a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c9f010b0b200141086a2802002104200141046a2802002105200341283a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9e010b0b200141086a2802002104200141046a2802002105200341293a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9d010b0b200141086a2802002104200141046a28020021052003412a3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9c010b0b200141086a2802002104200141046a28020021052003412b3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9b010b0b200141086a2802002104200141046a28020021052003412c3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9a010b0b200141086a2802002104200141046a28020021052003412f3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c99010b0b200141086a2802002104200141046a2802002105200341303a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c98010b0b200141086a2802002104200141046a2802002105200341343a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c97010b0b200141086a2802002104200141046a2802002105200341353a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c96010b0b200141086a2802002104200141046a2802002105200341363a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c95010b0b200141086a2802002104200141046a2802002105200341383a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c94010b0b200141086a2802002104200141046a28020021052003413b3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c93010b0b200141086a2802002104200141046a28020021052003413c3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c92010b0b200141086a2802002104200141046a28020021052003413d3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c91010b0b200141086a2802002104200141046a28020021052003413e3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c90010b0b20012d00012104200341c0003a0008200241046a2202200341086a41011025200320043a00082002200341086a410110250c8e010b200141046a2802002106200341c1003a0008200241046a2207200341086a410110252003200641ff00713a0008024020064107752204200641c00071220272452004417f4720024572734101470d00034020032006418001723a00082007200341086a410110252003200441ff00713a0008200441c000712102200421062004410775220521042005200272452005417f4720024572470d000b0b2007200341086a410110250c8d010b200141086a2903002108200341c2003a0008200241046a2205200341086a4101102520032008a7220441ff00713a000802402008420787220850200441c00071452202712008427f52200272734101470d00034020032004418001723a00082005200341086a4101102520032008a7220441ff00713a00082008420787220850200441c00071452202712008427f52200272470d000b0b2005200341086a410110250c8c010b200141086a2903002108200341c4003a0008200241046a2204200341086a41011025200320083703082004200341086a410810250c8b010b200341c5003a0008200241046a200341086a410110250c8a010b200341c6003a0008200241046a200341086a410110250c89010b200341c7003a0008200241046a200341086a410110250c88010b200341ca003a0008200241046a200341086a410110250c87010b200341cd003a0008200241046a200341086a410110250c86010b200341ce003a0008200241046a200341086a410110250c85010b200341d1003a0008200241046a200341086a410110250c84010b200341d2003a0008200241046a200341086a410110250c83010b200341d3003a0008200241046a200341086a410110250c82010b200341d4003a0008200241046a200341086a410110250c81010b200341d5003a0008200241046a200341086a410110250c80010b200341d6003a0008200241046a200341086a410110250c7f0b200341d9003a0008200241046a200341086a410110250c7e0b200341dd003a0008200241046a200341086a410110250c7d0b200341df003a0008200241046a200341086a410110250c7c0b200341e1003a0008200241046a200341086a410110250c7b0b200341e2003a0008200241046a200341086a410110250c7a0b200341e3003a0008200241046a200341086a410110250c790b200341e4003a0008200241046a200341086a410110250c780b200341e7003a0008200241046a200341086a410110250c770b200341eb003a0008200241046a200341086a410110250c760b200341ec003a0008200241046a200341086a410110250c750b200341ed003a0008200241046a200341086a410110250c740b200341ee003a0008200241046a200341086a410110250c730b200341ef003a0008200241046a200341086a410110250c720b200341f0003a0008200241046a200341086a410110250c710b200341f2003a0008200241046a200341086a410110250c700b200341f3003a0008200241046a200341086a410110250c6f0b200341f4003a0008200241046a200341086a410110250c6e0b200341f8003a0008200241046a200341086a410110250c6d0b200341f9003a0008200241046a200341086a410110250c6c0b200341fa003a0008200241046a200341086a410110250c6b0b200341fc003a0008200241046a200341086a410110250c6a0b200341fd003a0008200241046a200341086a410110250c690b200341fe003a0008200241046a200341086a410110250c680b200341ff003a0008200241046a200341086a410110250c670b20034180013a0008200241046a200341086a410110250c660b20034181013a0008200241046a200341086a410110250c650b20034182013a0008200241046a200341086a410110250c640b20034183013a0008200241046a200341086a410110250c630b20034185013a0008200241046a200341086a410110250c620b20034187013a0008200241046a200341086a410110250c610b2003418a013a0008200241046a200341086a410110250c600b2003418d013a0008200241046a200341086a410110250c5f0b2003418e013a0008200241046a200341086a410110250c5e0b2003418f013a0008200241046a200341086a410110250c5d0b20034190013a0008200241046a200341086a410110250c5c0b20034192013a0008200241046a200341086a410110250c5b0b20034193013a0008200241046a200341086a410110250c5a0b20034194013a0008200241046a200341086a410110250c590b20034196013a0008200241046a200341086a410110250c580b20034197013a0008200241046a200341086a410110250c570b2003419a013a0008200241046a200341086a410110250c560b2003419b013a0008200241046a200341086a410110250c550b2003419c013a0008200241046a200341086a410110250c540b2003419d013a0008200241046a200341086a410110250c530b2003419e013a0008200241046a200341086a410110250c520b2003419f013a0008200241046a200341086a410110250c510b200341a0013a0008200241046a200341086a410110250c500b200341a1013a0008200241046a200341086a410110250c4f0b200341a4013a0008200241046a200341086a410110250c4e0b200341a6013a0008200241046a200341086a410110250c4d0b200341a7013a0008200241046a200341086a410110250c4c0b200341aa013a0008200241046a200341086a410110250c4b0b200341ab013a0008200241046a200341086a410110250c4a0b200341ad013a0008200241046a200341086a410110250c490b200341ae013a0008200241046a200341086a410110250c480b200341af013a0008200241046a200341086a410110250c470b200341b0013a0008200241046a200341086a410110250c460b200341b1013a0008200241046a200341086a410110250c450b200341b2013a0008200241046a200341086a410110250c440b200341b3013a0008200241046a200341086a410110250c430b200341b4013a0008200241046a200341086a410110250c420b200341b5013a0008200241046a200341086a410110250c410b200341b6013a0008200241046a200341086a410110250c400b200341b7013a0008200241046a200341086a410110250c3f0b200341b8013a0008200241046a200341086a410110250c3e0b200341b9013a0008200241046a200341086a410110250c3d0b200341ba013a0008200241046a200341086a410110250c3c0b200341bb013a0008200241046a200341086a410110250c3b0b200341bc013a0008200241046a200341086a410110250c3a0b200341bd013a0008200241046a200341086a410110250c390b200341be013a0008200241046a200341086a410110250c380b200341bf013a0008200241046a200341086a410110250c370b2003410b3a0008200241046a200341086a410110250c360b200141046a28020021042003410c3a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c360b0b200141046a28020021042003410d3a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c350b0b2001410c6a2802002105200141086a2802002109200141046a280200210a2003410e3a0008200241046a2202200341086a41011025200341003a00082009210103402003200141800172200141ff0071200141077622041b3a00082002200341086a410110252004210120040d000b2003200a200a20094102746a102e02402003280200220620032802042207460d00034020062802002101200341003a000803402003200141800172200141ff0071200141077622041b3a00082002200341086a410110252004210120040d000b200641046a22062007470d000b0b200341003a000803402003200541800172200541ff0071200541077622011b3a00082002200341086a410110252001210520010d000b0240200941ffffffff0371450d00200a10010b2000411a3a0000200341106a24000f0b2003411a3a0008200241046a200341086a410110250c320b200141046a2802002104200341223a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c320b0b200141086a2802002104200141046a28020021052003412d3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c310b0b200141086a2802002104200141046a28020021052003412e3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c300b0b200141086a2802002104200141046a2802002105200341313a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2f0b0b200141086a2802002104200141046a2802002105200341323a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2e0b0b200141086a2802002104200141046a2802002105200341333a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2d0b0b200141086a2802002104200141046a2802002105200341373a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2c0b0b200141086a2802002104200141046a2802002105200341393a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2b0b0b200141086a2802002104200141046a28020021052003413a3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2a0b0b20012d000121042003413f3a0008200241046a2202200341086a41011025200320043a00082002200341086a410110250c280b200141046a2802002104200341c3003a0008200241046a2202200341086a41011025200320043602082002200341086a410410250c270b200341c8003a0008200241046a200341086a410110250c260b200341c9003a0008200241046a200341086a410110250c250b200341cb003a0008200241046a200341086a410110250c240b200341cc003a0008200241046a200341086a410110250c230b200341cf003a0008200241046a200341086a410110250c220b200341d0003a0008200241046a200341086a410110250c210b200341d7003a0008200241046a200341086a410110250c200b200341d8003a0008200241046a200341086a410110250c1f0b200341da003a0008200241046a200341086a410110250c1e0b200341db003a0008200241046a200341086a410110250c1d0b200341dc003a0008200241046a200341086a410110250c1c0b200341de003a0008200241046a200341086a410110250c1b0b200341e0003a0008200241046a200341086a410110250c1a0b200341e5003a0008200241046a200341086a410110250c190b200341e6003a0008200241046a200341086a410110250c180b200341e8003a0008200241046a200341086a410110250c170b200341e9003a0008200241046a200341086a410110250c160b200341ea003a0008200241046a200341086a410110250c150b200341f1003a0008200241046a200341086a410110250c140b200341f5003a0008200241046a200341086a410110250c130b200341f6003a0008200241046a200341086a410110250c120b200341f7003a0008200241046a200341086a410110250c110b200341fb003a0008200241046a200341086a410110250c100b20034184013a0008200241046a200341086a410110250c0f0b20034186013a0008200241046a200341086a410110250c0e0b20034188013a0008200241046a200341086a410110250c0d0b20034189013a0008200241046a200341086a410110250c0c0b2003418b013a0008200241046a200341086a410110250c0b0b2003418c013a0008200241046a200341086a410110250c0a0b20034191013a0008200241046a200341086a410110250c090b20034195013a0008200241046a200341086a410110250c080b20034198013a0008200241046a200341086a410110250c070b20034199013a0008200241046a200341086a410110250c060b200341a2013a0008200241046a200341086a410110250c050b200341a3013a0008200241046a200341086a410110250c040b200341a5013a0008200241046a200341086a410110250c030b200341a8013a0008200241046a200341086a410110250c020b200341a9013a0008200241046a200341086a410110250c010b200341ac013a0008200241046a200341086a410110250b2000411a3a0000024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200341106a24000bef03030a7f017e017f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a200110ab0220022802184101460d01200220032900003703082002200429000037000f200241186a41086a2d0000210a2002200229000f37001f20022002290308370318024020072008470d00200741016a220b2007490d032005200b200b2005491b2208ad420486220c422088a70d03200ca7220b4100480d0302402007450d00200b1000220d450d05200d2009200b20062006200b4b1b10f802210b20091001200b21090c010b200b10002209450d040b200920066a220b200a3a0000200b41086a200229001f370000200b41016a2002290318370000200541026a2105200641106a2106200741016a2107200a41ff01714106470d000b20002009360204200041003602002000410c6a2007360200200041086a2008360200200241306a24000f0b2000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d00200741086a28020041ffffffff0371450d00200741046a28020010010b200741106a2107200641706a22060d000b0b02402008450d00200910010b200241306a24000f0b1018000b200b41081019000bdf5103067f017e037f230041e0006b22022400024020012802082203200128020c2204470d00200241013a0040200241dc006a4101360200200241c8006a410c6a41013602002002410f360234200241e0c3c1003602502002410136024c200241b08fc2003602482002200241c0006a3602302002200241306a360258200241086a200241c8006a104d200241d3006a200241106a2802003600002002200229030837004b2002200241cf006a29000037001f20022002290048370318200041053a000420004101360200200020022903183700052000410c6a200229001f370000200241e0006a24000f0b200441016a2105024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004417f460d0020032005490d012001280200220620046a2d000021072001410c6a20053602000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020070ec001ac02ac0200840124ac02aa01aa01aa01aa01aa01a801a501a701a101200b11aa01aa01aa01aa01aa01aa01aa01aa01a60103aa01aa01aa01aa0112189801511aaa01aa01aa0121520533069f0186016f238f019e01a40132080d8801379b01a20104013841714970548b010209441476783f8101752226778701070c252c1016920194011f96019a01a3015ba0011599015e1b5a0f9c019d011d900174720a0e42452813950119602f91018e01890129173497013a27644b5565624a7c407b2e8a0185012b8c0193011c463e2d8d016e3b1e7d5f487982012a3130363d6d5c6c80017f3583014e4f7e7366617a695d39533c674c436a4d6b5768634756505859ac020b20032005470dc301200241013a002f200241dc006a4101360200200241d4006a41013602002002410f360244200241e0c3c1003602502002410136024c200241b08fc20036024820022002412f6a3602402002200241c0006a360258200241306a200241c8006a104d200241d2006a200241386a2802003601002002200229033037014a2002200241ce006a29010037011e20022002290148370318410521010cf2010b200241186a200110ac0220022802184101470da9012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200320056b41084f0da901200241013a0030200241dc006a4101360200200241d4006a41013602002002410f36020c200241e0c3c1003602502002410136024c200241b08fc2003602482002200241306a3602082002200241086a360258200241186a200241c8006a104d20022903182108200041106a2002280220360200200041086a200837020020004281808080d000370300200241e0006a24000f0b410e21070ca5010b200241186a200110ac0220022802184101470da8012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470da8012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470da8012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b413d21070ca1010b200241186a200110ac0220022802184101470da7012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b413121070c9f010b41d70021070c9e010b200241c8006a200110ac0220022802484101470da5012000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b413e21070c9c010b200241186a200110ac0220022802184101470da4012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41d80021070c9a010b41d00021070c99010b41c10021070c98010b200241c8006a200110ac0220022802484101470da1012000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200241c8006a200110ac0220022802484101470da1012000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b41dc0021070c95010b413321070c94010b41cb0021070c93010b41c20021070c92010b41e50021070c91010b200241c8006a200110ac0220022802484101470d9c012000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b41de0021070c8f010b200241c8006a200110ac0220022802484101470d9b012000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b41ce0021070c8d010b41f90021070c8c010b41d30021070c8b010b41800121070c8a010b41c50021070c89010b410a21070c88010b200241186a200110ac0220022802184101470d95012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b413921070c86010b200241186a200110ac0220022802184101470d94012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b20032005470d9401200241013a002f200241dc006a4101360200200241d4006a41013602002002410f360244200241e0c3c1003602502002410136024c200241b08fc20036024820022002412f6a3602402002200241c0006a360258200241306a200241c8006a104d200241d2006a200241386a2802003601002002200229033037014a2002200241ce006a29010037011e20022002290148370318410521010cca010b413f21070c83010b413a21070c82010b41e90021070c81010b41db0021070c80010b41e40021070c7f0b41860121070c7e0b41f60021070c7d0b41c00021070c7c0b41fc0021070c7b0b41f30021070c7a0b41e00021070c790b41880121070c780b41870121070c770b200241186a200110ac0220022802184101470d87012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470d87012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41e60021070c740b41900121070c730b41890121070c720b200241186a200110ac0220022802184101470d84012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470d84012000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b419b0121070c6f0b41e80021070c6e0b41ff0021070c6d0b419d0121070c6c0b418a0121070c6b0b41fb0021070c6a0b413621070c690b41f10021070c680b200241186a200110ac0220022802184101470d7c2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41d90021070c660b41a00121070c650b413221070c640b41da0021070c630b41fa0021070c620b41a70121070c610b41830121070c600b20032005470d75200241013a0040200241dc006a4101360200200241c8006a410c6a41013602002002410f360234200241e0c3c1003602502002410136024c200241b08fc2003602482002200241c0006a3602302002200241306a360258200241086a200241c8006a104d200241d3006a200241106a2802003600002002200229030837004b2002200241cf006a29000037001f20022002290048370318200041053a000420004101360200200020022903183700052000410c6a200229001f370000200241e0006a24000f0b41ef0021070c5e0b41eb0021070c5d0b419f0121070c5c0b41a20121070c5b0b41920121070c5a0b41930121070c590b41a90121070c580b200241c8006a200110ac0220022802484101470d6e2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470d6e2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b419c0121070c550b42002108410021042001410c6a21090340410e210a2004413f4b0dac0120032005460d7f2005417f460dbc012003200541016a2201490dbd01200620056a2d0000210720092001360200200741ff0071220bad2004413f71ad862008842108200441076a21042001210520074118744118752201417f4c0d000b200141c0007121072004413f4b0da1012007450da1012008427f2004413f71ad86842108412e21070cd5010b41ec0021070c530b41a80121070c520b41a40121070c510b41aa0121070c500b41ab0121070c4f0b41cf0021070c4e0b41c90021070c4d0b418c0121070c4c0b419a0121070c4b0b41cd0021070c4a0b41820121070c490b41df0021070c480b41970121070c470b41ee0021070c460b41a60121070c450b41ea0021070c440b41ed0021070c430b41960121070c420b419e0121070c410b41a50121070c400b41990121070c3f0b41a10121070c3e0b41a30121070c3d0b418d0121070c3c0b418b0121070c3b0b41fe0021070c3a0b200241186a200110ac0220022802184101470d522000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b2001410c6a210b410021014100210a0340410d21092001411f4b0db90120032005460d642005417f460da2012003200541016a2204490da301200620056a2d00002107200b2004360200200741ff00712001411f7174200a72210a200141076a210120042105200741187441187522044100480d000b200441c0007121072001411f4b0d86012007450d8601200a417f2001411f717472210a412d21070cba010b20032005470d51200241013a0040200241dc006a4101360200200241c8006a410c6a41013602002002410f360234200241e0c3c1003602502002410136024c200241b08fc2003602482002200241c0006a3602302002200241306a360258200241086a200241c8006a104d200241d3006a200241106a2802003600002002200229030837004b2002200241cf006a29000037001f20022002290048370318200041053a000420004101360200200020022903183700052000410c6a200229001f370000200241e0006a24000f0b41d60021070c360b41950121070c350b41d50021070c340b413821070c330b413421070c320b413b21070c310b413521070c300b41840121070c2f0b41980121070c2e0b41f20021070c2d0b41f00021070c2c0b41810121070c2b0b41940121070c2a0b418f0121070c290b418e0121070c280b413721070c270b41850121070c260b41910121070c250b20032005470d40200241013a002f200241dc006a4101360200200241d4006a41013602002002410f360244200241e0c3c1003602502002410136024c200241b08fc20036024820022002412f6a3602402002200241c0006a360258200241306a200241c8006a104d200241d2006a200241386a2802003601002002200229033037014a2002200241ce006a29010037011e20022002290148370318410521010c700b41f50021070c230b200241186a200110ac0220022802184101470d3f2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b413c21070c210b200241186a200110ac0220022802184101470d3e2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41e30021070c1f0b41f40021070c1e0b200320056b41044f0d3c200241013a0030200241dc006a4101360200200241d4006a41013602002002410f36020c200241e0c3c1003602502002410136024c200241b08fc2003602482002200241306a3602082002200241086a360258200241186a200241c8006a104d20004281808080d000370300200041086a2002290218370200200041106a200241186a41086a280200360200200241e0006a24000f0b41f70021070c1c0b41fd0021070c1b0b41e20021070c1a0b200241186a200110ac0220022802184101470d392000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41d40021070c180b41e10021070c170b41c30021070c160b41f80021070c150b41c40021070c140b41dd0021070c130b41c60021070c120b41e70021070c110b200241c8006a200110ac0220022802484101470d312000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b41cc0021070c0f0b41c70021070c0e0b200241186a200110ac0220022802184101470d2f2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41d10021070c0c0b41d20021070c0b0b200241186a200110ac0220022802184101470d2d2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470d2d2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41ca0021070c080b200241c8006a200110ad0220022802484101470d2c200041013602002000200241c8006a41047222012902003702042000410c6a200141086a290200370200200241e0006a24000f0b200241186a200110ac0220022802184101470d2c2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b41c80021070c050b200241186a200110ac0220022802184101470d2b2000200229021c370204200041013602002000410c6a200241186a410c6a290200370200200241e0006a24000f0b200241c8006a200110ac0220022802484101470d2b2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b410d21070c020b200241c8006a200110ac0220022802484101470d2a2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b410621070b0c80010b2000410b3a000420004101360200200041056a20073a0000200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d292000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200441096a2104200541784f0d6720032004490d68200620056a29000021082001410c6a2004360200413021070c7d0b200228021c210a200241c8006a200110ac0220022802484101470d282000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d282000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d282000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d282000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228024c210a410b21070c790b200228021c210a200241c8006a200110ac0220022802484101470d272000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200141086a28020022072001410c6a2802002204470d27200241013a0040200241dc006a4101360200200241c8006a410c6a41013602002002410f360234200241e0c3c1003602502002410136024c200241b08fc2003602482002200241c0006a3602302002200241306a360258200241086a200241c8006a104d200241d3006a200241086a41086a2802003600002002200229030837004b2002200241cf006a29000037001f20022002290048370318200041053a000420004101360200200020022903183700052000410c6a200229001f370000200241e0006a24000f0b200228024c210a410f21070c760b200228024c210a411021070c750b200228024c210a411321070c740b200228021c210a200241c8006a200110ac0220022802484101470d242000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d242000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200441026a21072005417f460d5c20032007490d5d200620056a2c000021042001410c6a20073602004100210920044100480d34200441017441807f71200472220441ff0171220741847e6a220141034b0d3e024020010e04004e4c4d000b41032109410421070c720b200228021c210a200241c8006a200110ac0220022802484101470d232000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d232000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d232000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d232000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d232000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200441026a21042005417f460d5820032004490d59200620056a2d000021072001410c6a20043602002007450d30200041153a000420004101360200200041056a20073a0000200241e0006a24000f0b200228024c210a411221070c6a0b200228021c210a200241c8006a200110ac0220022802484101470d212000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d212000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200441026a21042005417f460d5620032004490d57200620056a2d000021072001410c6a20043602002007450d2d200041153a000420004101360200200041056a20073a0000200241e0006a24000f0b200441026a21072005417f460d5720032007490d58200620056a2c000021042001410c6a20073602004100210920044100480d2d200441017441807f71200472220441ff0171220741847e6a220141034b0d34024020010e0400464445000b41032109410221070c670b200441026a21072005417f460d5820032007490d59200620056a2c000021042001410c6a20073602004100210920044100480d2e200441017441807f71200472220441ff0171220741847e6a220141034b0d34024020010e0400484647000b41032109410321070c660b200228021c210a200241c8006a200110ac0220022802484101470d1e2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d1e2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200441056a21042005417c4f0d5720032004490d58200620056a280000210a2001410c6a2004360200412f21070c620b200228021c210a200241c8006a200110ac0220022802484101470d1d2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228024c210a411121070c600b200228021c210a200241c8006a200110ac0220022802484101470d1c2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d1c2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d1c2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200241d4006a2802002107200241d0006a28020021052002200228024c22043602202002200536021c200220043602182002200420074102746a360224200241086a200241186a104320022802082105200228020c220720022802102204470d1c2005210a200721040c2f0b200228021c210a200241c8006a200110ac0220022802484101470d1c2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228021c210a200241c8006a200110ac0220022802484101470d1c2000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200241e0006a24000f0b200228024c210a410721070c590b200228024c210a410821070c580b200241013a0040200241dc006a4101360200200241d4006a41013602002002410f36020c200241e0c3c1003602502002410136024c200241b08fc2003602482002200241c0006a3602082002200241086a360258200241186a200241c8006a104d20022802202101200229031821084105210a0c2d0b200241013a0030200241dc006a4101360200200241d4006a41013602002002410f36020c200241e0c3c1003602502002410136024c200241b08fc2003602482002200241306a3602082002200241086a360258200241186a200241c8006a104d410521090c540b200235024c2108412821070c550b200235024c2108412721070c540b200235024c2108411621070c530b200235024c2108411821070c520b200235024c2108412121070c510b200235024c2108412221070c500b200441016a21052004417f460d4620072005490d47200228024c210a200128020020046a2d00002104410c21072001410c6a20053602002004450d1f200041163a000420004101360200200041056a20043a0000200241e0006a24000f0b200235024c2108411421070c4e0b200235024c2108411c21070c4d0b200235024c2108412021070c4c0b200235024c2108411721070c4b0b200235024c2108412421070c4a0b200235024c2108412921070c490b200235024c2108412a21070c480b200235024c2108411521070c470b200235024c2108411b21070c460b200235024c2108411a21070c450b200235024c2108412321070c440b200235024c2108411d21070c430b200235024c2108412521070c420b200235024c2108411e21070c410b200235024c2108411921070c400b20072004490d382004450d10200441027422031000220a450d39200a2005200320074102742207200720034b1b10f8021a0c110b200235024c2108412621070c3e0b200235024c2108411f21070c3d0b411821010b2002200229011e37010e200220022903183703080c380b412c2107410021090c3b0b412b2107410021090c3a0b411821010b2002200229011e37010e200220022903183703080c330b411821010b2002200229011e37010e200220022903183703080c300b200441c000490d082007450d08200b41ff00470d090c0b0b20014120490d0b2007450d0b2004417f7341ff00716741686a41ff01714105490d310c0c0b41062101200741c001470d2f41042109410421070c330b41062101200741c001470d2d41042109410221070c320b41062101200741c001470d2b41042109410321070c310b410021090c300b410021044104210a2007450d010b200510010b200241c8006a200110ac02024020022802484101470d002000200229024c370204200041013602002000410c6a200241c8006a410c6a290200370200200441ffffffff0371450d2f200a1001200241e0006a24000f0b200235024c4220862004ad842108410921070c2c0b200441c000490d022001450d020b0b200020022f00303b00052000200a3a000420004101360200200041106a2001360200200041086a2008370200200041076a200241326a2d00003a0000200241e0006a24000f0b412e21070c270b200441ff01716741686a41ff017141044b0d0020014120490d002007450d250b412d21070c260b410121090b410421070c250b41022109410421070c240b410121090b410221070c220b41022109410221070c210b410121090b410321070c1f0b41022109410321070c1e0b417f2005107a000b200520031076000b417f200541016a107a000b200541016a20031076000b417f200541016a107a000b200541016a20031076000b20052004107a000b200420031076000b417f2007107a000b200720031076000b417f2004107a000b200420031076000b417f2004107a000b200420031076000b417f2007107a000b200720031076000b417f2007107a000b200720031076000b20052004107a000b200420031076000b417f2005107a000b200520071076000b4190a0c200104f000b200341041019000b200020043a0005200020013a000420002002290308370106200041013602002000410c6a200229010e370100200241e0006a24000f0b200020043a0005200020013a000420002002290308370106200041013602002000410c6a200229010e370100200241e0006a24000f0b200020043a0005200020013a000420002002290308370106200041013602002000410c6a200229010e370100200241e0006a24000f0b2000200936020420004101360200200041086a2002290218370200200041106a200241186a41086a280200360200200241e0006a24000f0b0b0b20004100360200200041106a20083703002000410c6a200a360200200041096a20093a0000200041086a20073a00000b200241e0006a24000bab0301087f230041c0006b22022400410021032001410c6a2104200141086a210541002106024002400240024002400340200341204f0d012005280200220720042802002208460d02200841016a21092008417f460d0420072009490d05200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b20034120490d0220086741686a41ff017141044f0d02200041013602002000410d3a0004200241c0006a24000f0b200041013602002000410f3a0004200241c0006a24000f0b200241013a000f200241346a4101360200200241206a410c6a41013602002002410f36023c200241e0c3c10036022820024101360224200241b08fc20036022020022002410f6a3602382002200241386a360230200241106a200241206a104d2002412b6a200241186a28020036000020022002290310370023200041053a000420004101360200200020022900203700052000410c6a200241276a290000370000200241c0006a24000f0b2000410036020020002006360204200241c0006a24000f0b417f2009107a000b200920071076000bbc08030d7f017e017f230041c0006b22022400410021032001410c6a2104200141086a21054100210602400240024002400240024002400240024002400240024002400240024003402003411f4b0d012005280200220720042802002208460d02200841016a21092008417f460d0820072009490d09200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b200241086a200241186a41086a280200360200200220022902183703004104210a4100210b410d200641ff01712003411f4b20086741686a41ff01714104497122031b4100200641807e7120031b72210520030d034100210c02402005450d002001410c6a2104200141086a210d4100210b4100210c4104210a0340200b220e41016a210b410021034100210603402003411f4b0d07200d280200220720042802002208460d08200841016a21092008417f460d0c20072009490d0d200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b024020034120490d0020086741686a41ff01714104490d090b0240200e200c470d00200e4101742203200e41016a220820082003491b220cad420286220f422088a70d0e200fa722034100480d0e0240200e450d00200310002208450d102008200a2003200e4102742209200920034b1b10f8022103200a10012003210a0c010b20031000220a450d0f0b200a200e4102746a20064108762210410874200641ff017172360200200b2005490d000b0b2000200a360204200041003602002000410c6a200b360200200041086a200c360200200241c0006a24000f0b410f21050c010b200241013a000f2002413c6a4101360200200241346a41013602002002410f360214200241e0c3c1003602302002410136022c200241b08fc20036022820022002410f6a3602102002200241106a360238200241186a200241286a104d410521050b200241086a200241186a41086a280200360200200220022902183703000b2000200536020420004101360200200041086a2002290300370200200041106a200241086a2802003602000c0a0b410f21030c080b200241013a00002002413c6a4101360200200241346a4101360200200241286a41086a41e0c3c1003602002002410f360214200241386a200241106a3602002002410136022c200241b08fc20036022820022002360210200241186a200241286a104d200241186a41086a2802002106200228021c21092002280218210841002110410521030c070b410d21030c060b417f2009107a000b200920071076000b417f2009107a000b200920071076000b1018000b200341041019000b20004101360200200041106a20063602002000410c6a2009360200200041086a200836020020002010410874200372360204200c450d00200a1001200241c0006a24000f0b200241c0006a24000be84903057f017e027f230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220441aa014b0d00024020040eab0100020304057576777806070879090a0b7a0c0d0e0f1011127b7c13147d7e7f15161780011881018201191a1b1c83011d1e1f840120212223850186012487018801252689018a012728292a2b2c8b018c012d8d018e018f012e90012f910130313233920193013494019501960135363738393a97013b3c3d980199019a013e3f409b0141424344454647489c01499d014a9e019f014ba001a1014c4d4e4fa201505152a3015354a401a50155565758595a5b5ca601a7015da8015e5fa901aa016061ab0162636465666768696a6b6c6d6e6f7071727374000b200341013a0008200241046a200341086a410110250cab010b200341003a0008200241046a200341086a410110250caa010b20012d00012104200341023a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca9010b20012d00012104200341033a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca8010b20012d00012104200341043a0008200241046a2202200341086a41011025200342fffdf7e78f182004410374ad42f8018388a72204413f7141c00072200420044118744118754100481b3a00082002200341086a410110250ca7010b200341053a0008200241046a200341086a410110250ca6010b2003410f3a0008200241046a200341086a410110250ca5010b200141046a2802002104200341103a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca5010b0b200141046a280200210420012d00012106200341113a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000b200320063a00082005200341086a410110250ca3010b2003411b3a0008200241046a200341086a410110250ca2010b200141046a2802002104200341203a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca2010b0b200141046a2802002104200341213a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca1010b0b200141046a2802002104200341233a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000ca0010b0b200141046a2802002104200341243a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c9f010b0b200141086a2802002104200141046a2802002105200341283a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9e010b0b200141086a2802002104200141046a2802002105200341293a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9d010b0b200141086a2802002104200141046a28020021052003412a3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9c010b0b200141086a2802002104200141046a28020021052003412b3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9b010b0b200141086a2802002104200141046a28020021052003412c3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c9a010b0b200141086a2802002104200141046a28020021052003412f3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c99010b0b200141086a2802002104200141046a2802002105200341303a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c98010b0b200141086a2802002104200141046a2802002105200341343a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c97010b0b200141086a2802002104200141046a2802002105200341353a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c96010b0b200141086a2802002104200141046a2802002105200341363a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c95010b0b200141086a2802002104200141046a2802002105200341383a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c94010b0b200141086a2802002104200141046a28020021052003413b3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c93010b0b200141086a2802002104200141046a28020021052003413c3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c92010b0b200141086a2802002104200141046a28020021052003413d3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c91010b0b200141086a2802002104200141046a28020021052003413e3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c90010b0b20012d00012104200341c0003a0008200241046a2202200341086a41011025200320043a00082002200341086a410110250c8e010b200141046a2802002106200341c1003a0008200241046a2207200341086a410110252003200641ff00713a0008024020064107752204200641c00071220272452004417f4720024572734101470d00034020032006418001723a00082007200341086a410110252003200441ff00713a0008200441c000712102200421062004410775220521042005200272452005417f4720024572470d000b0b2007200341086a410110250c8d010b200141086a2903002108200341c2003a0008200241046a2205200341086a4101102520032008a7220441ff00713a000802402008420787220850200441c00071452202712008427f52200272734101470d00034020032004418001723a00082005200341086a4101102520032008a7220441ff00713a00082008420787220850200441c00071452202712008427f52200272470d000b0b2005200341086a410110250c8c010b200141086a2903002108200341c4003a0008200241046a2204200341086a41011025200320083703082004200341086a410810250c8b010b200341c5003a0008200241046a200341086a410110250c8a010b200341c6003a0008200241046a200341086a410110250c89010b200341c7003a0008200241046a200341086a410110250c88010b200341ca003a0008200241046a200341086a410110250c87010b200341cd003a0008200241046a200341086a410110250c86010b200341ce003a0008200241046a200341086a410110250c85010b200341d1003a0008200241046a200341086a410110250c84010b200341d2003a0008200241046a200341086a410110250c83010b200341d3003a0008200241046a200341086a410110250c82010b200341d4003a0008200241046a200341086a410110250c81010b200341d5003a0008200241046a200341086a410110250c80010b200341d6003a0008200241046a200341086a410110250c7f0b200341d9003a0008200241046a200341086a410110250c7e0b200341dd003a0008200241046a200341086a410110250c7d0b200341df003a0008200241046a200341086a410110250c7c0b200341e1003a0008200241046a200341086a410110250c7b0b200341e2003a0008200241046a200341086a410110250c7a0b200341e3003a0008200241046a200341086a410110250c790b200341e4003a0008200241046a200341086a410110250c780b200341e7003a0008200241046a200341086a410110250c770b200341eb003a0008200241046a200341086a410110250c760b200341ec003a0008200241046a200341086a410110250c750b200341ed003a0008200241046a200341086a410110250c740b200341ee003a0008200241046a200341086a410110250c730b200341ef003a0008200241046a200341086a410110250c720b200341f0003a0008200241046a200341086a410110250c710b200341f2003a0008200241046a200341086a410110250c700b200341f3003a0008200241046a200341086a410110250c6f0b200341f4003a0008200241046a200341086a410110250c6e0b200341f8003a0008200241046a200341086a410110250c6d0b200341f9003a0008200241046a200341086a410110250c6c0b200341fa003a0008200241046a200341086a410110250c6b0b200341fc003a0008200241046a200341086a410110250c6a0b200341fd003a0008200241046a200341086a410110250c690b200341fe003a0008200241046a200341086a410110250c680b200341ff003a0008200241046a200341086a410110250c670b20034180013a0008200241046a200341086a410110250c660b20034181013a0008200241046a200341086a410110250c650b20034182013a0008200241046a200341086a410110250c640b20034183013a0008200241046a200341086a410110250c630b20034185013a0008200241046a200341086a410110250c620b20034187013a0008200241046a200341086a410110250c610b2003418a013a0008200241046a200341086a410110250c600b2003418d013a0008200241046a200341086a410110250c5f0b2003418e013a0008200241046a200341086a410110250c5e0b2003418f013a0008200241046a200341086a410110250c5d0b20034190013a0008200241046a200341086a410110250c5c0b20034192013a0008200241046a200341086a410110250c5b0b20034193013a0008200241046a200341086a410110250c5a0b20034194013a0008200241046a200341086a410110250c590b20034196013a0008200241046a200341086a410110250c580b20034197013a0008200241046a200341086a410110250c570b2003419a013a0008200241046a200341086a410110250c560b2003419b013a0008200241046a200341086a410110250c550b2003419c013a0008200241046a200341086a410110250c540b2003419d013a0008200241046a200341086a410110250c530b2003419e013a0008200241046a200341086a410110250c520b2003419f013a0008200241046a200341086a410110250c510b200341a0013a0008200241046a200341086a410110250c500b200341a1013a0008200241046a200341086a410110250c4f0b200341a4013a0008200241046a200341086a410110250c4e0b200341a6013a0008200241046a200341086a410110250c4d0b200341a7013a0008200241046a200341086a410110250c4c0b200341aa013a0008200241046a200341086a410110250c4b0b200341ab013a0008200241046a200341086a410110250c4a0b200341ad013a0008200241046a200341086a410110250c490b200341ae013a0008200241046a200341086a410110250c480b200341af013a0008200241046a200341086a410110250c470b200341b0013a0008200241046a200341086a410110250c460b200341b1013a0008200241046a200341086a410110250c450b200341b2013a0008200241046a200341086a410110250c440b200341b3013a0008200241046a200341086a410110250c430b200341b4013a0008200241046a200341086a410110250c420b200341b5013a0008200241046a200341086a410110250c410b200341b6013a0008200241046a200341086a410110250c400b200341b7013a0008200241046a200341086a410110250c3f0b200341b8013a0008200241046a200341086a410110250c3e0b200341b9013a0008200241046a200341086a410110250c3d0b200341ba013a0008200241046a200341086a410110250c3c0b200341bb013a0008200241046a200341086a410110250c3b0b200341bc013a0008200241046a200341086a410110250c3a0b200341bd013a0008200241046a200341086a410110250c390b200341be013a0008200241046a200341086a410110250c380b200341bf013a0008200241046a200341086a410110250c370b2003410b3a0008200241046a200341086a410110250c360b200141046a28020021042003410c3a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c360b0b200141046a28020021042003410d3a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c350b0b2001410c6a2802002105200141086a2802002109200141046a280200210a2003410e3a0008200241046a2202200341086a41011025200341003a00082009210103402003200141800172200141ff0071200141077622041b3a00082002200341086a410110252004210120040d000b2003200a200a20094102746a102e02402003280200220620032802042207460d00034020062802002101200341003a000803402003200141800172200141ff0071200141077622041b3a00082002200341086a410110252004210120040d000b200641046a22062007470d000b0b200341003a000803402003200541800172200541ff0071200541077622011b3a00082002200341086a410110252001210520010d000b0240200941ffffffff0371450d00200a10010b2000411a3a0000200341106a24000f0b2003411a3a0008200241046a200341086a410110250c320b200141046a2802002104200341223a0008200241046a2205200341086a41011025200341003a000803402003200441800172200441ff0071200441077622021b3a00082005200341086a410110252002210420020d000c320b0b200141086a2802002104200141046a28020021052003412d3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c310b0b200141086a2802002104200141046a28020021052003412e3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c300b0b200141086a2802002104200141046a2802002105200341313a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2f0b0b200141086a2802002104200141046a2802002105200341323a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2e0b0b200141086a2802002104200141046a2802002105200341333a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2d0b0b200141086a2802002104200141046a2802002105200341373a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2c0b0b200141086a2802002104200141046a2802002105200341393a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2b0b0b200141086a2802002104200141046a28020021052003413a3a0008200241046a2206200341086a41011025200341003a000803402003200541800172200541ff0071200541077622021b3a00082006200341086a410110252002210520020d000b200341003a000803402003200441800172200441ff0071200441077622021b3a00082006200341086a410110252002210420020d000c2a0b0b20012d000121042003413f3a0008200241046a2202200341086a41011025200320043a00082002200341086a410110250c280b200141046a2802002104200341c3003a0008200241046a2202200341086a41011025200320043602082002200341086a410410250c270b200341c8003a0008200241046a200341086a410110250c260b200341c9003a0008200241046a200341086a410110250c250b200341cb003a0008200241046a200341086a410110250c240b200341cc003a0008200241046a200341086a410110250c230b200341cf003a0008200241046a200341086a410110250c220b200341d0003a0008200241046a200341086a410110250c210b200341d7003a0008200241046a200341086a410110250c200b200341d8003a0008200241046a200341086a410110250c1f0b200341da003a0008200241046a200341086a410110250c1e0b200341db003a0008200241046a200341086a410110250c1d0b200341dc003a0008200241046a200341086a410110250c1c0b200341de003a0008200241046a200341086a410110250c1b0b200341e0003a0008200241046a200341086a410110250c1a0b200341e5003a0008200241046a200341086a410110250c190b200341e6003a0008200241046a200341086a410110250c180b200341e8003a0008200241046a200341086a410110250c170b200341e9003a0008200241046a200341086a410110250c160b200341ea003a0008200241046a200341086a410110250c150b200341f1003a0008200241046a200341086a410110250c140b200341f5003a0008200241046a200341086a410110250c130b200341f6003a0008200241046a200341086a410110250c120b200341f7003a0008200241046a200341086a410110250c110b200341fb003a0008200241046a200341086a410110250c100b20034184013a0008200241046a200341086a410110250c0f0b20034186013a0008200241046a200341086a410110250c0e0b20034188013a0008200241046a200341086a410110250c0d0b20034189013a0008200241046a200341086a410110250c0c0b2003418b013a0008200241046a200341086a410110250c0b0b2003418c013a0008200241046a200341086a410110250c0a0b20034191013a0008200241046a200341086a410110250c090b20034195013a0008200241046a200341086a410110250c080b20034198013a0008200241046a200341086a410110250c070b20034199013a0008200241046a200341086a410110250c060b200341a2013a0008200241046a200341086a410110250c050b200341a3013a0008200241046a200341086a410110250c040b200341a5013a0008200241046a200341086a410110250c030b200341a8013a0008200241046a200341086a410110250c020b200341a9013a0008200241046a200341086a410110250c010b200341ac013a0008200241046a200341086a410110250b2000411a3a0000024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200341106a24000bfa0301047f0240024002400240024002400240200141046a2802002202200141086a28020022036b41204f0d00200341206a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d052004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d030b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041186a290000370000200341106a200041106a290000370000200341086a200041086a290000370000200320002900003700000240024002400240200141046a2802002202200528020022036b41204f0d00200341206a22042003490d0420024101742203200420042003491b22034100480d042002450d0120012802002105200310002204450d062004200520032002200220034b1b10f8021a200510010c020b200128020021040c020b200310002204450d040b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041386a290000370000200141106a200041306a290000370000200141086a200041286a290000370000200120002900203700000f0b1018000b200341011019000b200341011019000b3400200041829cc10036020420004100360200200041146a4101360200200041106a41d8e6c200360200200041086a420f3702000b4b00200041ddf5c10036020420004100360200200041206a41013602002000411c6a4194e7c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b130020004101360204200041c4e7c2003602000b8fcd01040b7f017e0d7f017e230041b0016b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2204410d4b0d00024020040e0e00090607030a0c080e050d02040b000b200141186a2802002105200141146a2802002104200141106a28020021062001410c6a2802002107200141086a2802002108200141046a2802002109200341f8006a4100200210b402200320032900793703002003200341f8006a41086a29000037000720032d0078220a411a470d16200341f8006a41146a2005360200200341f8006a41106a2004360200200320063602840120032007360280012003200836027c200320093602782003200341f8006a200210b502200320032900013703a0012003200341086a2900003700a70120032d00002204411a470d2241012102410021090c530b2001410c6a2802002106200141086a2802002104200141046a2802002108200341f8006a20012d0001200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782209411a470d0d200241046a2802002207200241086a28020022096b20064f0d20200920066a22052009490d8d0120074101742209200520052009491b22094100480d8d012007450d462002280200210a200910002205450d9f012005200a20092007200720094b1b10f8021a200a10010c470b200341d8006a41086a2001410c6a2802003602002003200141046a290200370358200341f8006a410b200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d200328025c21072003280258210920032802602105200341a0016a410c6a4100360200200342013702a401200320023602a001200341003a005720092005411c6c6a210b200341a0016a41047221062005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200b36020c20032009360208200320073602042003200936020002402005450d00200341f8006a410172210c0340200341086a2009411c6a22023602002009280204220a450d01200941186a2802002105200941146a280200210d200941086a290200210e2009280210210720092802002104200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200e37021c2003200a360218200341f8006a200341186a200341a0016a10a80220032d00782204411a470d42200341003a00572005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b20062007200510250240200d450d00200710010b200320032900970137006f2003200329039001370368200221092002200b470d000b0b20031030200341ac016a280200210d200341a0016a41086a280200210c20032802a401210b20032802a0012102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d910120044101742209200620062009491b22094100480d91012004450d012002280200210a200910002206450d97012006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d95010b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d242004200d6a22082004490d8c0120064101742204200820082004491b22044100480d8c012006450d6420022802002109200410002208450da4012008200920042006200620044b1b10f8021a200910010c650b2001410c6a2802002106200141086a280200210d200141046a280200210a200341f8006a4104200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d200341f8006a410c6a41003602002003420137027c20032002360278200341003a00a001200341f8006a41047221022006210403402003200441800172200441ff0071200441077622081b3a00a0012002200341a0016a410110252008210420080d000b200a2006410c6c6a21072006450d27200a210403402004410c6a2109200428020422054102460d29200441086a280200210620042802002104200341f0003a00572002200341d7006a41011025200320054101463a00572002200341d7006a41011025200341003a005703402003200441800172200441ff0071200441077622081b3a00572002200341d7006a410110252008210420080d000b024020054101470d00200341003a005703402003200641800172200641ff0071200641077622041b3a00572002200341d7006a410110252004210620040d000b0b2009210420092007470d000b200721090c280b200341106a200141146a280200360200200341086a2001410c6a2902003703002003200141046a290200370300200341f8006a4100200210b402200320032900793703a0012003200341f8006a41086a2900003700a70120032d00782204411a470d0d410410002204450d9a012003420437027c20032004360278200341f8006a41df9dc10041041025200328028001210f200328027c211020032802782111200341106a28020021122003410c6a2802002113200341086a28020021142003280204211520032d000022164101460d3920164102460d3620164103470d3a20032d00012104200320133600532003201436004f2003201536004b200341c8006a41036a21084100211741012118410121194101211a0c740b2001410c6a2802002105200141086a2802002107200141046a2802002109200341f8006a4109200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d200341a0016a410c6a4100360200200342013702a401200320023602a001200341003a005720092005411c6c6a210b200341a0016a41047221062005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200b36020c20032009360208200320073602042003200936020002402005450d00200341f8006a410172210c0340200341086a2009411c6a22053602002009280204220a450d01200941186a2802002102200941146a280200210d200941086a290200210e2009280210210720092802002104200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200e37021c2003200a360218200341f8006a200341186a200341a0016a10a80220032d00782204411a470d40200341003a00572002210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b02402002450d00200720024102746a210920072102034020022802002104200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b200241046a22022009470d000b0b0240200d450d00200710010b200320032900970137006f2003200329039001370368200521092005200b470d000b0b20031030200341ac016a280200210d200341a0016a41086a280200210c20032802a401210b20032802a0012102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d8e0120044101742209200620062009491b22094100480d8e012004450d012002280200210a200910002206450d95012006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d93010b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d222004200d6a22082004490d890120064101742204200820082004491b22044100480d89012006450d6420022802002109200410002208450da2012008200920042006200620044b1b10f8021a200910010c650b2001410c6a2802002109200141086a2802002111200141046a2802002113200341f8006a4102200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d2003410c6a41003602002003420137020420032002360200200341003a00782013200941286c6a2105200341047221082009210403402003200441800172200441ff0071200441077622061b3a00782008200341f8006a410110252006210420060d000b2009450d26200341f8006a410172221541076a2110201321090340200341f8006a41086a220a2009220241086a28020036020020032002290200370378200241286a210920022d001822074104460d28200241246a2800002106200241206a280000211b2002411c6a28000021042002411a6a2d00002114200241196a2c00002116200241146a280200210c200241106a280200210d200228020c210b200341a0016a41086a2202200a280200360200200320032903783703a001200341d8006a41086a220a2002280200360200200320032903a0013703582002200a280200360200200320032903583703a001200341f8006a200341a0016a200310b60220032d00782202411a470d56200341c8006a41086a200c3602002003200d36024c2003200b360248200341f8006a200341c8006a200310b602200320152900003703a001200320102900003700a70120032d00782202411a470d5802400240024020074101460d00024020074102460d0020074103470d02200341033a00a0012008200341a0016a4101102520032016417f732204413f7141c0007220042016417f4a1b3a00a0012008200341a0016a410110252003201441ff01714100473a00a0012008200341a0016a410110252003200341f8006a41076a29000037004f200320032900783703480c030b200341023a00a0012008200341a0016a410110252003201b4101463a00a0012008200341a0016a41011025200341003a005703402003200441800172200441ff0071200441077622021b3a00572008200341d7006a410110252002210420020d000b201b4101470d02200341003a00a00103402003200641800172200641ff0071200641077622041b3a00a0012008200341a0016a410110252004210620040d000c030b0b200341013a00a0012008200341a0016a41011025200341f0003a00a0012008200341a0016a410110252003201b4101463a00a0012008200341a0016a41011025200341003a005703402003200441800172200441ff0071200441077622021b3a00572008200341d7006a410110252002210420020d000b201b4101470d01200341003a00a00103402003200641800172200641ff0071200641077622041b3a00a0012008200341a0016a410110252004210620040d000c020b0b200341003a00a0012008200341a0016a41011025200341003a00a00103402003200441800172200441ff0071200441077622061b3a00a0012008200341a0016a410110252006210420060d000b0b200320032900970137006f200320032903900137036820092005470d000b200522092005470d280c290b2001410c6a2802002109200141086a2802002107200141046a2802002105200341f8006a4103200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d200341f8006a410c6a41003602002003420137027c20032002360278200341003a0057200341f8006a41047221062009210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b02402009450d00200520094102746a210920052102034020022802002104200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b200241046a22022009470d000b0b02402007450d00200510010b20034184016a280200210d200341f8006a41086a280200210c200328027c210b20032802782102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d8c0120044101742209200620062009491b22094100480d8c012004450d012002280200210a200910002206450d8d012006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d8b010b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d1d2004200d6a22082004490d870120064101742204200820082004491b22044100480d87012006450d4620022802002109200410002208450d9b012008200920042006200620044b1b10f8021a200910010c470b2001410c6a2802002105200141086a280200210d200141046a280200210a200341f8006a4107200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0d2003410c6a41003602002003420137020420032002360200200341003a0057200a200541146c6a2109200341047221062005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2005450d28200341f8006a410172210b200341306a2107200a21080340200841146a2102200828020c22054104460d2a200841106a28020021042008290200210e200720082802083602002003200e370328200341f8006a200341286a200310b60220032d00782208411a470d3d200320053a00572006200341d7006a41011025200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b200320032900a70137009701200320032903a001370390012002210820022009470d000c2b0b0b2001410c6a2802002109200141086a280200210c200141046a280200210b200341f8006a4101200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d0e200341f8006a410c6a41003602002003420137027c20032002360278200341003a00a001200b20094104746a210d200341f8006a41047221062009210403402003200441800172200441ff0071200441077622081b3a00a0012006200341a0016a410110252008210420080d000b2009450d2a200b21040340200441106a210520042d000d22074105460d2c200428020821022004290200210e200320042d000c3a00572006200341d7006a41011025200341003a0057200ea7210a2002210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b02402002450d00200a2104034020042c000022084104460d01200441016a210420032008417f732209413f7141c0007220092008417f4a1b3a00572006200341d7006a410110252002417f6a22020d000b0b0240200e428080808010540d00200a10010b024020074104470d00200341003a00572006200341d7006a41011025200521042005200d470d010c2e0b200341013a00572006200341d7006a410110252003200741ff00733a00572006200341d7006a41011025200521042005200d470d000c2d0b0b2001410c6a280200210d200141086a280200210b200141046a280200210a200341f8006a4105200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d12200341f8006a410c6a41003602002003420137027c20032002360278200341003a00a001200a200d410c6c6a2107200341f8006a4104722102200d210403402003200441800172200441ff0071200441077622081b3a00a0012002200341a0016a410110252008210420080d000b200d450d2c200a210403402004410c6a2109200428020422054102460d2e200441086a280200210620042802002104200320054101463a00572002200341d7006a41011025200341003a005703402003200441800172200441ff0071200441077622081b3a00572002200341d7006a410110252008210420080d000b024020054101470d00200341003a005703402003200641800172200641ff0071200641077622041b3a00572002200341d7006a410110252004210620040d000b0b2009210420092007470d000b200721090c2d0b200141286a280200210c200141246a280200210a200141206a28020021072001411c6a2802002109200141186a280200210b200141146a280200210d2001410c6a290200210e200141086a2802002104200141046a2802002108200341f8006a4100200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782206411a470d122003410c6a410036020020034201370204200320023602002003200e3e02702003200436026c20032008360268200341f8006a200341e8006a200310b60220032d00782204411a470d1820034104722106200341003a0057200e422088a7210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b410121160240200d450d00200320093602702003200b36026c2003200d360268200341f8006a200341e8006a200310b60220032d00782204411a470d52410021160b200341003a00572007200c4104746a211b200c210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b201b2007460d7a2007210203402002220841106a21022008280200220541074b0d7c2008410c6a2802002109200841086a280200210420082802042108024002400240024002400240024002400240024020050e080005020301060704000b200341003a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622091b3a00572006200341d7006a410110252009210820090d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000c080b0b200341043a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622051b3a00572006200341d7006a410110252005210820050d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200941ff00713a0057024020094107752204200941c00071220872452004417f4720084572734101470d00034020032009418001723a00572006200341d7006a410110252003200441ff00713a0057200441c000712108200421092004410775220521042005200872452005417f4720084572470d000b0b2006200341d7006a410110252002201b470d080c070b200341023a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622091b3a00572006200341d7006a410110252009210820090d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000c060b0b200341033a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622051b3a00572006200341d7006a410110252005210820050d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200941ff00713a0057024020094107752204200941c00071220872452004417f4720084572734101470d00034020032009418001723a00572006200341d7006a410110252003200441ff00713a0057200441c000712108200421092004410775220521042005200872452005417f4720084572470d000b0b2006200341d7006a410110252002201b470d060c050b200341073a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622091b3a00572006200341d7006a410110252009210820090d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000c040b0b200341013a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622091b3a00572006200341d7006a410110252009210820090d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000c030b0b200341053a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622051b3a00572006200341d7006a410110252005210820050d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200941ff00713a0057024020094107752204200941c00071220872452004417f4720084572734101470d00034020032009418001723a00572006200341d7006a410110252003200441ff00713a0057200441c000712108200421092004410775220521042005200872452005417f4720084572470d000b0b2006200341d7006a410110252002201b470d030c020b200341063a00572006200341d7006a41011025200341003a005703402003200841800172200841ff0071200841077622091b3a00572006200341d7006a410110252009210820090d000b200341003a005703402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b0b2002201b470d010b0b201b21020c7b0b2001410c6a2802002105200141086a2802002107200141046a2802002109200341f8006a4106200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d12200341a0016a410c6a4100360200200342013702a401200320023602a001200341003a0057200920054104746a2102200341a0016a41047221062005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b2003200236020c20032009360208200320073602042003200936020002402005450d0020054104742108200341086a2107200341f8006a410172220a41076a210d03402007200941106a22023602002009410d6a2d000022044102460d012009290200210e200941086a280200210520032009410c6a2d000041ff00733a00572006200341d7006a41011025200320043a00572006200341d7006a41011025200341286a41086a20053602002003200e3e02282003200e4220883e022c200341f8006a200341286a200341a0016a10a8022003200a290000370390012003200d2900003700970120032d00782204411a470d3b20022109200841706a22080d000b0b20031033200341ac016a280200210d200341a0016a41086a280200210c20032802a401210b20032802a0012102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d870120044101742209200620062009491b22094100480d87012004450d012002280200210a200910002206450d8f012006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d8d010b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d1c2004200d6a22082004490d820120064101742204200820082004491b22044100480d82012006450d6420022802002109200410002208450d9d012008200920042006200620044b1b10f8021a200910010c650b2001410c6a2802002105200141086a2802002107200141046a2802002109200341f8006a410a200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782204411a470d1220034190016a410c6a410036020020034201370294012003200236029001200341003a00572009200541186c6a210220034190016a41047221062005210403402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b200320023602ac01200320093602a801200320073602a401200320093602a0012005450d342003410172220841076a2106034020092802002204450d33200941046a290200210e2009410c6a290200211c200341f8006a41146a200941146a280200360200200341f8006a410c6a201c3702002003200e37027c200320043602782003200341f8006a20034190016a10b702200320082900003703682003200629000037006f20032d00002204411a470d3a200941186a22092002470d000c340b0b200141046a2802002104200341f8006a4108200210b402200320032900793703002003200341f8006a41086a29000037000720032d00782208411a470d1220034184016a41003602002003420137027c20032002360278200341003a0057200341f8006a410472210603402003200441800172200441ff0071200441077622081b3a00572006200341d7006a410110252008210420080d000b20034184016a280200210d200341f8006a41086a280200210c200328027c210b20032802782102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d850120044101742209200620062009491b22094100480d85012004450d012002280200210a200910002206450d87012006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d85010b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d172004200d6a22082004490d800120064101742204200820082004491b22044100480d80012006450d4920022802002109200410002208450d97012008200920042006200620044b1b10f8021a200910010c4a0b20002003290300370001200020093a0000200041086a20032900073700004100210d410121154101210b4101210c4101211b410121164101210541012107410121144101210a410121004100450da7010ca9010b20002003290300370001200020043a0000200041086a200329000737000020032802582109024020032802602204450d0020092004411c6c6a210220092106034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b410021074101210a200328025c450d1920091001410121140cab010b20002003290300370001200020043a0000200041086a200329000737000041002106410121150240200d450d00200a10010b410121004101210b410121020c0a0b200020032903a001370001200020043a0000200041086a20032900a70137000020032d000022044102460d2920044101460d2720040d2a4101210a41002114200341086a280200450da801200328020410010ca8010b20002003290300370001200020043a0000200041086a200329000737000002402005450d0020092005411c6c6a210220092106034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b410021164101211502402007450d00200910010b410121004101210b4101210241012106410121094101210c4101211b0cac010b20002003290300370001200020043a0000200041086a200329000737000002402009450d00200941286c21082013210403400240200441046a280200450d00200428020010010b0240200441106a280200450d002004410c6a28020010010b200441286a2104200841586a22080d000b0b4100210b4101211502402011450d00201310010b410121000c050b20002003290300370001200020043a0000200041086a2003290007370000410021024101211502402007450d00200510010b410121004101210b0c050b20002003290300370001200020043a0000200041086a200329000737000002402005450d00200541146c2108200a210403400240200441046a280200450d00200428020010010b200441146a21042008416c6a22080d000b0b4100211b410121150240200d450d00200a10010b410121004101210b4101210241012106410121094101210c0ca8010b200020032903003700012000200a3a0000200041086a200329000737000002402008450d00200910010b02402004450d00200610010b410121004100211541010d014101210b4101210241012106410121094101210c4101211b410121164101210541012107410121144101210a4101210d20030da0010ca2010b20002003290300370001200020043a0000200041086a200329000737000002402009450d0020094104742108200b210403400240200441046a280200450d00200428020010010b200441106a2104200841706a22080d000b0b4100210041012115200c450d00200b10010b4101210b0b410121020b410121060b410121090ca0010b20002003290300370001200020043a0000200041086a200329000737000041002109410121150240200b450d00200a10010b410121004101210b41012102410121060c9f010b20002003290300370001200020063a0000200041086a200329000737000002402004450d00200810010b0240200d450d00200b450d00200d10010b0240200a450d00200710010b4100210a410121140c9c010b20002003290300370001200020043a0000200041086a200329000737000002402005450d00200920054104746a2102200921060340024020062802082208450d0020062802002104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641106a21040240200641046a280200450d00200628020010010b2004210620042002470d000b0b4100210c4101211502402007450d00200910010b410121004101210b4101210241012106410121090c9e010b20002003290300370001200020043a0000200041086a200329000737000002402005450d002009200541186c6a21022009210603400240200641046a280200450d00200628020010010b0240200641146a2802002208450d00200628020c2104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641186a21040240200641106a280200450d002006410c6a28020010010b2004210620042002470d000b0b410021054101211502402007450d00200910010b410121004101210b4101210241012106410121094101210c4101211b410121160ca0010b20002003290300370001200020083a0000200041086a2003290007370000410121154101210b0c3f0b200228020021050c270b200020032903a001370001200020043a0000200041086a20032900a7013700004101210b410021150c3c0b200320032900793703a001200320034180016a2900003700a70141002108200341086a280200450d91010c90010b200228020021080c2a0b200228020021080c330b200228020021080c410b200228020021080c430b200228020021080c490b410121140c91010b200a21090b200720096b2104024003402004450d01200441746a2104200928020421082009410c6a210920084102470d000b0b0240200d450d00200a10010b20034184016a280200210d200341f8006a41086a280200210c200328027c210b20032802782102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d6720044101742209200620062009491b22094100480d672004450d012002280200210a200910002206450d6a2006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d680b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200d4f0d002004200d6a22082004490d6320064101742204200820082004491b22044100480d632006450d1f20022802002109200410002208450d762008200920042006200620044b1b10f8021a200910010c200b200228020021080c200b201321090b20092005460d010b0340200941186a2d00004104460d01200941106a28020021042009410c6a28020021080240200941046a280200450d00200928020010010b02402004450d00200810010b200941286a22092005470d000b0b02402011450d00201310010b2003410c6a280200210d200341086a280200210c2003280204210b20032802002102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d6320044101742209200620062009491b22094100480d632004450d012002280200210a200910002206450d6f2006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d6d0b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b200241046a2802002206200241086a28020022046b200d4f0d082004200d6a22082004490d5e20064101742204200820082004491b22044100480d5e2006450d4920022802002109200410002208450d7c2008200920042006200620044b1b10f8021a200910010c4a0b200a21020b20022009460d0003402002410c6a2802004104460d010240200241046a280200450d00200228020010010b200241146a22022009470d000b0b0240200d450d00200a10010b2003410c6a280200210d200341086a280200210c2003280204210b20032802002102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d6020044101742209200620062009491b22094100480d602004450d012002280200210a200910002206450d692006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d670b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200d4f0d002004200d6a22082004490d5c20064101742204200820082004491b22044100480d5c2006450d3a20022802002109200410002208450d762008200920042006200620044b1b10f8021a200910010c3b0b200228020021080c3b0b200b21050b2005200d460d0003402005410d6a2d00004105460d010240200541046a280200450d00200528020010010b200541106a2205200d470d000b0b0240200c450d00200b10010b20034184016a280200210d200341f8006a41086a280200210c200328027c210b20032802782102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d5d20044101742209200620062009491b22094100480d5d2004450d012002280200210a200910002206450d612006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d5f0b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200d4f0d002004200d6a22082004490d5920064101742204200820082004491b22044100480d592006450d1b20022802002109200410002208450d6e2008200920042006200620044b1b10f8021a200910010c1c0b200228020021080c1c0b200a21090b200a200d410c6c6a20096b2104024003402004450d01200441746a2104200928020421082009410c6a210920084102470d000b0b0240200b450d00200a10010b20034184016a280200210d200341f8006a41086a280200210c200328027c210b20032802782102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d5b20044101742209200620062009491b22094100480d5b2004450d012002280200210a200910002206450d602006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d5e0b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200d4f0d002004200d6a22082004490d5720064101742204200820082004491b22044100480d572006450d1d20022802002109200410002208450d6d2008200920042006200620044b1b10f8021a200910010c1e0b200228020021080c1e0b200228020021080c420b0240200341106a2802002208450d00200341086a28020021042008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b4101210a410021142003410c6a280200450d8001200341086a28020010010c80010b2003410036027020034201370368200341003a0057200341f0006a210d4101210a41002104410021082015210603402003200641807f72200641ff0071200641077622091b22053a0057024020082004470d00200441016a22062004490d5520044101742205200620062005491b22064100480d55200610002107024002402004450d002007450d652007200a20062004200420064b1b10f8021a200a10010c010b2007450d640b2003200636026c2003200736026820032d005721052007210a200621040b200d200841016a2206360200200a20086a20053a0000200621082009210620090d000b200341f8006a41106a220b201436020020034184016a20133602002003418c016a201420124104746a220d36020020032014360280012003201536027c20034100360278200341f8006a41086a211a2015450d3c41002104201421092015211803402009200d460d3d02400340200b200941106a2208360200200941046a280200220c0d01200441016a210420082109200d2008470d000c3e0b0b200941086a290200210e2003200441016a22193602782009280200211720032018417f6a221836027c200341003a0057200941106a2109200341e8006a41086a221b2802002106200328026c210803402003200441807f72200441ff0071200441077622051b220a3a0057024002400240024020062008470d00200841016a22042008490d5920084101742207200420042007491b22074100480d592008450d012003280268210a200710002204450d682004200a20072008200820074b1b10f8021a200a10010c020b200328026821040c020b200710002204450d660b2003200736026c2003200436026820032d0057210a200721080b201b200641016a2207360200200420066a200a3a0000200721062005210420050d000b200341a0016a41086a200e3703002003200c3602a401200320173602a00120034190016a200341a0016a200341e8006a10b80220032d0090012208411a470d532019210420180d000c3d0b0b0240200341106a2802002204450d00200341086a280200220920044104746a210003402009220241106a2109024020022802042204450d0002402002410c6a2802002208450d002008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200241086a280200450d00200241046a28020010010b20092000470d000b0b4101210a410021142003410c6a280200450d7e200341086a28020010010c7e0b4101210a41002114200341086a280200450d7d200328020410010c7d0b4100211820034100360298012003420137039001200341f8006a410c6a2012360200200341f8006a41086a20133602002003201436027c20032015360278200341a0016a200341f8006a20034190016a10b80220032d00a0012208411a470d49200341d3006a20034198016a280200360000200320032903900137004b200341cb006a2108410121194100211a41002117410121040c3a0b4100211a20034100360298012003420137039001200320133602a801200320143602a401200320153602a001200341f8006a200341a0016a20034190016a10b90220032d00782208411a470d49200341d3006a20034190016a41086a280200360000200320032903900137004b200341cb006a2108410121184101211941012117410021040c390b200941186a21020b200341a8016a20023602000b200341a0016a10312003419c016a280200210d20034190016a41086a280200210c200328029401210b2003280290012102200341003a0057200241046a2107200d210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d5120044101742209200620062009491b22094100480d512004450d012002280200210a200910002206450d5b2006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d590b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200d4f0d002004200d6a22082004490d4d20064101742204200820082004491b22044100480d4d2006450d3220022802002109200410002208450d692008200920042006200620044b1b10f8021a200910010c330b200228020021080c330b2003200c290000370390012003200c41076a290000370097010240200d450d00200710010b200320032900970137006f20032003290390013703682003200329006f37004f20032003290368370348200310302003200329004f37003f200320032903483703380240200341a0016a41086a280200450d0020032802a40110010b2003200329003f37002f20032003290338370328200020043a000020002003290328370001200041086a200329002f37000041002107410121154101210b4101210c4101211b41012116410121050c220b2003200c290000370390012003200c41076a290000370097010240200d450d00200710010b200320032900970137006f20032003290390013703682003200329006f37004f20032003290368370348200310302003200329004f37003f200320032903483703380240200341a0016a41086a280200450d0020032802a40110010b2003200329003f37002f20032003290338370328200020043a000020002003290328370001200041086a200329002f37000041002116410121154101210b4101210c4101211b0c1f0b2003200b2900003703a0012003200b41076a2900003700a701200320032900a70137009701200320032903a00137039001200320032900970137006f2003200329039001370368024020022009460d0003402002410c6a2802004104460d010240200241046a280200450d00200228020010010b200241146a22022009470d000b0b0240200d450d00200a10010b2003200329006f37004f200320032903683703480240200341086a280200450d00200328020410010b2003200329004f37003f200320032903483703382008411a460d2a20002003290338370001200020083a0000200041086a200329003f3700004100211b410121154101210b4101210c0c1d0b200320032900970137006f2003200329039001370368200310332003200329006f37004f200320032903683703480240200341a0016a41086a280200450d0020032802a40110010b2003200329004f37003f20032003290348370338200020043a000020002003290338370001200041086a200329003f3700004100210c410121154101210b0c1b0b200341a0016a41086a200941186a360200200320032903683703482003200329006f37004f200341a0016a10312003200329004f37003f20032003290348370338024020034190016a41086a280200450d0020032802940110010b2003200329003f37002f20032003290338370328200020043a000020002003290328370001200041086a200329002f37000041002105410121154101210b4101210c4101211b410121160c1d0b200910002205450d580b20022005360200200241046a2009360200200241086a28020021090b200241086a200920066a360200200520096a2008200610f8021a41002105410121094101210241012113410121074101210a4101210d4101210b4101210c4101211b410121064101211641012114410121154100450d680c690b200410002208450d560b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b4100210a410121094101210241012113410121070c320b200410002208450d540b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b410021074101210941012102410121130c2e0b200410002208450d520b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b41002102410121090b0c060b200410002208450d4f0b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b4100210d410121094101210241012113410121074101210a0c290b200410002208450d4d0b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b41012109410121020b410121130c220b20032015290000370390012003201541076a29000037009701200d450d02200b10010c020b200320032900793703a001200320034180016a2900003700a70141012108200341086a2802000d570c580b200320032900a70137009701200320032903a001370390010b200320032900970137006f20032003290390013703682003200329006f37003f20032003290368370338024020092005460d000340200941186a2d00004104460d01200941106a28020021042009410c6a28020021080240200941046a280200450d00200928020010010b02402004450d00200810010b200941286a22092005470d000b0b02402011450d00201310010b2003200329003f37002f200320032903383703280240200341086a280200450d00200328020410010b2003200329002f37001f200320032903283703182002411a460d1d20002003290318370001200020023a0000200041086a200329001f3700004100210b410121150b0b4101210c0b4101211b0b410121160b410121050b410121070b410121144101210a4101210d4101210041010d520c500b200410002208450d3f0b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329003f37002f2003200329033837032841002116410121094101210241012113410121074101210a4101210d4101210b4101210c4101211b410121064101211441012115410121054101450d490c4a0b200410002208450d3d0b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329003f37002f200320032903383703284100211b410121094101210241012113410121074101210a4101210d4101210b4101210c0c170b200410002208450d3b0b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329004f37003f200320032903483703380b4100210c410121094101210241012113410121074101210a4101210d4101210b0c120b200410002208450d380b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329004f37003f200320032903483703384100210b410121094101210241012113410121074101210a4101210d0c0e0b200410002208450d360b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329003f37002f2003200329033837032841002106410121094101210241012113410121074101210a4101210d4101210b4101210c4101211b0c0e0b200320043602780b201a1032200341d3006a200341e8006a41086a2802003600002003200329036837004b200341cb006a21084102210441002119410121184100211a410021170b2008280000210c2003280053210a200328004f211b410110002207450d26200720043a0000200341003a00574101210441012108200a210603402003200641807f72200641ff0071200641077622091b22063a0057024002400240024020042008470d00200441016a22082004490d1a20044101742206200820082006491b22054100480d1a2004450d01200510002208450d252008200720052004200420054b1b10f802210820071001200821070c020b200421050c020b200510002207450d230b20032d0057210620042108200521040b200720086a20063a0000200841016a21082009210620090d000b0240024002400240200520086b200a4f0d002008200a6a22042008490d1920054101742206200420042006491b220d4100480d192005450d01200d1000220b450d36200b2007200d20052005200d4b1b10f802210420071001200420086a200c200a10f8021a201b0d020c030b2005210d2007220b20086a200c200a10f8021a201b0d010c020b200d1000220b450d34200b20086a200c200a10f8021a201b450d010b200c10010b2008200a6a210c024002402016450d000240024020164101460d0020164102470d03411a21072019450d3b2012450d01201420124104746a210a2014210503402005220941106a2105024020092802042204450d0002402009410c6a2802002208450d002008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200941086a280200450d00200941046a28020010010b2005200a470d000c020b0b411a21072018450d3a2012450d002012410c6c2108201421040340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b2013450d39201410010c390b411a21072017201445720d380c370b411a2107201a20144572450d360c370b200410002208450d320b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200d6a360200200820046a200b200d10f8021a0240200c450d00200b10010b2003200329002f37001f200320032903283703180b4100211341012109410121020b410121070b4101210a0b4101210d0b4101210b0b4101210c0b4101211b0b410121060b4101211641012114410121154101210541010d2e0c2d0b200721020b2007200c4104746a21080240034020082002460d0120022802002104200241106a210220044108470d000b0b0240200a450d00200710010b2003410c6a280200210c200341086a28020021142003280204211b20032802002102200341003a0057200241046a2107200c210403402003200441807f72200441ff0071200441077622081b22093a005702400240024002402007280200200241086a22052802002204470d00200441016a22062004490d0c20044101742209200620062009491b22094100480d0c2004450d012002280200210a200910002206450d192006200a20092004200420094b1b10f8021a200a10010c020b200228020021060c020b200910002206450d170b20022006360200200720093602002005280200210420032d005721090b2005200441016a360200200620046a20093a00002008210420080d000b0240200241046a2802002206200241086a28020022046b200c4f0d002004200c6a22082004490d0820064101742204200820082004491b22044100480d082006450d0420022802002109200410002208450d272008200920042006200620044b1b10f8021a200910010c050b200228020021080c050b200341a0016a41086a290300210e20032802a401210420032f00a10120032d00a301411074724108742008722107200328029401450d0120032802900110010c010b200341f8006a41086a290300210e200328027c210420032f007920032d007b411074724108742008722107200328029401450d0020032802900110010b4100210d4101210b0c240b200410002208450d220b20022008360200200241046a2004360200200241086a28020021040b200241086a2004200c6a360200200820046a201b200c10f8021a02402014450d00201b10010b02402016450d00200d450d00200b450d00200d10010b200320032900a70137009701200320032903a0013703900141002115410121094101210241012113410121074101210a4101210d4101210b4101210c4101211b410121064101211641012114410121054101450d250c260b20032d009301210620032f009101210920034190016a41086a290300210e2003280294012104201a1032200920064110747241087421060240200328026c450d00200328026810010b200620087221074101210b0240024002402016450d004100210d20164101460d0220164102460d234101210b20140d010c230b4100210d41000d222014450d220b201510010c210b02402012450d002012410c6c2106201421080340024020082802002209450d00200841046a280200450d00200910010b2008410c6a2108200641746a22060d000b0b4101210b2013450d20201410010c200b1018000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200941011019000b200541011019000b200941011019000b200941011019000b200641011019000b200741011019000b410441011019000b410141011019000b200941011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200441011019000b200d41011019000b200441011019000b200441011019000b4100210c0c020b201510010b0b024002400240200741ff0171411a470d002003418c016a200c36020020034188016a200d3602002003200b360284012003200f360280012003201036027c20032011360278200341a0016a200341f8006a200210b502200320032900a101370390012003200341a0016a41086a2900003700970120032d00a0012204411a470d0141002114410121094101210241012113410121074101210a4101210d4101210b4101210c4101211b410121064101211641012115410121054101450d030c040b0240200d450d00200b10010b20002007360200200041086a200e370200200041046a200436020041002114410121152010450d01201110010c010b2000200329039001370001200020043a0000200041086a20032900970137000041002114410121150b4101210b4101210c4101211b4101211641012105410121074101210a4101210d410121004101450d040c060b2004450d00200810010b2000411a3a0000024002400240024020012d00002204410e4b0d000240024002400240024002400240024002400240024002400240024020040e0f0009080703050a0b0d0e0c02060401000b2005450d24200141086a280200450d24200141046a2802001001200341b0016a24000f0b2015450d230240200141086a280200450d00200141046a28020010010b0240200141146a2802002204450d00200141186a280200450d00200410010b200141246a280200450d23200141206a2802001001200341b0016a24000f0b2006450d2202402001410c6a2802002204450d00200141046a2802002206200441186c6a210203400240200641046a280200450d00200628020010010b0240200641146a2802002208450d00200628020c2104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641186a21040240200641106a280200450d002006410c6a28020010010b2004210620042002470d000b0b200141086a280200450d22200141046a2802001001200341b0016a24000f0b2007450d21200141086a280200450d21200141046a2802001001200341b0016a24000f0b2014450d20200141046a2d000022044102460d0b20044101460d0a20040d0c2001410c6a280200450d20200141086a2802001001200341b0016a24000f0b200a450d1f200141086a280200450d1f200141046a2802001001200341b0016a24000f0b2016450d1e02402001410c6a2802002204450d00200141046a28020022062004411c6c6a2102034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b200141086a280200450d1e200141046a2802001001200341b0016a24000f0b2013450d1d02402001410c6a2802002208450d00200141046a2802002104200841286c210803400240200441046a280200450d00200428020010010b0240200441106a280200450d002004410c6a28020010010b200441286a2104200841586a22080d000b0b200141086a280200450d1d200141046a2802001001200341b0016a24000f0b2002450d1c02402001410c6a2802002208450d00200141046a28020021042008410474210803400240200441046a280200450d00200428020010010b200441106a2104200841706a22080d000b0b200141086a280200450d1c200141046a2802001001200341b0016a24000f0b2009450d1b0240200141086a280200450d00200141046a28020010010b200141146a280200450d1b200141106a2802001001200341b0016a24000f0b200d450d1a200141086a280200450d1a200141046a2802001001200341b0016a24000f0b200b450d1902402001410c6a2802002204450d00200141046a280200220620044104746a21020340024020062802082208450d0020062802002104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641106a21040240200641046a280200450d00200628020010010b2004210620042002470d000b0b200141086a280200450d19200141046a2802001001200341b0016a24000f0b201b450d1802402001410c6a2802002204450d00200141046a28020022062004411c6c6a2102034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b200141086a280200450d18200141046a2802001001200341b0016a24000f0b200c450d1702402001410c6a2802002208450d00200141046a2802002104200841146c210803400240200441046a280200450d00200428020010010b200441146a21042008416c6a22080d000b0b200141086a280200450d17200141046a2802001001200341b0016a24000f0b2001102a200341b0016a24000f0b0240200141146a2802002208450d002001410c6a28020021042008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200141106a280200450d152001410c6a2802001001200341b0016a24000f0b0240200141146a2802002204450d002001410c6a280200220920044104746a210003402009220241106a2109024020022802042204450d0002402002410c6a2802002208450d002008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200241086a280200450d00200241046a28020010010b20092000470d000b0b200141106a280200450d142001410c6a2802001001200341b0016a24000f0b2001410c6a280200450d13200141086a2802001001200341b0016a24000f0b200328020410010b0240200d452008720d00200b450d00200d10010b0240200a450d00200710010b200320032900a70137009701200320032903a00137039001200020043a00002000200329039001370001200041086a2003290097013700004100210a410121154101210b4101210c4101211b410121164101210541012107410121144101210d4101210041010d020b4101210241012106410121092004450d020b20081001410121000b4101210241012106410121090b20012d00002204410e4d0d080c090b410121070b41012115410121004101210b4101210241012106410121094101210c4101211b41012116410121050c050b4101210c0b4101211b0b410121160b410121050b41012107410121144101210a0b4101210d20012d00002204410e4b0d010b0240024002400240024002400240024002400240024002400240024020040e0f0009080703050a0b0d0e0c02060401000b200d450d11200141086a280200450d11200141046a2802001001200341b0016a24000f0b200a450d100240200141086a280200450d00200141046a28020010010b0240200141146a2802002204450d00200141186a280200450d00200410010b200141246a280200450d10200141206a2802001001200341b0016a24000f0b2005450d0f02402001410c6a2802002204450d00200141046a2802002206200441186c6a210203400240200641046a280200450d00200628020010010b0240200641146a2802002208450d00200628020c2104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641186a21040240200641106a280200450d002006410c6a28020010010b2004210620042002470d000b0b200141086a280200450d0f200141046a2802001001200341b0016a24000f0b2002450d0e200141086a280200450d0e200141046a2802001001200341b0016a24000f0b2014450d0d200141046a2d000022044102460d0b20044101460d0a20040d0c2001410c6a280200450d0d200141086a2802001001200341b0016a24000f0b2006450d0c200141086a280200450d0c200141046a2802001001200341b0016a24000f0b2007450d0b02402001410c6a2802002204450d00200141046a28020022062004411c6c6a2102034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b200141086a280200450d0b200141046a2802001001200341b0016a24000f0b200b450d0a02402001410c6a2802002208450d00200141046a2802002104200841286c210803400240200441046a280200450d00200428020010010b0240200441106a280200450d002004410c6a28020010010b200441286a2104200841586a22080d000b0b200141086a280200450d0a200141046a2802001001200341b0016a24000f0b2000450d0902402001410c6a2802002208450d00200141046a28020021042008410474210803400240200441046a280200450d00200428020010010b200441106a2104200841706a22080d000b0b200141086a280200450d09200141046a2802001001200341b0016a24000f0b2015450d080240200141086a280200450d00200141046a28020010010b200141146a280200450d08200141106a2802001001200341b0016a24000f0b2009450d07200141086a280200450d07200141046a2802001001200341b0016a24000f0b200c450d0602402001410c6a2802002204450d00200141046a280200220620044104746a21020340024020062802082208450d0020062802002104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b200641106a21040240200641046a280200450d00200628020010010b2004210620042002470d000b0b200141086a280200450d06200141046a2802001001200341b0016a24000f0b2016450d0502402001410c6a2802002204450d00200141046a28020022062004411c6c6a2102034002402006410c6a2802002208450d0020062802042104200841047421080340024020042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010010b200441106a2104200841706a22080d000b0b0240200641086a280200450d00200641046a28020010010b2006411c6a21040240200641146a280200450d00200628021010010b2004210620042002470d000b0b200141086a280200450d05200141046a2802001001200341b0016a24000f0b201b450d0402402001410c6a2802002208450d00200141046a2802002104200841146c210803400240200441046a280200450d00200428020010010b200441146a21042008416c6a22080d000b0b200141086a280200450d04200141046a2802001001200341b0016a24000f0b2001102a0c030b0240200141146a2802002208450d002001410c6a28020021042008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200141106a280200450d022001410c6a2802001001200341b0016a24000f0b0240200141146a2802002204450d002001410c6a280200220920044104746a210003402009220241106a2109024020022802042204450d0002402002410c6a2802002208450d002008410c6c21080340024020042802002206450d00200441046a280200450d00200610010b2004410c6a2104200841746a22080d000b0b200241086a280200450d00200241046a28020010010b20092000470d000b0b200141106a280200450d012001410c6a2802001001200341b0016a24000f0b2001410c6a280200450d00200141086a2802001001200341b0016a24000f0b200341b0016a24000bd00101047f024002400240024002400240200241046a280200200241086a2802002203470d00200341016a22042003490d0420034101742205200420042005491b22054100480d042003450d0120022802002106200510002204450d052004200620052003200320054b1b10f8021a200610010c020b200228020021040c020b200510002204450d030b20022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20013a00002000411a3a00000f0b1018000b200541011019000bb505010c7f230041306b220324002003410c6a220441003602002003420137020420032002360200200341206a41086a200141086a28020036020020032001290200370320200341106a200341206a200310b60202400240024002400240024002400240024020032d0010411a470d002003410472200128020c2205200141146a2802001025200341086a2802002106200328020421072003280200220841046a21092004280200220a2104034002400240024002402009280200200841086a220b2802002202470d00200241016a220c2002490d0b2002410174220d200c200c200d491b220d4100480d0b2002450d012008280200210e200d1000220c450d0c200c200e200d20022002200d4b1b10f8021a200e10010c020b2008280200210c0c020b200d1000220c450d0a0b2008200c3602002009200d360200200b28020021020b200b200241016a360200200c20026a200441807f72200441ff0071200441077622021b3a00002002210420020d000b200841046a280200220c200841086a28020022026b200a4f0d012002200a6a22042002490d06200c4101742202200420042002491b22024100480d06200c450d022008280200210b200210002204450d082004200b2002200c200c20024b1b10f8021a200b10010c030b20002003290310370200200041086a200341106a41086a2903003702000240200341086a280200450d00200328020410010b200141106a280200450d042001410c6a2802001001200341306a24000f0b200828020021040c020b200210002204450d050b20082004360200200841046a2002360200200841086a28020021020b200841086a2002200a6a360200200420026a2007200a10f8021a02402006450d00200710010b2000411a3a0000200141106a280200450d00200510010b200341306a24000f0b1018000b200d41011019000b200241011019000b860101047f230041106b22032400200141086a2802002104200341003a000f200241046a21052004210203402003200241800172200241ff0071200241077622061b3a000f20052003410f6a410110252006210220060d000b200128020421022005200128020022062004102502402002450d00200610010b2000411a3a0000200341106a24000bdf0803087f017e047f230041e0006b22032400200341146a41003602002003420137020c20032002360208200128020421042001280200210520012802082106200341003a0050200520064103746a2107200341086a41047221082006210203402003200241800172200241ff0071200241077622091b3a00502008200341d0006a410110252009210220090d000b024002402006450d00200521020340200241086a210a2002290200220b422088a7220241ff01714104460d022002411874411875210c200341003a0050200ba7210203402003200241800172200241ff0071200241077622091b3a00502008200341d0006a410110252009210220090d000b2003200c417f732202413f7141c000722002200c417f4a1b3a00502008200341d0006a41011025200a2102200a2007470d000b2007210a0c010b2005210a0b200520064103746a2109024003402009200a460d01200a2d00042102200a41086a210a20024104470d000b0b02402004450d00200510010b200128020c2205200141146a280200220d41047422046a2106200141106a280200210e024002400240024002400240200d450d00200341d0006a410172210a41002109200341d0006a41026a2108200341c0006a410172220141076a210f03402008200520096a220241036a2d00003a00002003200241016a2f00003b015020022d0000220c41ac01460d022003412c6a41026a220720082d00003a0000200320032f01503b012c200241046a290200210b200341d0006a410c6a2002410c6a280200360200200a20032f012c3b0000200a41026a20072d00003a00002003200c3a00502003200b370254200341c0006a200341d0006a200341086a10ae02200320012900003703302003200f29000037003720032d0040220c411a470d052004200941106a2209470d000c040b0b200522022006470d010c020b200241106a22022006460d010b03400240024020022d000022094109460d00200941ac01470d010c030b200241086a28020041ffffffff0371450d00200241046a28020010010b200241106a22022006470d000b0b0240200e450d00200510010b200341146a280200210a200341106a2802002107200328020c210c20032802082102200341003a0050200241046a2108200a210203402003200241800172200241ff0071200241077622091b3a00502008200341d0006a410110252009210220090d000b2008200c200a102502402007450d00200c10010b2000411a3a00000c010b2003200329003737001f200320032903303703180240200d41047441706a2009460d00200241186a2102034002400240200241786a22092d000022084109460d00200841ac01470d010c030b200228020041ffffffff0371450d002002417c6a28020010010b200241106a2102200941106a2006470d000b0b0240200e450d00200510010b200020032903183700012000200c3a0000200041086a200329001f370000200341086a41086a280200450d00200328020c1001200341e0006a24000f0b200341e0006a24000b900703107f017e017f230041306b22032400200241086a2104200241046a2105200128020022062107024002400240024003400240024002400240200528020020042802002208470d00200841016a22092008490d052008410174220a20092009200a491b220a4100480d052008450d012002280200210b200a10002209450d062009200b200a20082008200a4b1b10f8021a200b10010c020b200228020021090c020b200a10002209450d040b200220093602002005200a360200200428020021080b2004200841016a360200200920086a200741807f72200741ff0071200741077622081b3a00002008210720080d000b2001280204220c2001410c6a280200220d410c6c6a210e200141086a280200210f200c21080240024002402006450d00200341106a4101722110200241086a210a200c21114100211203402011200e460d02201221072011210902400340200928020022010d01200741016a2107200e2009410c6a2209470d000c040b0b2009410c6a2111200741016a21122006417f6a2106200941046a290200211303400240024002400240200241046a220b280200200a2802002208470d00200841016a22042008490d0920084101742205200420042005491b22054100480d092008450d0120022802002114200510002204450d0b2004201420052008200820054b1b10f8021a201410010c020b200228020021040c020b200510002204450d090b20022004360200200b2005360200200a28020021080b200a200841016a360200200420086a200741807f72200741ff0071200741077622081b3a00002008210720080d000b2003201337022420032001360220200341106a200341206a200210b902200320102900003703002003201041076a29000037000720032d00102208411a470d0320060d000b2009410c6a21080b2008200e460d00200c200d410c6c6a2102034020082207410c6a2108024020072802002209450d00200741046a280200450d00200910010b20022008470d000b0b0240200f450d00200c10010b2000411a3a00000c040b20002003290300370001200020083a0000200041086a20032900073700000240200c200d410c6c6a220241746a2009460d002009410c6a2108034020082207410c6a2108024020072802002209450d00200741046a280200450d00200910010b20022008470d000b0b200f450d03200c1001200341306a24000f0b1018000b200a41011019000b200541011019000b200341306a24000bd60301087f200241046a2103200141086a28020022042105024002400240034002400240024002402003280200200241086a22062802002207470d00200741016a22082007490d0520074101742209200820082009491b22094100480d052007450d012002280200210a200910002208450d062008200a20092007200720094b1b10f8021a200a10010c020b200228020021080c020b200910002208450d040b2002200836020020032009360200200628020021070b2006200741016a360200200820076a200541807f72200541ff0071200541077622071b3a00002007210520070d000b20012802042109200128020021080240024002400240200241046a2802002206200241086a28020022076b20044f0d00200720046a22052007490d0420064101742207200520052007491b22074100480d042006450d0120022802002103200710002205450d062005200320072006200620074b1b10f8021a200310010c020b200228020021050c020b200710002205450d040b20022005360200200241046a2007360200200241086a28020021070b200241086a200720046a360200200520076a2008200410f8021a02402009450d00200810010b2000411a3a00000f0b1018000b200941011019000b200741011019000bc0c20108097f017e017f017e077f017e117f017e230041f080046b22022400024002402001280204220320012802082204470d00200241013a0020200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc2003602582002200241206a3602182002200241186a360268200241d880046a200241d8006a104d20022802dc8004210120022802d88004210520004101360200200041003a00042001450d01200510010c010b200441016a2105024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004417f460d00024020032005490d002001280200220620046a2d00002104200141086a20053602000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004410b4b0d0002400240024002400240024002400240024002400240024020040e0c00070405020809060b030a01000b41002104200141086a21074100210803402004411f4b0d6520032005460d632005417f460d262003200541016a2209490d25200620056a2d0000210a20072009360200200a41ff00712004411f71742008722108200441076a210420092105200a418001710d000b20044120490d38200a6741686a41ff017141044f0d38410d21010c650b200241d8006a200110bb0220022802584101470d0b200228025c22094108762101200241e8006a280200210a200241d8006a41086a290300210b0c600b200241d8006a200110bb0220022802584101470d0b200228025c22014108762105200241e8006a2802002103200241d8006a41086a290300210b0c5b0b200241d8006a200110bb0220022802584101470d0b200228025c220a4108762101200241e8006a2802002109200241d8006a41086a290300210b0c560b200241d8006a200110bb0220022802584101470d0b200228025c22054108762101200241e8006a2802002103200241d8006a41086a290300210b0c510b200241d8006a200110bb0220022802584101470d0b200228025c22014108762105200241e8006a2802002103200241d8006a41086a290300210b0c4c0b200241d8006a200110bb0220022802584101470d0b200228025c22054108762103200241e8006a2802002101200241d8006a41086a290300210b0c460b200241d8006a200110bb0220022802584101470d0b200228025c220c4108762105200241e8006a2802002101200241d8006a41086a290300210b0c410b200241d8006a200110bb0220022802584101470d63200228025c22054108762101200241e8006a2802002103200241d8006a41086a290300210b0c6a0b200241d8006a200110bb0220022802584101470d60200228025c22014108762105200241e8006a280200210a200241d8006a41086a290300210b0c610b200241d8006a200110bb0220022802584101470d5d200228025c22034108762101200241e8006a280200210a200241d8006a41086a290300210b0c5e0b200241d8006a200110bb02200241d8006a410472210120022802584101470d5b20004101360200200020012902003702042000410c6a200141086a290200370200200241f080046a24000f0b200041123a000420004101360200200041056a20043a0000200241f080046a24000f0b200241306a200241ec006a280200360200200241286a2208200241d8006a410c6a2902003703002002200229025c370320410021014100210303402001411f4b0d522008280200220a200241206a410c6a22092802002205460d37200541016a21042005417f460d17200a2004490d16200228022020056a2d0000210520092004360200200541ff00712001411f71742003722103200141076a21012005418001710d000b41042104410d200341ff01712001411f4b20056741686a41ff01714104497122011b4100200341807e7120011b72210920010d522009450d204200210d41042104200241d8006a410c6a210e200241d8006a41086a210f410021100340200241d8006a200241206a10ac02200228025c211120022802584101460d1e200241d8006a200241206a10aa02200228025c211220022802584101460d1d200e280200210c200f2802002113200241d8006a200241206a10ac02200228025c210820022802584101460d1c41002105200241c8006a41086a2214410036020020024201370348200241d8006a41004180800410f7021a024002402008450d00410021030340200241206a41086a2802002206200241206a410c6a220728020022056b200820036b220141808004200141808004491b2201490d26200520016a220a2005490d0c2006200a490d0b200241d8006a200228022020056a200110f8021a2007200a360200200241c8006a200241d8006a200110252008200120036a22034b0d000b20142802002105200228024c21032002280248210a0c010b4101210a410021030b0240200d422088a72201200da7470d00200141016a22082001490d6120014101742206200820082006491bad220b421c7e2215422088a70d612015a722084100480d61024002402001450d00200810002206450d0a2006200420082001411c6c2201200120084b1b10f802210120041001200121040c010b200810002204450d090b200d42808080807083200b84210d0b2004200d422088a7411c6c6a2201201141087622083b00012001200a36021020012012360204200120113a0000200141036a20084110763a0000200141186a2005360200200141146a20033602002001410c6a200c360200200141086a2013360200200d4280808080107c210d201041016a22102009490d000c220b0b200241e880046a200241ec006a280200360200200241e080046a2201200241e4006a2902003703002002200229025c3703d88004200128020021044100210520022802e48004210120022802d8800421084100210303402005411f4b0d4d20042001460d342001417f460d142004200141016a220a490d13200820016a2d0000220941ff00712005411f71742003722103200541076a2105200a21012009418001710d000b200241e480046a200a36020041042104410d200341ff01712005411f4b20096741686a41ff01714104497122051b4100200341807e7120051b7221012005450d294200210d0c4d0b200241e880046a200241ec006a280200360200200241e080046a2208200241d8006a410c6a2902003703002002200229025c3703d88004410021014100210303402001411f4b0d482008280200220a200241d880046a410c6a22092802002205460d31200541016a21042005417f460d11200a2004490d1020022802d8800420056a2d0000210520092004360200200541ff00712001411f71742003722103200141076a21012005418001710d000b41042104410d200341ff01712001411f4b20056741686a41ff01714104497122011b4100200341807e7120011b7221102001450d272010210a0c480b200241e880046a200241ec006a280200360200200241e080046a2208200241d8006a410c6a2902003703002002200229025c3703d88004410021014100210303402001411f4b0d432008280200220a200241d880046a410c6a22092802002205460d2e200541016a21042005417f460d0e200a2004490d0d20022802d8800420056a2d0000210520092004360200200541ff00712001411f71742003722103200141076a21012005418001710d000b41042104410d20032001411f4b20056741686a41ff01714104497122011b41ff01714100200341807e7120011b7221052001450d254200210d4200210b0c430b200241e880046a200241ec006a280200360200200241e080046a2201200241e4006a2902003703002002200229025c3703d88004200128020021044100210520022802e48004210120022802d8800421084100210303402005411f4b0d3d20042001460d2c2001417f460d0b2004200141016a220a490d0a200820016a2d0000220941ff00712005411f71742003722103200541076a2105200a21012009418001710d000b200241e480046a200a36020041042104410d200341ff01712005411f4b20096741686a41ff01714104497122051b4100200341807e7120051b7221012005450d234200210d0c3d0b200241e880046a200241ec006a280200360200200241e080046a2201200241e4006a2902003703002002200229025c3703d88004200128020021044100210520022802e48004210120022802d8800421084100210303402005411f4b0d3820042001460d292001417f460d082004200141016a220a490d07200820016a2d0000220941ff00712005411f71742003722103200541076a2105200a21012009418001710d000b200241e480046a200a36020041042104410d200341ff01712005411f4b20096741686a41ff01714104497122011b4100200341807e7120011b7221052001450d214200210d0c380b200241e880046a200241ec006a280200360200200241e080046a2208200241d8006a410c6a2902003703002002200229025c3703d88004410021014100210303402001411f4b0d332008280200220a200241d880046a410c6a22092802002205460d27200541016a21042005417f460d05200a2004490d0420022802d8800420056a2d0000210520092004360200200541ff00712001411f71742003722103200141076a21012005418001710d000b41042104410d20032001411f4b20056741686a41ff01714104497122011b41ff01714100200341807e7120011b72210c20010d33200c450d184200210d200241d880046a410c6a2111200241d880046a41086a210e200241ec006a2114200241d8006a41106a210f2002412a6a2116200241296a2117200241ea006a2118200241e9006a211941042104410021100240034002400240200e280200220920112802002203470d0041012113200241013a004820144101360200200241d8006a410c6a4101360200200241d8006a41086a41e0c3c1003602002002410f360204200f20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d20162f0100210820172d00002109200241206a41086a2d000021012002280224210620022802202103410521050c010b200341016a210102400240024002400240024002400240024002400240024002402003417f460d0020092001490d0120022802d88004221220036a2d0000210a2011200136020041012113411721050240024002400240024002400240200a41e000470d00200341036a210641002105410021070340200621082005411f4b0d0220092001460d032001417f460d062009200141016a220a490d07201220016a2d000021032011200a360200200341ff00712005411f71742007722107200841016a2106200541076a2105200a21012003418001710d000b410d20072005411f4b20036741686a41ff01714104497122011b41ff01714100200741807e7120011b7221072001450d04200721050c030b0c130b410f21050c010b200241013a004820144101360200200241d8006a410c6a4101360200200241d8006a41086a41e0c3c1003602002002410f360204200f20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d200241206a41086a280200211a2002280224211b2002280220211c410521050b201c2103201b2106201a21010c0f0b41012105024002400240024002400240024002402007450d00410120096b211d410021034100210603402006210a201d20086a4102460d032008450d0d20092008490d0e201220086a417f6a2c000021012011200836020020014100480d04200141017441807f71200172220141ff017141847e6a220641034b0d054100210102400240024002400240024020060e0400010203000b41032101200a2003460d030c040b41022101200a2003460d020c030b410121010b200a2003470d010b200341016a22062003490d752003410174221e20062006201e491b22064100480d75024002402003450d0020061000221e450d12201e200520062003200320064b1b10f802210320051001200321050c010b200610002205450d110b200621030b2005200a6a20013a0000200841016a2108200a41016a22062007490d000c020b0b41002103410021060b200241d8006a200241d880046a10ac02024020022802584101470d0020182f0100210820192d00002109200f2d00002101200241d8006a410c6a2802002106200241d8006a41086a280200211d20022f015e210720022d005d210a20022d005c2112410121132003450d140c130b41042112200228025c2201450d0320014101470d04200e280200220a20112802002201470d05200241013a004820144101360200200241d8006a410c6a4101360200200241d8006a41086a41e0c3c1003602002002410f360204200f20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d4105211220162f0100221f210820172d000022202109200241206a41086a2d00002221210120022802242222210620022802202223211d4101211320030d120c130b200241013a000020144101360200200241d8006a410c6a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200f200241186a3602002002410136025c200241b08fc20036025820022002360218200241206a200241d8006a104d200241206a41086a28020021242002280224212520022802202126410041ff0171410874410572210a2003450d100c0f0b200141ff0171410874411872210a20030d0e0c0f0b200141ff0171410874410672210a20030d0d0c0e0b410421090c0b0b41c6c4c100211d412421064101211320030d0d0c0e0b200141016a21092001417f460d07200a2009490d0820022802d8800420016a2c0000210a2011200936020002400240200a4100480d0041062112200a41017441807f71200a72220a41ff017141fc01490d01200a417f7321090c0b0b411821120b201f21082020210920212101202221062023211d4101211320030d0c0c0d0b417f200141016a107a000b200141016a20091076000b417f2001107a000b200120091076000b417f2008107a000b200820091076000b200641011019000b417f2009107a000b2009200a1076000b200541107621072005410876210a4100211341e00021010c050b200510010b202621032025210620242101200a21050c020b200510010b201d2103201221050c010b2001411076210820014108762109200541107621072005410876210a0b200941ff0171410874200141ff0171722008411074722101200a41ff0171410874200541ff017172200741107472210a024020130d000240200d422088a72205200da7470d00200541016a22092005490d5d20054101742208200920092008491bad220b4204862215422088a70d5d2015a722094100480d5d024002402005450d00200910002208450d052008200420092005410474220520092005491b10f802210520041001200521040c010b200910002204450d040b200d42808080807083200b84210d0b2004200d422088a74104746a2205200136020c20052006360208200520033602042005200a360200200d4280808080107c210d201041016a2210200c490d010c1c0b0b2006ad422086210b2003ad21150240200d422088a72205450d00200541047421032004210503400240200541046a280200450d00200528020010010b200541106a2105200341706a22030d000b0b200b201584210b0240200da7450d00200410010b200a220c410876210520022802dc80040d350c360b200941041019000b200841041019000b200a20061076000b2005200a107a000b2004200a1076000b417f2004107a000b200141016a20041076000b417f200141016a107a000b200141016a20041076000b417f200141016a107a000b2004200a1076000b417f2004107a000b2004200a1076000b417f2004107a000b200141016a20041076000b417f200141016a107a000b2004200a1076000b417f2004107a000b200541016a20031076000b417f200541016a107a000b200520031076000b417f2005107a000b20084108762106200241e8006a280200210a200241e4006a2802002103200241d8006a41086a280200210920082111200c0d070c080b20124108762106200241e8006a280200210a200241e4006a2802002103200241d8006a41086a2802002109201221110c080b20114108762106200241e8006a280200210a200241e4006a2802002103200241d8006a41086a28020021090c070b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410221010c470b20024103410220012005461b3a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821012002290320210b0240200d422088a72205450d00200541047421032004210503400240200541046a280200450d00200528020010010b200541106a2105200341706a22030d000b0b4105210c41002105200da7450d1b200410010c1b0b4200210d0b2002412c6a28020021012002280230210502402002280224450d00200228022010010b024020012005470d00410c21010c450b20024103410220012005461b3a0000200241d8006a41146a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210a20022903d88004210b0240200d422088a72201450d0020042001411c6c6a210920042103034002402003410c6a2802002205450d0020032802042101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b2001210320012009470d000b0b4105210941002101200da7450d32200410010c320b200241013a0038200241ec80046a4101360200200241e480046a4101360200200241d880046a41086a41e0c3c1003602002002410f36021c200241e880046a200241186a360200200241013602dc8004200241b08fc2003602d880042002200241386a3602182002200241d880046a104d200241086a280200210a20022802042103200228020021090240200228024c450d00200228024810010b4100210641052111200c450d010b200c4104742105201221010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b2013450d00201210010b201141ff01712108200641087421062003ad422086210b2009ad21150240200d422088a72201450d0020042001411c6c6a210920042103034002402003410c6a2802002205450d0020032802042101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b2001210320012009470d000b0b20062008722109200b201584210b200da7450d11200410012009410876210120022802240d2d0c2e0b024002400240024002400240024002400240024002400240024002402005450d004200210d41042104200241d8006a410c6a210c200241d8006a41086a2112410021060340200241d8006a200241d880046a10bc02200c280200210a20122802002109200228025c210820022802584101460d03200241d880046a41086a2802002207200241d880046a410c6a22112802002201460d04200141016a21032001417f460d0a20072003490d0b20022802d8800420016a2d0000210120112003360200200141034b0d050240024002400240024020010e0400030102000b200241d8006a200241d880046a10ac02200228025c210320022802584101460d0d410021070c030b200241d8006a200241d880046a10ac02200228025c210320022802584101460d0a410221070c020b200241d8006a200241d880046a10ac02200228025c210320022802584101460d08410321070c010b200241d8006a200241d880046a10ac02200228025c210320022802584101460d09410121070b0240200d422088a72201200da7470d00200141016a22112001490d4820014101742213201120112013491bad220b42147e2215422088a70d482015a722114100480d48024002402001450d00201110002213450d0f201320042011200141146c2201200120114b1b10f802210120041001200121040c010b201110002204450d0e0b200d42808080807083200b84210d0b2004200d422088a741146c6a22012003ad4220862007ad84220b37020c2001200a3602082001200936020420012008360200200d4280808080107c210d200641016a22062005490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410821010c4c0b20024103410220012005461b3a0000200241d8006a41146a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821012002290320210b0240200d422088a72205450d00200541146c21032004210503400240200541046a280200450d00200528020010010b200541146a21052003416c6a22030d000b0b4105210541002103200da7450d24200410010c240b200b42808080807083200241e8006a35020084212720082105200921060c0a0b200241013a0000200241ec006a4101360200200241e4006a4101360200200241e0006a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc20036025820022002360218200241206a200241d8006a104d20022902242115200228022021064105210341002105410021010c080b410a2103410021050c070b20034180807c71210520034108762101200241e4006a2902002115200241d8006a41086a28020021060c060b20034180807c71210520034108762101200241e4006a2902002115200241d8006a41086a28020021060c050b20034180807c71210520034108762101200241e4006a2902002115200241d8006a41086a28020021060c040b20034180807c71210520034108762101200241e4006a2902002115200241d8006a41086a28020021060c030b417f2003107a000b200320071076000b201141041019000b200b428080808070832015422088842127200141ff0171410874200572200341ff01717221052015a7210a2009450d00200810010b200aad422086210b2006ad21150240200d422088a72201450d00200141146c21032004210103400240200141046a280200450d00200128020010010b200141146a21012003416c6a22030d000b0b200b201584210b2027a72101200da7450d07200410012005410876210320022802dc80040d170c180b02400240024002402001450d004200210d41042104410021030340200241d8006a200241d880046a10ac02200228025c210a20022802584101460d030240200d422088a72205200da7470d00200541016a22092005490d3d20054101742208200920092008491bad220b4202862215422088a70d3d2015a722094100480d3d024002402005450d00200910002208450d072008200420092005410274220520092005491b10f802210520041001200521040c010b200910002204450d060b200d42808080807083200b84210d0b2004200d422088a74102746a200a360200200d4280808080107c210d200341016a22032001490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410421010c410b20024103410220012005461b3a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821032002290320210b4105210141002105200da7450d1e200410010c1e0b200241e8006a2802002103200241e0006a290300210b0240200da7450d00200410010b200a2201410876210520022802dc80040d1c0c1d0b200941041019000b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402005450d004200210d41042104200241d8006a410c6a2107200241d8006a41086a21084100210e0340200241d8006a200241d880046a10bc02200728020021112008280200210c200228025c211220022802584101460d03200241d8006a200241d880046a10bc022007280200210f20082802002113200228025c211020022802584101460d04200241d880046a41086a2802002209200241d880046a410c6a22062802002203460d05200341016a210a2003417f460d152009200a490d1620022802d88004221420036a2d000021012006200a360200200141034b0d0602400240024002400240024002400240024020010e0400030102000b200241d8006a200241d880046a10ac0220022802584101460d12200228025c2103410021060c070b200241d8006a200241d880046a10bd022008290300210b200228025c210320022802584101460d10410221060c060b2009200a460d0d200341026a2116200a417f460d2220092016490d232014200a6a2c000021012006201636020020014100480d12200141017441807f71200172220141ff017141847e6a220641034b0d164100210a024020060e0400020304000b4103210a20092016470d040c170b2009200a460d0d200341026a2103200a417f460d1d20092003490d1e2014200a6a2c000021012006200336020020014100480d10200141017441807f71200172220141ff017141f001470d12200241d8006a200241d880046a10bd022008290300210b200228025c210320022802584101460d17410121060c040b4102210a20092016470d020c150b4101210a0b20092016460d130b200341036a21062016417f460d1b20092006490d1c201420166a2d00002101410c2103200241d880046a410c6a2006360200410321064100210902402001450d0020014101470d22410121090b0b0240200d422088a72201200da7470d00200141016a22142001490d5a20014101742216201420142016491bad221542287e2227422088a70d5a2027a722144100480d5a024002402001450d00201410002216450d1a201620042014200141286c2201200120144b1b10f802210120041001200121040c010b201410002204450d190b200d42808080807083201584210d0b2004200d422088a741286c6a220120063a00182001201036020c200120113602082001200c36020420012012360200200141206a200b3702002001411c6a20033602002001411a6a20093a0000200141196a200a3a0000200141146a200f360200200141106a2013360200200d4280808080107c210d200e41016a220e2005490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410321010c5e0b20024103410220012005461b3a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821032002290320210b0240200d422088a72201450d00200141286c21052004210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101200541586a22050d000b0b4105210541002101200da7450d3f200410010c3f0b200241e8006a280200210320122105200c21090c1e0b200241e8006a28020021032010210520132109200f2111200c0d1c0c1d0b200241013a0000200241ec006a4101360200200241e4006a4101360200200241e0006a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc20036025820022002360218200241206a200241d8006a104d0c190b410921030c170b200241013a0048200241ec006a4101360200200241e4006a4101360200200241e0006a41e0c3c1003602002002410f360204200241e8006a20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d0c170b200241013a0048200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f360204200241e8006a20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d200241206a41086a28020021052002290320210b410521030c060b200241d8006a41086a200241d8006a41106a2802003602002003411876211420034110762116200341087621010c0a0b200241e4006a2902002115200241e0006a280200210920022d005f211420022d005e211620022d005d210120022d005c21030c150b411821030c020b411821030c110b410721030b0b200141ff017141087420037221030c030b410621030c0d0b200241013a0048200241ec006a4101360200200241e4006a4101360200200241e0006a41e0c3c1003602002002410f360204200241e8006a20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d0c0d0b200241e8006a28020021050b200241d8006a41086a20053602002003411876211420034110762116200341087621010b2002200b370358200229025c2115200ba721090c0b0b417f200a107a000b200a20091076000b201441041019000b417f2003107a000b200320091076000b417f2006107a000b200620091076000b417f2016107a000b201620091076000b0c010b2002290224211520022802202109410521030b200141ff0171410874200341ff017172201641ff01714110747220144118747221052015422088a721032015a7211102402013450d00201010010b200c450d010b201210010b2011ad422086210b2009ad21150240200d422088a72201450d00200141286c210a2004210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141286a2101200a41586a220a0d000b0b200b201584210b200da7450d08200410012005410876210120022802dc80040d1e0c1f0b02400240024002400240024002402010450d004200210d41042104200241d8006a410c6a2109200241d8006a41086a2108410021070340200241d8006a200241d880046a10ac02200228025c210a20022802584101460d03200241d8006a200241d880046a10aa022009280200210520082802002103200228025c210620022802584101460d04200241d8006a200241d880046a10ad0220022802584101460d05200828020021112009280200210c200241206a41086a200228025c2201360200200241206a410c6a2001200c4102746a36020020022011360224200220013602202002200241206a1043200241086a28020021112002280204210c200228020021120240200d422088a72201200da7470d00200141016a22132001490d3e2001410174220e20132013200e491bad220b421c7e2215422088a70d3e2015a722134100480d3e024002402001450d0020131000220e450d0a200e200420132001411c6c2201200120134b1b10f802210120041001200121040c010b201310002204450d090b200d42808080807083200b84210d0b2004200d422088a7411c6c6a2201200a41087622133b000120012012360210200120063602042001200a3a0000200141036a20134110763a0000200141186a2011360200200141146a200c3602002001410c6a2005360200200141086a2003360200200d4280808080107c210d200741016a22072010490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410a21010c420b20024103410220012005461b3a0000200241d8006a41146a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821092002290320210b0240200d422088a72201450d0020042001411c6c6a210a20042103034002402003410c6a2802002205450d0020032802042101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b200121032001200a470d000b0b4105210a41002101200da7450d27200410010c270b200241e8006a2802002109200241e4006a2802002105200241e0006a28020021030c020b200241e8006a28020021092006210a0c010b200241d8006a41106a2802002109200241e4006a2802002108200241d8006a41086a2802002107200228025c210a02402005450d0020054104742105200621010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b02402003450d00200610010b20072103200821050b2005ad422086210b2003ad21150240200d422088a72201450d0020042001411c6c6a210820042103034002402003410c6a2802002205450d0020032802042101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b0240200341086a280200450d00200341046a28020010010b2003411c6a21010240200341146a280200450d00200328021010010b2001210320012008470d000b0b200b201584210b200da7450d0a20041001200a410876210120022802dc80040d220c230b201341041019000b0240024002400240024002400240024002400240024002402001450d004200210d41042104200241d880046a410c6a2109200241d880046a41086a210c410021110340200c280200220a20092802002205460d03200541016a21032005417f460d0a200a2003490d0b20022802d8800420056a2c000021052009200336020020054100480d04200541017441807f71200572220541ff017141f001470d05200241d8006a200241d880046a10bd0220022f005d20022d005f41107472210a200241d8006a410c6a2802002108200241d8006a41086a280200210620022d005c210720022802584101460d080240200d422088a72205200da7470d00200541016a22032005490d4220054101742212200320032012491bad220b420c7e2215422088a70d422015a722034100480d42024002402005450d00200310002212450d0f2012200420032005410c6c2205200520034b1b10f802210520041001200521040c010b200310002204450d0e0b200d42808080807083200b84210d0b2004200d422088a7410c6c6a2205200a3b00012005200836020820052006360204200520073a0000200541036a200a4110763a0000200d4280808080107c210d201141016a22112001490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410521010c460b20024103410220012005461b3a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821032002290320210b4105210141002105200da7450d2f200410010c2f0b200241013a0000200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc20036025820022002360218200241206a200241d8006a104d200241206a41086a28020021032002280224210820022802202106410521070c030b411821070c010b410721070b0b200541ff0171210a0c010b200241e8006a28020021030b200a410874200741ff01717221012008ad4220862006ad84210b200da7450d0d200410012001410876210520022802dc80040d270c280b417f2003107a000b2003200a1076000b200341041019000b410021032002410036020820024201370300200241d8006a41004180800110f7021a41002105410021074101210602400240024002400240024002400240024002400240024002402008450d004100210a200141086a2106200141046a2111034020112802002207200628020022046b2008200a6b220541808001200541808001491b2205490d02200420056a22092004490d0720072009490d08200241d8006a200128020020046a200510f8021a200620093602002002200241d8006a2005102520082005200a6a220a4b0d000b200241086a280200210520022802042107200228020021060b410021014100210403402001411f4b0d0220052003460d03200520034d0d08200620036a2d0000220a41ff00712001411f71742004722104200141076a2101200341016a22092103200a418001710d000b20014120490d04200a6741686a41ff017141044f0d04410d21010c030b200241013a0048200241ec80046a4101360200200241e480046a41013602002002410f36021c200241e0c3c1003602e08004200241013602dc8004200241b08fc2003602d880042002200241c8006a3602182002200241186a3602e88004200241206a200241d880046a104d200228022821052002290320210d2002280204450d35200228020010010c350b410f21010c010b200241013a0020200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc2003602582002200241206a3602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210520022903d88004210d410521010b200d42808080807083200d42ffffffff0f8384210d2007450d340c070b024002400240024002402004450d00410021032002410036025020024201370348200241d8006a410041800810f7021a0340200520096b200420036b22014180082001418008491b2201490d02200920016a220a2009490d092005200a490d0a200241d8006a200620096a200110f8021a200241c8006a200241d8006a20011025200a21092004200120036a22034b0d000b200228024c2104200241d8006a20022802482203200241d0006a28020022091086014101210120022802584101470d02200241306a200229025c37030020022003360224200241206a41047221030c030b41002104410121034200210d20052009490d030c090b200241013a0038200241ec80046a4101360200200241e480046a41013602002002410f36021c200241e0c3c1003602e08004200241013602dc8004200241b08fc2003602d880042002200241386a3602182002200241186a3602e880042002200241d880046a104d2002290300210d200228020821050240200228024c450d00200228024810010b41052101200d42808080807083200d42ffffffff0f8384210d20070d090c360b20022003360224200241206a4104722103410021010b2002412c6a2009360200200241206a41086a220920043602002002200136022002402001450d0002402009280200450d00200328020010010b410821014200210d20070d080c350b2002280224220341087621042009290300210d2005200a22094f0d060b20092005107a000b20042009107a000b200920071076000b200341016a20051076000b2009200a107a000b200a20051076000b0240200520096b2201417f4c0d00024002402001450d002001100022050d01200141011019000b410121050b200241003602602002200136025c20022005360258200241d8006a200620096a20011025200229025c210b2002280258210502402007450d00200610010b2004410874200341ff0171722104410121010c3c0b102c000b200610010c2c0b200241013a0048200241ec006a4101360200200241e4006a41013602002002410f360204200241e0c3c1003602602002410136025c200241b08fc2003602582002200241c8006a36020020022002360268200241206a200241d8006a104d200228022821012002290320210b4105210c4105410876210520022802dc8004450d0e0c0d0b200241d880046a410c6a2004360200200241013a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d20022802282101410521052002350224422086200235022084210b0b2005410876210320022802dc8004450d100c0f0b200241d880046a410c6a2004360200200241013a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d2002350224422086210d200228022821032002350220210b410521010c120b200241013a0048200241ec006a4101360200200241e4006a41013602002002410f360204200241e0c3c1003602602002410136025c200241b08fc2003602582002200241c8006a36020020022002360268200241206a200241d8006a104d20022802282103410521052002350224422086200235022084210b0b2005410876210120022802dc8004450d160c150b200241013a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821094105210a2002350224422086200235022084210b0b200a410876210120022802dc8004450d180c170b200241d880046a410c6a2004360200200241013a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d20022802282103410521012002350224422086200235022084210b0b2001410876210520022802dc8004450d1a0c190b200241013a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210a4105210920023502dc800442208620023502d8800484210b0b200941087621012002280224450d1c0c1b0b410f210c0b200c410876210520022802dc8004450d010b20022802d8800410010b20004101360200200041106a2001360200200041086a200b37020020002005410874200c41ff017172360204200241f080046a24000f0b200241e480046a20013602004200210d410f21050b200d420084210b2005410876210320022802dc8004450d010b20022802d8800410010b20004101360200200041106a2001360200200041086a200b37020020002003410874200541ff017172360204200241f080046a24000f0b200241e480046a20013602004200210d410f21010b4200210b0b200d200b84210b2001410876210520022802dc8004450d010b20022802d8800410010b20004101360200200041106a2003360200200041086a200b37020020002005410874200141ff017172360204200241f080046a24000f0b410f21054200210b4200210d0b200d200b84210b2005410876210120022802dc8004450d010b20022802d8800410010b20004101360200200041106a2003360200200041086a200b37020020002001410874200541ff017172360204200241f080046a24000f0b410f210a0b4200420084210b200a410876210120022802dc8004450d010b20022802d8800410010b20004101360200200041106a2009360200200041086a200b37020020002001410874200a41ff017172360204200241f080046a24000f0b200241e480046a20013602004200210d410f21010b200d420084210b2001410876210520022802dc8004450d010b20022802d8800410010b20004101360200200041106a2003360200200041086a200b37020020002005410874200141ff017172360204200241f080046a24000f0b410f21090b4200420084210b200941087621012002280224450d010b200228022010010b20004101360200200041106a200a360200200041086a200b37020020002001410874200941ff017172360204200241f080046a24000f0b200241013a0020200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc2003602582002200241206a3602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210520022903d88004210d0b410521010c010b410f21010b2000200136020420004101360200200041106a2005360200200041086a200d370200200241f080046a24000f0b200241d880046a41106a200141106a280200360200200241d880046a41086a200141086a290200370300200220012902003703d88004200241d8006a200241d880046a10ac02024020022802584101470d002000200229025c370204200041013602002000410c6a200241d8006a410c6a29020037020020022802dc8004450d0e20022802d880041001200241f080046a24000f0b200228025c210420022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410010b02402001450d00410921010c0d0b20024103410220011b3a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200241e3006a200241286a2802003600002002200229032037005b200041053a000420004101360200200020022900583700052000410c6a200241df006a290000370000200241f080046a24000f0b200241106a200241ec006a280200360200200241086a2201200241e4006a2902003703002002200229025c3703002001280200210441002105200228020c210120022802002108410021030240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024003402005411f4b0d0120042001460d032001417f460d152004200141016a220a490d16200820016a2d0000220941ff00712005411f71742003722103200541076a2105200a21012009418001710d000b2002410c6a200a36020041042104410d20032005411f4b20096741686a41ff01714104497122011b41ff01714100200341807e7120011b72210320010d012003450d03200241e1006a21124200210d200241386a41086a211d200241206a41106a2126200241206a410c6a2111200241d8006a41146a211b410421044100211a0340200241d8006a200210ac0220022802584101460d0b200228025c21064100210a201d410036020020024201370338200241d8006a41004180800110f7021a024002402006450d002002410c6a220e2802002101200241086a2802002107410021092002280200210c0340200720016b200620096b220541808001200541808001491b2205490d09200120056a22082001490d1a20072008490d1b200241d8006a200c20016a200510f8021a200241386a200241d8006a20051025200821012006200520096a22094b0d000b200e2008360200201d2802002108200228023c2101200228023821070c010b4101210741002101410021080b201a41016a211a2026200836020020114100360200200241206a41086a220e20083602002002200136022420022007360220410021014100210603402001411f4b0d092008200a460d0a200a417f460d1a2008200a41016a2209490d1b2007200a6a2d0000210520112009360200200541ff00712001411f71742006722106200141076a21012009210a2005418001710d000b410d20062001411f4b20056741686a41ff01714104497122011b41ff01714100200641807e7120011b72210720010d1341002105024002402007450d004100210c410421094104211e410021170340200241d8006a200241206a10ac02200228025c210620022802584101460d0f200e280200220820112802002201460d10200141016a210a2001417f460d1f2008200a490d20200228022020016a2c000021012011200a36020020014100480d11200141017441807f71200172220141ff017141fb014d0d1202402017200c470d00200c41016a220a200c490d2f200c4101742208200a200a2008491b2208ad420386220b422088a70d2f200ba7220a4100480d2f02400240200c450d00200a1000220f450d21200f201e200a200c410374220c200c200a4b1b10f802210a201e1001200a211e0c010b200a1000221e450d200b2008210c0b201e20096a220a201c41807e712001417f7341ff017172221c3a0000200a417c6a2006360200200941086a2109201741016a22172007490d000c020b0b4104211e4100210c410021170b4101210a4108210e41002109410021080340200241d8006a200241206a10ab0220022802584101460d0b200241d880046a41026a2201201241026a2d00003a0000200220122f00003b01d88004200241d8006a410c6a2802002114200241d8006a41106a280200210f201b280200211602400240200241d8006a41086a2d000022074106470d00200a417f6a210a0c010b2007417e6a41024b0d004104200a41016a22252025200a4922241b21064115201020241b211041c29bc100201320241b21132025200a490d142006210a0b200241d8006a41026a220620012d00003a0000200220022f01d880043b0158024020082009470d00200941016a22012009490d2d20094101742225200120012025491b2225ad420486220b422088a70d2d200ba722014100480d2d024002402009450d00200110002224450d222024200e200120094104742209200920014b1b10f8022101200e10012001210e0c010b20011000220e450d210b202521090b200e20056a220120073a00002001410c6a2016360200200141086a200f360200200141046a2014360200200141036a20062d00003a0000200141016a20022f01583b0000200541106a2105200841016a2108200a0d000b202628020021012011280200210502402002280224450d00200228022010010b20052001470d140240200d422088a72201200da7470d00200141016a22052001490d2c2001410174220a20052005200a491bad220b42187e2215422088a70d2c2015a722054100480d2c024002402001450d0020051000220a450d22200a20042005200141186c2201200120054b1b10f802210120041001200121040c010b200510002204450d210b200d42808080807083200b84210d0b2004200d422088a741186c6a2201200e36020c200120173602082001200c3602042001201e360200200141146a2008360200200141106a2009360200200d4280808080107c210d201a2003490d000c050b0b2002410c6a2001360200410f21030b2003410876210120022802040d230c240b2002410c6a2004360200200241013a0020200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc2003602582002200241206a3602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210a20022903d88004210b410521034105410876210120022802040d220c230b4200210d0b2002410c6a28020021012002280210210502402002280204450d00200228020010010b20012005470d01410b21010c2c0b2002410c6a2001360200200241013a0047200241ec80046a4101360200200241d880046a410c6a4101360200200241d880046a41086a41e0c3c1003602002002410f36021c200241e880046a200241186a360200200241013602dc8004200241b08fc2003602d880042002200241c7006a360218200241c8006a200241d880046a104d200241c8006a41086a280200210a200228024c21102002280248211341052106200228023c450d1e200228023810010c1e0b20024103410220012005461b3a0020200241d8006a41146a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc2003602582002200241206a3602182002200241186a360268200241d880046a200241d8006a104d20022802e08004210a20022903d88004210b0240200d422088a72201450d002004200141186c6a21092004210303400240200341046a280200450d00200328020010010b0240200341146a2802002205450d00200328020c2101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b200341186a21010240200341106a280200450d002003410c6a28020010010b2001210320012009470d000b0b4105210341002101200da7450d1f200410010c1f0b410f210620022802240d1b0c1c0b200241013a0048200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc2003602582002200241c8006a360218200241d880046a200241d8006a104d200241d880046a41086a280200210a20022802dc8004211020022802d8800421134105210620022802240d1a0c1b0b200241e8006a280200210a200241e4006a2802002110200241e0006a2802002113200228025c21062008450d160c150b200241e8006a280200210a200241e4006a2802002110200241e0006a2802002113200228025c21060c190b200241e8006a280200210a200241e4006a2802002110200241e0006a2802002113200c0d150c160b200241013a0048200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc2003602582002200241c8006a360218200241d880046a200241d8006a104d200241e280046a2f01002105200241e180046a2d00002103200241d880046a41086a2d0000210a20022802dc8004211020022802d880042113410521090c030b411821090c010b410621090b0b200341ff0171410874200a41ff017172200541107472210a200141ff01714108742009722106200c450d110c100b024020074109470d00200f41ffffffff0371450d00201410010b20080d0d0c0e0b2007210620022802240d100c110b20024103410220052001461b3a0048200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200241d8006a41106a200241186a3602002002410136025c200241b08fc2003602582002200241c8006a360218200241d880046a200241d8006a104d200241d880046a41086a280200210a20022802dc8004211020022802d88004211302402008450d0020084104742105200e21010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b02402009450d00200e10010b41052106200c450d10201e10010c100b417f200141016a107a000b200141016a20041076000b20012008107a000b200820071076000b417f200a41016a107a000b200a41016a20081076000b200a41041019000b417f200a107a000b200a20081076000b200141081019000b200541041019000b200e21010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b02402009450d00200e10010b200c450d010b201e10010b2002280224450d010b200228022010010b2010ad422086210b2013ad21150240200d422088a72201450d002004200141186c6a21092004210303400240200341046a280200450d00200328020010010b0240200341146a2802002205450d00200328020c2101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b200341186a21010240200341106a280200450d002003410c6a28020010010b2001210320012009470d000b0b200b201584210b0240200da7450d00200410010b2006220341087621012002280204450d010b200228020010010b20004101360200200041106a200a360200200041086a200b37020020002001410874200341ff017172360204200241f080046a24000f0b200241e880046a200241ec006a280200360200200241e080046a2208200241d8006a410c6a2902003703002002200229025c3703d88004410021014100210302400240024002400240024002400240024002400240024003402001411f4b0d012008280200220a200241d880046a410c6a22092802002205460d02200541016a21042005417f460d05200a2004490d0620022802d8800420056a2d0000210520092004360200200541ff00712001411f71742003722103200141076a21012005418001710d000b41042104410d20032001411f4b20056741686a41ff01714104497122051b41ff01714100200341807e7120051b7221012005450d034200210d4200210b0c020b410f21014200210b4200210d0c010b200241013a0048200241ec006a4101360200200241e4006a41013602002002410f360204200241e0c3c1003602602002410136025c200241b08fc2003602582002200241c8006a36020020022002360268200241206a200241d8006a104d2002350224422086210d2002280228210a2002350220210b410521010b200d200b84210b2001410876210520022802dc8004450d090c080b0240024002400240024002400240024002400240024002402001450d004200210d200241d880046a410c6a2108200241d880046a41086a211341042104410021120340201328020022092008280200220a460d03200a41016a2105200a417f460d0f20092005490d1020022802d880042207200a6a2c000021032008200536020020034100480d04200341017441807f71200372220341ff017141847e6a221141034b0d05410021060240024002400240024020110e0400010203000b4103210620092005470d030c0c0b4102210620092005470d020c0b0b410121060b20092005460d090b200a41026a21032005417f460d1120092003490d12200720056a2d00002105200820033602004100210302402005450d0020054101470d0a41800221030b200241d8006a200241d880046a10aa02200241d8006a410c6a2802002109200241d8006a41086a2802002107200228025c211120022802584101460d0b0240200d422088a72205200da7470d00200541016a220a2005490d1820054101742210200a200a2010491bad220b4204862215422088a70d182015a7220a4100480d18024002402005450d00200a10002210450d1620102004200a20054104742205200a2005491b10f802210520041001200521040c010b200a10002204450d150b200d42808080807083200b84210d0b2004200d422088a74104746a2205200c4180807c71200672200372220c36020c200520093602082005200736020420052011360200200d4280808080107c210d201241016a22122001490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410721010c1c0b20024103410220012005461b3a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d2002280228210a2002290320210b0240200d422088a72201450d00200420014104746a2109200421030340024020032802082205450d0020032802002101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b200341106a21010240200341046a280200450d00200328020010010b2001210320012009470d000b0b4105210141002105200da7450d12200410010c120b200241013a0048200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f360204200241e8006a20023602002002410136025c200241b08fc2003602582002200241c8006a360200200241206a200241d8006a104d200241206a41086a280200210a2002280224210920022802202107410521010c030b411821010c010b410621010b0b200341ff017141087420017221110c040b200241013a0000200241ec006a4101360200200241e4006a4101360200200241d8006a41086a41e0c3c1003602002002410f36021c200241e8006a200241186a3602002002410136025c200241b08fc20036025820022002360218200241206a200241d8006a104d200241206a41086a280200210a2002280224210920022802202107410521010c010b410c21010b200541ff017141087420017221110c010b200241e8006a280200210a0b2009ad422086210b2007ad21150240200d422088a72201450d00200420014104746a2109200421030340024020032802082205450d0020032802002101200541047421050340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010010b200141106a2101200541706a22050d000b0b200341106a21010240200341046a280200450d00200328020010010b2001210320012009470d000b0b200b201584210b0240200da7450d00200410010b20112201410876210520022802dc80040d070c080b417f2004107a000b2004200a1076000b417f2005107a000b200520091076000b417f2003107a000b200320091076000b200a41041019000b20022802d8800410010b20004101360200200041106a200a360200200041086a200b37020020002005410874200141ff017172360204200241f080046a24000f0b200241e880046a200241ec006a280200360200200241e080046a2201200241e4006a2902003703002002200229025c3703d88004200128020021044100210520022802e48004210120022802d88004210841002103024002400240024003402005411f4b0d0120042001460d032001417f460d062004200141016a220a490d07200820016a2d0000220941ff00712005411f71742003722103200541076a2105200a21012009418001710d000b200241e480046a200a36020041042104410d200341ff01712005411f4b20096741686a41ff01714104497122011b4100200341807e7120011b7221052001450d034200210d0c010b200241e480046a20013602004200210d410f21050b200d420084210b2005410876210120022802dc80040d070c080b200241d880046a410c6a2004360200200241013a0000200241ec006a4101360200200241d8006a410c6a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d20022802282103410521052002350224422086200235022084210b0c050b0240024002402005450d004200210d41042104200241d8006a410c6a210c200241d8006a41086a21124100210a0340200241d8006a200241d880046a10bd0220022d005c210320022802584101460d0320022d005f210920022f005d2108200c2802002106201228020021070240200d422088a72201200da7470d00200141016a22112001490d0520014101742213201120112013491bad220b420c7e2215422088a70d052015a722114100480d05024002402001450d00201110002213450d0a2013200420112001410c6c2201200120114b1b10f802210120041001200121040c010b201110002204450d090b200d42808080807083200b84210d0b2004200d422088a7410c6c6a2201200820094110747222093b000120012007360204200120033a0000200141036a20094110763a0000200141086a2006360200200d4280808080107c210d200a41016a220a2005490d000c020b0b4200210d0b200241e480046a280200210120022802e880042105024020022802dc8004450d0020022802d8800410010b024020012005470d00410621010c090b20024103410220012005461b3a0000200241ec006a4101360200200241e4006a41013602002002410f36021c200241e0c3c1003602602002410136025c200241b08fc200360258200220023602182002200241186a360268200241206a200241d8006a104d200228022821032002290320210b4105210541002101200da7450d07200410010c070b20022f005d20022d005f411074724108742003722105200241d8006a41106a2802002103200241d8006a41086a290300210b200da7450d04200410012005410876210120022802dc80040d050c060b1018000b417f200141016a107a000b200141016a20041076000b201141041019000b2005410876210120022802dc8004450d010b20022802d8800410010b20004101360200200041106a2003360200200041086a200b37020020002001410874200541ff017172360204200241f080046a24000f0b200020013a000420004100360200200041056a20022f00d880043b0000200041186a200b370200200041146a20053602002000410c6a200d370200200041086a2004360200200041206a2002290258370200200041076a200241da80046a2d00003a0000200041286a200241d8006a41086a290200370200200241f080046a24000f0b200241f080046a24000be30602097f017e230041d080016b2202240041002103200141086a2104200141046a21054100210602400240024002400240024002400240024003402003411f4b0d012005280200220720042802002208460d02200841016a21092008417f460d0520072009490d06200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b024020034120490d00410d210320086741686a41ff01714104490d030b2002410036021020024201370308200241186a41004180800110f7021a4100210302402006450d0041002109200141086a2107200141046a210a0340200a2802002205200728020022086b200620096b220341808001200341808001491b2203490d05200820036a22042008490d0820052004490d09200241186a200128020020086a200310f8021a20072004360200200241086a200241186a200310252006200320096a22094b0d000b200241106a28020021030b2002290308210b200041146a2003360200200041106a41003602002000410c6a20033602002000200b37020420004100360200200241d080016a24000f0b410f21030c010b200241013a00a880012002412c6a4101360200200241246a41013602002002410f36029c8001200241e0c3c1003602202002410136021c200241b08fc2003602182002200241a880016a360298800120022002419880016a360228200241b880016a200241186a104d410521030b2000200336020420004101360200200041086a20022902b88001370200200041106a200241b880016a41086a2802003602000c050b200241013a00a78001200241cc80016a4101360200200241b880016a410c6a41013602002002410f36029c8001200241e0c3c1003602c08001200241013602bc8001200241b08fc2003602b880012002200241a780016a360298800120022002419880016a3602c88001200241a880016a200241b880016a104d200241c380016a200241b080016a280200360000200220022903a880013700bb8001200041053a000420004101360200200020022900b880013700052000410c6a200241bf80016a290000370000200228020c450d0420022802081001200241d080016a24000f0b417f2009107a000b200920071076000b20082004107a000b200420051076000b200241d080016a24000bdc0501097f230041e0086b22022400200241286a200110ac02024020022802284101470d002000200229022c370204200041013602002000410c6a200241286a410c6a290200370200200241e0086a24000f0b024002400240024002400240200228022c2203450d00410021042002410036022020024201370318200241286a410041800810f7021a2001410c6a2105200141086a2106034020062802002207200528020022086b200320046b22094180082009418008491b2209490d02200820096a220a2008490d052007200a490d06200241286a200128020020086a200910f8021a2005200a360200200241186a200241286a200910252003200920046a22044b0d000b200228021c2104200241286a20022802182208200241206a280200220a1086014101210920022802284101470d02200241106a200229022c37030020022008360204200241047221080c030b2000428080808010370200200041086a4200370200200241e0086a24000f0b200241013a00af08200241d4086a4101360200200241c0086a410c6a41013602002002410f3602dc08200241e0c3c1003602c808200241013602c408200241b08fc2003602c0082002200241af086a3602d8082002200241d8086a3602d008200241b0086a200241c0086a104d200241cb086a200241b8086a280200360000200220022903b0083700c308200041053a000420004101360200200020022900c0083700052000410c6a200241c7086a2900003700000240200228021c450d00200228021810010b200241e0086a24000f0b2002200836020420024104722108410021090b2002410c6a200a360200200241086a220a20043602002002200936020002402009450d000240200a280200450d00200828020010010b200041083a000420004101360200200241e0086a24000f0b200020082902003702042000410c6a200841086a28020036020020004100360200200241e0086a24000f0b2008200a107a000b200a20071076000ba20401047f230041c0006b2202240002400240024002400240024020012802082203200128020c2204470d00200241013a000f200241346a41013602002002412c6a41013602002002410f36023c200241e0c3c10036022820024101360224200241b08fc20036022020022002410f6a3602382002200241386a360230200241106a200241206a104d2002412a6a200241186a280200360100200220022903103701222002200241266a29010037010620022002290120370300410521030c010b200441016a21052004417f460d0320032005490d04200128020020046a2d00002104410c21032001410c6a20053602002004450d014101210520044101460d020b200020043a0005200020033a000420002002290300370106200041013602002000410c6a2002290106370100200241c0006a24000f0b410021050b200241206a200110ac02024020022802204101470d0020002002290224370204200041013602002000410c6a200241206a410c6a290200370200200241c0006a24000f0b200228022421040240024002402005450d00200241206a200110ac024101210120022802204101470d0120002002290224370204200041013602002000410c6a200241206a410c6a290200370200200241c0006a24000f0b410021010c010b200228022421030b20002004360204200041003602002000410c6a2003360200200041086a2001360200200241c0006a24000f0b417f2005107a000b200520031076000b3802017f017e230041106b220324002003200210a901200329030021042000200341086a29030037030820002004370300200341106a24000bda0402027f017e23004180016b22052400200541106a41186a200241186a290000370300200541106a41106a200241106a290000370300200541106a41086a200241086a2900003703002005200229000037031002400240024002402004417f4c0d00024002402004450d002004100022020d01200441011019000b410121020b200520043602542005200236025020054100360258200541d0006a200320041025200541306a41086a2204200528025836020020052005290350370330200541d0006a41186a200541106a41186a290300370300200541d0006a41106a200541106a41106a290300370300200541d0006a41086a200541106a41086a29030037030020052005290310370350200541f0006a41086a200428020036020020052005290330370370200541c0006a200541d0006a200541f0006a10c0020240024002400240024020052802402203200528024822044188f0c100410041001004417f460d00200541003602582005200436025420052003360250200541086a200541d0006a10352005280208450d07200528020c2204417f4c0d052004450d01200410002202450d0820024100200410f7021a0c020b2000410036020020052802440d020c030b410121020b200541d8006a2206200628020022062004410020052802502005280254200220042006100422062006417f461b2206200620044b1b6a360200200420064b0d032002450d0420002004ad2207422086200784370204200020023602002005280244450d010b200310010b20054180016a24000f0b102c000b200210010b41eac4c10041331042000b200441011019000baf0601087f230041e0006b22032400200341c0006a41186a200141186a290000370300200341c0006a41106a200141106a290000370300200341c0006a41086a200141086a290000370300200320012900003703402003410036023820034201370330200341306a418b9ec10041081025200341106a200341c0006a10f50120032802142104200328021021050240024002400240024002400240024020032802342206200328023822076b200328021822084f0d00200720086a22012007490d0420064101742209200120012009491b22094100480d042006450d012003280230210a200910002201450d072001200a20092006200620094b1b10f8021a200a10010c020b20032802302101200621090c020b200910002201450d050b20032009360234200320013602300b200120076a2005200810f8021a200341306a41086a200720086a220736020002402004450d00200510010b200341106a41086a220842003703002003420037031020012007200341106a1002200341086a20082903003703002003200329031037030002402009450d00200110010b2003410036024820034201370340200228020022042002280208200341c0006a108e01200328024421072003280248210920032802402101200341c0006a41186a22084200370300200341c0006a41106a22064200370300200341c0006a41086a220542003703002003420037034020012009200341c0006a100d200341106a41186a2008290300370300200341106a41106a2006290300370300200341106a41086a20052903003703002003200329034037031002402007450d00200110010b411010002207450d0120072003290300370000200741086a2209200341086a290300370000413010002201450d0220012007290000370000200141086a200929000037000020071001200042b0808080800637020420002001360200200141286a200341106a41186a290300370000200141206a200341206a290300370000200141186a200341106a41086a290300370000200120032903103700100240200241046a280200450d00200410010b200341e0006a24000f0b1018000b411041011019000b413041011019000b200941011019000bcd0c05027f017e0e7f027e097f23004190036b2202240020024188016a41086a2203200141086a2802003602002002200129020037038801200241086a20024188016a10cf01200241306a41206a200241086a41206a280200360200200241306a41186a200241086a41186a290300370300200241306a41106a200241086a41106a290300370300200241306a41086a200241086a41086a2903003703002002200229030837033020024188016a200241306a10d1010240024020022903a80122044202510d00200241cc016a2105200241b8016a2106200241b0016a2107200241c0016a2108200241c4016a2109200241c8016a210a20024188016a41206a210b200241ec026a210c200241f4026a210d0340200241e8006a41186a220120024188016a41186a220e290300370300200241e8006a41106a220f20024188016a41106a2210290300370300200241e8006a41086a22112003290300370300200241d8006a41086a2212200541086a28020036020020022002290388013703682002200529020037035820062903002113200729030021142008280200211520092802002116200a2802002117200241d8016a41186a22182001290300370300200241d8016a41106a2219200f290300370300200241d8016a41086a221a2011290300370300200220022903683703d801200241f8016a41086a22012012280200360200200220022903583703f8010240024020044201520d00200241d8016a2014201310c202450d0002402015450d002016450d00201510010b20024188026a41086a2001280200360200200220022903f8013703880220024188016a20024188026a10cb0120024188016a10cc010c010b024002402015450d00410f1000220f450d052002420f37028c012002200f3602880120024188016a41c1b0c000410f102520024188026a41086a220f2003280200360200200220022903880137038802200241d8016a20024188026a101e200f280200211b200228028c02211c20022802880221112003410036020020024201370388012015201720024188016a108e0120032802002117200228028c01211d20022802880121122003420037030020024200370388012011201b20024188016a1002200f200329030037030020022002290388013703880220024188026a41102012201710030240201d450d00201210010b0240201c450d00201110010b4101211b2016450d01201510010c010b4100211b0b20032001280200360200200220022903f8013703880120024188026a20024188016a10cb01200b20024188026a41206a280200360200200e20024188026a41186a290300370300201020024188026a41106a290300370300200320024188026a41086a290300370300200220022903880237038801200241e0026a20024188016a10cd01024020022802e002450d000340200241b0026a41086a2211200241e0026a41086a2201280200360200200220022903e0023703b002200c280200210f200241e0026a41106a22122802002110200d2802002117200241c0026a41086a220e2011280200360200200220022903b0023703c00202400240200f450d00200241e0026a41186a2018290300370300201220192903003703002001201a290300370300200220022903d8013703e00220024180036a41086a200e280200360200200220022903c00237038003200241d0026a200241e0026a20024180036a10c002200241d0026a41086a280200211220022802d002211120014100360200200242013703e002200f2017200241e0026a108e0120022802e402210e2011201220022802e0022217200128020010030240200e450d00201710010b024020022802d402450d00201110010b2010450d01200f10010c010b200241e0026a41186a2018290300370300201220192903003703002001201a290300370300200220022903d8013703e00220024180036a41086a200e280200360200200220022903c00237038003200241d0026a200241e0026a20024180036a10c00220022802d0022201200241d0026a41086a280200100820022802d402450d00200110010b200241e0026a20024188016a10cd0120022802e0020d000b0b20024188016a10cc01201b201545720d002016450d00201510010b20024188016a200241306a10d101200b29030022044202520d000b0b200241306a10d00120024190036a24000f0b410f41011019000bbb1106027f017e047f017e067f037e230041b0016b22032400200341a0016a41086a22044200370300200342003703a00141bef0c100411b200341a0016a100220034190016a41086a2004290300370300200320032903a001370390010240024002400240024002400240024020034190016a41104188f0c100410041001004417f460d00200342003703282003420037032020034190016a4110200341206a4110410010042204417f460d012004410f4d0d012003290320200158200341286a290300220520025820052002511b0d0020002001200210aa01200341b0016a240041010f0b411410002204450d022003421437022420032004360220200341206a41eeefc10041141025200341a0016a41086a22042003280228360200200320032903203703a0012000200341a0016a101e2004280200210620032802a401210720032802a001210820044200370300200342003703a00120082006200341a0016a100220034190016a41086a2004290300370300200320032903a0013703900120034190016a4110100e210402402007450d00200810010b02402004450d0020002001200210aa01200341b0016a240041000f0b200341a0016a41086a22044200370300200342003703a001419d85c2004114200341a0016a100220034190016a41086a2004290300370300200320032903a00137039001410021040240024020034190016a41104188f0c100410041001004417f460d002003410036022020034190016a4110200341206a41044100100441016a41044d0d0320032802202204410e744180807c71418080046a22080d0141a4acc300104f000b4180800421080b200341106a200120022008ad420010fd0241002109024002402003280210220841ff017141e900470d00200341a0016a2008410e76220610ce0202402008410876220720064106746b220820032802a8014f0d00200320032802a00120084105746a220810b0014200210a2003290300200341086a290300844200510d020b024020032802a401450d0020032802a00110010b410221090b200341206a200410ce02024020032802282208413f4d0d00200341286a21060340200441016a210402402003280224450d00200328022010010b200341206a200410ce022006280200220841c0004f0d000b0b2003280220210620032802242107200341206a41186a220b200041186a290000370300200341206a41106a220c200041106a290000370300200341206a41086a220d200041086a2900003703002003200029000037032002400240024020082007470d00200841016a22072008490d072008410174220e20072007200e491b2207ad4205862205422088a70d072005a7220f4100480d072008450d01200f1000220e450d08200e2006200f200841057422102010200f4b1b10f8021a200610010c020b2006210e0c010b200f1000220e450d060b200441067420086a210f200e20084105746a22062003290320370000200641186a200b290300370000200641106a200c290300370000200641086a200d2903003700000240200841016a220841c000470d002003200441016a360220200341a0016a41086a22064200370300200342003703a001419d85c2004114200341a0016a100220034190016a41086a2006290300370300200320032903a0013703900120034190016a4110200341206a410410030b20032008360228200320073602242003200e3602202004200341206a10f402200341206a41086a41003a0000200341cc006a200f360200200341c9006a20093a0000200341296a2000290000370000200341316a200041086a290000370000200341396a200041106a290000370000200341c1006a200041186a290000370000200341013a0020200341206a10b40120012105200221110c070b200341206a41186a200041186a220e2900002205370300200341206a41106a200041106a22092900002212370300200341206a41086a2204200041086a220b2900002211370300200820002900002213370000200841086a2011370000200841106a2012370000200841186a2005370000200320133703202004200341a0016a41086a2208280200360200200320032903a0013703202006200341206a10f402200441003a0000200341cc006a2007360200200341c9006a41013a0000200341296a2000290000370000200341316a200b290000370000200341396a2009290000370000200341c1006a200e290000370000200341013a0020200341206a10b40120084200370300200342003703a00141b185c2004116200341a0016a100220034190016a41086a2008290300370300200320032903a001370390010240024020034190016a41104188f0c100410041001004417f460d00200342003703282003420037032020034190016a4110200341206a4110410010042204417f460d072004410f4d0d07200341286a29030021052003290320210a0c010b420021050b200520027c200a20017c2205200a54ad7c21110c060b41eac4c10041331042000b41eac4c10041331042000b411441011019000b1018000b200f41011019000b41eac4c10041331042000b20002005201110aa0142002112200341a0016a41086a22044200370300200342003703a00141d9f0c1004116200341a0016a100220034190016a41086a2004290300370300200320032903a0013703900102400240024020034190016a41104188f0c100410041001004417f460d00200342003703282003420037032020034190016a4110200341206a4110410010042204417f460d022004410f4d0d02200341286a290300210a200329032021120c010b4200210a0b02402012200520017d7c22132012542204200a201120027d2005200154ad7d7c2004ad7c2202200a542002200a511b0d002003201337032020032002370328200341a0016a41086a22044200370300200342003703a00141d9f0c1004116200341a0016a100220034190016a41086a2004290300370300200320032903a0013703900120034190016a4110200341206a411010030b200341b0016a240041000f0b41eac4c10041331042000bc60302057f017e230041306b2203240002400240024002400240410f10002204450d002003420f37022420032004360220200341206a41c1b0c000410f1025200341106a41086a22042003280228360200200320032903203703102002200341106a101e200428020021022003280214210520032802102106200341206a41086a220742003703002003420037032020062002200341206a1002200420072903003703002003200329032037031002400240024002400240200341106a41104188f0c100410041001004417f460d00200342103702242003200341106a360220200341086a200341206a10352003280208450d08200328020c2204417f4c0d062004450d01200410002202450d0920024100200410f7021a0c020b200041003602082000420137020020050d020c030b410121020b200341286a2207200728020022072004410020032802202003280224200220042007100422072007417f461b2207200720044b1b6a360200200420074b0d042002450d0520002004ad2208422086200884370204200020023602002005450d010b200610010b200341306a24000f0b410f41011019000b102c000b200210010b41eac4c10041331042000b200441011019000b9a0201027f0240024002402000280200220241074b0d000240024002400240024020020e080706050001020304070b2001410110240f0b20014102102420002802042000410c6a2802002001108e010f0b200141031024200041086a290300200110230f0b20014104102420002802042000410c6a2802002001108e010f0b200141051024200028020421032000410c6a28020022002001101b02402000450d002003200041186c6a210003402003280200200341086a2802002001108e012003410c6a280200200341146a2802002001108e01200341186a22032000470d000b20024101460d022002450d030b0f0b20014100102420002802042000410c6a2802002001108e010f0b41f089c300104f000b41f089c300104f000bb50102027f027e230041106b220324000240200128020022044100480d00200441ffffffff07460d002001200441016a36020002400240200141046a200210de012204450d002004280200450d00200441106a2903002105200441086a29030021060c010b200320012802102002200141146a280200280214110400200341086a2903002105200329030021060b20012001280200417f6a3602002000200537030820002006370300200341106a24000f0b10c602000b900101017f230041c0006b220024002000411836020c200041e39dc100360208200041286a410c6a4110360200200041246a4102360200200041106a410c6a41023602002000410136022c2000418489c20036021820004102360214200041a4aec3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41b4aec3001071000b840b05027f017e0f7f027e057f230041a0036b22022400024020002802000d002000417f36020020024188016a41086a2203200141086a2802003602002002200129020037038801200241086a20024188016a10cf01200241306a41206a200241086a41206a280200360200200241306a41186a200241086a41186a290300370300200241306a41106a200241086a41106a290300370300200241306a41086a200241086a41086a2903003703002002200229030837033020024188016a200241306a10d101024020022903a80122044202510d00200041046a2105200241a0026a41246a2106200241cc016a2107200241dc026a210120024188016a410472210820024188016a41306a210920024188016a41286a210a200241c0016a210b200241c4016a210c200241c8016a210d200241bc026a210e0340200241e8006a41186a220f20024188016a41186a290300370300200241e8006a41106a221020024188016a41106a2211290300370300200241e8006a41086a22122003290300370300200241d8006a41086a2213200741086a28020036020020022002290388013703682002200729020037035820092903002114200a2903002115200b2802002116200c2802002117200d2802002118200241d8016a41086a22192013280200360200200220022903583703d801200241e8016a41186a2213200f290300370300200241e8016a41106a221a2010290300370300200241e8016a41086a220f2012290300370300200220022903683703e80120024188016a2005200241e8016a10df0102400240024002402002280288014101470d00200328020041e8026a201128020041306c6a2110024020044201520d002010420137030020102015370308201041106a20143703000b2016450d01201041186a2112024020102802182211450d00201241046a280200450d00201110010b201220173602042012201636020020102018360220410121180c020b200241e8016a41306a200841306a280200360200200241e8016a41286a200841286a290200370300200241e8016a41206a200841206a2902003703002013200841186a290200370300201a200841106a290200370300200f200841086a290200370300200220082902003703e801200241a0026a41106a2014370300200241a0026a41086a2015370300200241a0026a41206a2018360200200e2017360200200241a0026a41186a2016360200200620022903d801370200200641086a2019280200360200200220043703a002200241e8016a200241a0026a10e2011a0c020b410021180b200f2019280200360200200220022903d8013703e801200241a0026a200241e8016a10cb01200241e8016a41206a200241a0026a41206a2802003602002013200241a0026a41186a290300370300201a200241a0026a41106a290300370300200f200241a0026a41086a290300370300200220022903a0023703e801200241e8026a200241e8016a10cd01024020022802e802450d00201041246a21120340200241d0026a41106a200241e8026a41106a290300370300200241d0026a41086a220f200241e8026a41086a2210290300370300200220022903e8023703d00220024190036a41086a200f280200360200200220022903d002370390032010200141086a280200360200200220012902003703e80220024180036a201220024190036a200241e8026a10e0010240200228028003450d00200228028403220f450d0020024180036a41086a280200450d00200f10010b200241e8026a200241e8016a10cd0120022802e8020d000b0b200241e8016a10cc012018201645720d002017450d00201610010b20024188016a200241306a10d10120024188016a41206a29030022044202520d000b0b200241306a10d0012000200028020041016a360200200241a0036a24000f0b108402000bb50101027f230041106b220324000240200128020022044100480d00200441ffffffff07460d002001200441016a360200024002400240200141046a200210de012204450d002004280218450d002003200441186a102b2003280200450d0120002003290300370200200041086a200341086a2802003602000c020b200341003602000b200020012802102002200141146a2802002802101104000b20012001280200417f6a360200200341106a24000f0b10c602000b2001017f2000200128020022023602002000200128020420026b41286e3602040bb70703037f017e067f230041106b2202240020024100360208200242013703000240024002400240024002400240024002400240024002400240200128020022034101460d00024020034102460d0020034103470d0220012802042101410110002203450d09200242818080801037020420022003360200200341003a0000200128020020012802082002108e010c050b200141086a280200210320012802042104410110002201450d07200242818080801037020420022001360200200141033a000020042903002105410910002204450d09200420012d00003a00002001100120024289808080900137020420022004360200200420053700012002280204220641776a413f4b0d022006410174220141c900200141c9004b1b22074100480d05200710002201450d0c2001200420072006200620074b1b10f80221062004100120022007360204200220063602000c030b20012802042103410110002201450d09200242818080801037020420022001360200200141023a000020032002101e0c030b200141086a280200210320012802042101410110002204450d09200242818080801037020420022004360200200441013a000020032002101b2003450d0220034105742108200241086a220928020021032002280204210603400240024002400240200620036b41204f0d00200341206a22042003490d0820064101742207200420042007491b220a4100480d082006450d012002280200210b200a10002207450d092007200b200a20062006200a4b1b10f8021a200b10010c020b200341206a2104200228020021070c020b200a10002207450d070b2002200a36020420022007360200200a21060b20092004360200200720036a220341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a2900003700002003200129000037000020042103200141206a2101200841606a22080d000c030b0b200421010b200241086a41c900360200200141116a200341086a290000370000200141196a200341106a290000370000200141216a200341186a290000370000200141296a200341206a290000370000200141316a200341286a290000370000200141396a200341306a290000370000200141c1006a200341386a290000370000200120032900003700090b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1018000b200a41011019000b410141011019000b410141011019000b410941011019000b410141011019000b410141011019000b200741011019000b8b71070d7f027e027f057e047f017e017f230041f0016b22022400200241003a0000200128020020012802042002410120012802081004210320012001280208200341016a220341014b6a2204360208024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d00002203410b4b0d08024020030e0c00020304050a0b060c070d08000b41002105200241003a00002001280200200141046a28020020024101200410042103200141086a22012001280200200341016a220141014b6a36020020014102490d0f024020022d00002201450d0020014101462201450d104101410220011b21050b200041003a0000200020054101713a0001200041026a200241ee0010f8021a200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d1a20022d00002203450d1720034101460d1820034102470d1a200241186a22064200370300200241106a4200370300200241086a2207420037030020024200370300200141086a220541002001280200200141046a2208280200200241202004100422032003417f461b2203412020034120491b20052802006a22093602002003411f4d0d1a2002280003210320022f0001210420022d0000210a20022f0007210b20022d0009210c20022f010a210d200228020c210e2002290310210f200241e1016a20062903003700002002200f3700d9012002200e3600d5012002200d3b00d3012002200c3a00d2012002200b3b01d001200642003703002007420037030020024200370310200242003703002005410020012802002008280200200241202009100422062006417f461b22064120200641204922061b20052802006a220736020020060d1a200241186a290300210f20022903102110200228020c210d20022f010a210e20022d0009211120022f000721122002280003210520022f0001210c20022d0000210b2002420037030820024200370300200141086a220841002001280200200141046a2209280200200241102007100422062006417f461b2206411020064110491b20082802006a22073602002006410f4d0d1a200241086a29030021132002290300211420024200370308200242003703002008410020012802002009280200200241102007100422012001417f461b2201411020014110491b20082802006a3602002001410f4d0d1a200241086a29030021152002290300211620024190016a41116a200f370000200241b0016a41186a200241d0016a41186a2d00003a0000200241b0016a41106a200241d0016a41106a290300370300200241b0016a41086a200241d0016a41086a29030037030020022010370099012002200d360095012002200e3b009301200220113a009201200220123b019001200220022903d0013703b001200241f0006a41086a20024190016a41086a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41186a20024190016a41186a2d00003a00002002200229039001370370200241b0016a41116a290000210f20022900b901211020022800b501210620022f00b301210720022d00b201210820022f01b0012109410221120c190b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d0a20022d00000d0a20024200370300200141086a220341002001280200200141046a280200200241082004100422012001417f461b2201410820014108491b20032802006a360200200141074d0d0a2002290300210f200041023a0000200041086a200f370300200020022800d001360001200041056a200241d0016a41046a2f00003b0000200041076a200241d6016a2d00003a0000200041106a200241e00010f8021a200241f0016a24000f0b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d1d20022d00002203450d1920034101460d1b20034102470d1d200241186a220a4200370300200241106a4200370300200241086a420037030020024200370300200141086a220541002001280200200141046a2206280200200241202004100422032003417f461b2203412020034120491b20052802006a22073602002003411f4d0d1d200a290300211720022903102113200228020c210820022f010a210920022d0009210b20022f0007210c2002280003210320022f0001210420022d0000210a20024200370308200242003703002005410020012802002006280200200241102007100422012001417f461b22014110200141104922011b20052802006a36020020010d1d200241086a290300210f20022903002110200220133700d901200241e1016a2017370000200220083600d501200220093b00d3012002200b3a00d2012002200c3b01d0012013423888201742088684a721012017423088a721062017421088a72107200241d0016a41086a290300211320022903d00121142017a72108410221050c1a0b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d3a20022d0000220341054b0d3a024020030e06003435363739000b200141046a220a280200210320024100360200200141086a2205410020012802002003200241042004100422032003417f461b2203410420034104491b20052802006a2206360200200341034d0d3a200228020021042002420037030820024200370300200541002001280200200a280200200241102006100422032003417f461b2203411020034110491b20052802006a3602002003410f4d0d3a200241086a290300210f2002290300211020022001103620022802002201450d3a200141187621032001410876210620022902042213423088a721072013422888a721082013421888a721092013a7210b410021050c390b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d2920022d0000220341044b0d29024020030e050023242527000b200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220941002001280200200141046a220b280200200241202004100422032003417f461b2203412020034120491b20092802006a220c3602002003411f4d0d292005290300210f20022903102110200228020c210320022f010a210420022d0009210520022f0007210a2002280003210620022f0001210720022d00002108200b280200210b20024100360200200941002001280200200b20024104200c1004220b200b417f461b220b4104200b410449220b1b20092802006a220c360200200b0d2920022802002118200241186a220b4200370300200241106a4200370300200241086a420037030020024200370300200141086a221941002001280200200141046a221a28020020024120200c100422092009417f461b2209412020094120491b20192802006a221b3602002009411f4d0d29200b290300211320022903102114200228020c210920022f010a210b20022d0009210c20022f0007210d2002280003210e20022f0001211120022d00002112201a280200211a20024100360200201941002001280200201a20024104201b100422012001417f461b22014104200141044922011b20192802006a36020020010d29200228020021014100211a0c270b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d3020022d0000220341044b0d30024020030e05002a2b2c2e000b200141046a28020021054100210320024100360200200141086a220a410020012802002005200241042004100422012001417f461b2201410420014104491b200a2802006a360200200141034d0d30200228020021010c2f0b41002105200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d0620022d00002203450d0920034101470d06200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220341002001280200200141046a280200200241202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d062005290300210f20022903102110200228020c210120022f010a210320022d0009210420022f0007210a2002280003210620022f0001210720022d00002108410121050c0a0b2000410c3a0000200241f0016a24000f0b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d3720022d0000220341034b0d37024020030e0400191a1b000b200241186a22064200370300200241106a4200370300200241086a2207420037030020024200370300200141086a220a41002001280200200141046a2208280200200241202004100422032003417f461b2203412020034120491b200a2802006a22093602002003411f4d0d372002280003210320022f0001210420022d0000210520022f0007210b20022d0009210c20022f010a210d200228020c210e2002290310210f200241d0016a41116a20062903003700002002200f3700d9012002200e3600d5012002200d3b00d3012002200c3a00d2012002200b3b01d00120064200370300200742003703002002420037031020024200370300200a410020012802002008280200200241202009100422012001417f461b22014120200141204922011b200a2802006a36020020010d372002280003210c20022f0001210e20022d0000210d20022f0007210120022d0009210a20022f010a2106200228020c21072002290310210f20024190016a41116a200241186a290300370000200241b0016a41086a200241d0016a41086a290300370300200241b0016a41106a200241d0016a41106a290300370300200241b0016a41186a200241d0016a41186a2d00003a00002002200f370099012002200736009501200220063b0093012002200a3a009201200220013b019001200220022903d0013703b001200241f0006a41086a20024190016a41086a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41186a20024190016a41186a2d00003a00002002200229039001370370200241b0016a41116a290000211320022900b901211420022800b501211120022f00b301211220022d00b201211820022f01b00121194100211a0c1d0b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d0a20022d00002203450d0820034101470d0a200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220341002001280200200141046a220a280200200241202004100422042004417f461b2204412020044120491b20032802006a22063602002004411f4d0d0a2005290300210f20022903102110200228020c210b20022f010a210c20022d0009210d20022f0007210e2002280003210720022f0001210820022d00002109200a2802002104200241003602002003410020012802002004200241042006100422042004417f461b22044104200441044922041b20032802006a220536020020040d0a2002280200210a200141046a2206280200210420024100360200200141086a2203410020012802002004200241042005100422042004417f461b2204410420044104491b20032802006a2205360200200441034d0d0a2002280200210420062802002106200241003602002003410020012802002006200241042005100422012001417f461b2201410420014104491b20032802006a360200200141034d0d0a20022802002101200241e1016a200f370000200241f0006a41186a200241d0016a41186a2d00003a0000200220103700d901200241f0006a41106a200241d0016a41106a2903003703002002200b3600d501200241f0006a41086a200241d0016a41086a2903003703002002200c3b00d3012002200d3a00d2012002200e3b01d001200220022903d001370370410121030c090b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a36020020034102490d3620022d0000450d040c360b200241003a00002001280200200141046a28020020024101200410042103200141086a22042004280200200341016a220341014b6a220436020020034102490d0b20022d00002203450d0920034101470d0b200241186a220a4200370300200241106a4200370300200241086a2206420037030020024200370300200141086a220541002001280200200141046a2207280200200241202004100422032003417f461b2203412020034120491b20052802006a22043602002003411f4d0d0b200a290300210f20022903102110200228020c210820022f010a210920022d0009210b20022f0007210c2002280003210d20022f0001210e20022d00002111200a42003703002006420037030020024200370310200242003703002005410020012802002007280200200241202004100422012001417f461b2201412020014120491b20052802006a3602002001411f4d0d0b200241186a290300211320022903102114200228020c210120022f010a210620022d0009210720022f000721122002280003210320022f0001210420022d000021054101210a0c0a0b2000410c3a0000200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b20022001103c20022802002201450d312002290204210f200041083a0000200041086a200f370000200041046a2001360000200020022f00d0013b0001200041036a200241d2016a2d00003a0000200041106a200241e00010f8021a200241f0016a24000f0b0b200020053a00012000410b3a00002000411a6a200f370000200041126a20103700002000410e6a20013600002000410c6a20033b00002000410b6a20043a0000200041096a200a3b0000200041056a2006360000200041036a20073b0000200041026a20083a0000200041226a200241ce0010f8021a200241f0016a24000f0b200241186a220a4200370300200241106a4200370300200241086a420037030020024200370300200141086a220541002001280200200141046a2206280200200241202004100422032003417f461b2203412020034120491b20052802006a22043602002003411f4d0d012002280003210720022f0001210820022d0000210920022f0007210320022d0009210b20022f010a210c200228020c210d2002290310210f200241c1016a200a2903003700002002200f3700b9012002200d3600b5012002200c3b00b3012002200b3a00b201200220033b01b00120062802002103200241003602002005410020012802002003200241042004100422032003417f461b22034104200341044922031b20052802006a220436020020030d012002280200210a200141046a2206280200210320024100360200200141086a2205410020012802002003200241042004100422032003417f461b2203410420034104491b20052802006a220b360200200341034d0d01200228020021042006280200210320024100360200200541002001280200200320024104200b100422012001417f461b2201410420014104491b20052802006a360200200141034d0d012002280200210120024190016a41186a2203200241b0016a41186a2d00003a000020024190016a41106a2205200241b0016a41106a29030037030020024190016a41086a2206200241b0016a41086a290300370300200220022903b00137039001200241f0006a41186a20032d00003a0000200241f0006a41106a2005290300370300200241f0006a41086a20062903003703002002200229039001370370410021030b200241186a2205200241f0006a41186a2d000022063a0000200241106a220b200241f0006a41106a290300220f370300200241086a220c200241f0006a41086a2903002210370300200241d0016a41086a220d2010370300200241d0016a41106a220e200f370300200241d0016a41186a221120063a000020022002290370220f3703d0012002200f370300200041063a0000200041086a2007360000200041066a20083b0000200041056a20093a0000200041046a20033a0000200041306a20013600002000412c6a2004360000200041286a200a360000200020022f00b0013b0001200041036a200241b2016a2d00003a00002000410c6a20022903d001370000200041146a200d2903003700002000411c6a200e290300370000200041246a20112d00003a0000200041ec006a200241386a280200360200200041e4006a200241306a290200370200200041dc006a200241286a290200370200200041d4006a200241206a290200370200200041cc006a2005290200370200200041c4006a200b2902003702002000413c6a200c290200370200200041346a2002290200370200200241f0016a24000f0b200241186a200241f0006a41186a2d00003a0000200241106a200241f0006a41106a290300370300200241086a200241f0006a41086a290300370300200220022903703703002000410c3a0000200241f0016a24000f0b200241186a220a4200370300200241106a4200370300200241086a2206420037030020024200370300200141086a220541002001280200200141046a2207280200200241202004100422032003417f461b2203412020034120491b20052802006a22043602002003411f4d0d01200a290300210f20022903102110200228020c210820022f010a210920022d0009210b20022f0007210c2002280003210d20022f0001210e20022d00002111200a42003703002006420037030020024200370310200242003703002005410020012802002007280200200241202004100422032003417f461b2203412020034120491b20052802006a22063602002003411f4d0d012002280003210320022f0001210420022d0000210520022f0007210a20022d0009210720022f010a2112200228020c211820022903102113200241a1016a2219200241186a29030037000020022013370099012002201836009501200220123b009301200220073a0092012002200a3b01900120024200370308200242003703004100210a200141086a220741002001280200200141046a280200200241102006100422012001417f461b22014110200141104922011b20072802006a36020020010d01200241086a290300211c200229030021172019290000211320024199016a2900002114200228009501210120022f009301210620022d009201210720022f01900121120b200020022800d0013600012000410a3a0000200041d8006a201c370000200041d0006a2017370000200041c1006a2013370000200041396a2014370000200041216a200f370000200041196a2010370000200041356a2001360000200041336a20063b0000200041326a20073a0000200041306a20123b00002000412c6a20033600002000412a6a20043b0000200041296a20053a0000200041156a2008360000200041136a20093b0000200041126a200b3a0000200041106a200c3b00002000410c6a200d3600002000410a6a200e3b0000200041096a20113a0000200041086a200a3a0000200041056a200241d4016a2f00003b0000200041076a200241d6016a2d00003a0000200041e8006a200241086a290300370300200041e0006a2002290300370300200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b200241186a220a4200370300200241106a4200370300200241086a420037030020024200370300200141086a220541002001280200200141046a220b280200200241202004100422032003417f461b2203412020034120491b20052802006a220c3602002003411f4d0d02200a290300210f20022903102110200228020c210620022f010a210720022d0009210820022f000721092002280003210320022f0001210420022d0000210a200b280200210b20024100360200200541002001280200200b20024104200c1004220b200b417f461b220b4104200b410449220b1b20052802006a220c360200200b0d0220022802002105200241003a00002001280200200141046a28020020024101200c1004210b200141086a22012001280200200b41016a220141014b6a36020020014102490d0220022d0000220b41034f0d02200241f0006a41186a200241186a2d00003a0000200241f0006a41106a200241106a290300370300200241f0006a41086a200241086a29030037030020022002290300370370410021120c010b200241186a22054200370300200241106a220b4200370300200241086a220c420037030020024200370300200141086a220341002001280200200141046a280200200241202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d012005290300210f20022903102110200228020c210620022f010a210720022d0009210820022f000721092002280003210320022f0001210420022d0000210a200241f0006a41186a20052d00003a0000200241f0006a41106a200b290000370300200241f0006a41086a200c29000037030020022002290000370370410121120b200241186a200241f0006a41186a2d000022013a0000200241106a200241f0006a41106a2903002217370300200241086a200241f0006a41086a290300221c370300200241d0016a41086a220d201c370300200241d0016a41106a220e2017370300200241d0016a41186a221120013a00002002200229037022173703d00120022017370300200041216a200f370000200041196a2010370000200041013a00002000412c6a20053600002000412a6a200c3b0000200041296a200b3a0000200041156a2006360000200041136a20073b0000200041126a20083a0000200041106a20093b00002000410c6a20033600002000410a6a20043b0000200041096a200a3a0000200041086a20123a000020002002280000360001200041056a200241046a2f00003b0000200041076a200241066a2d00003a0000200041e8006a2015370000200041e0006a2016370000200041d8006a2013370000200041d0006a2014370000200041c8006a20112d00003a0000200041c0006a200e290300370000200041386a200d290300370000200041306a20022903d001370000200241f0016a24000f0b200241186a200241f0006a41186a2d00003a0000200241106a200241f0006a41106a290300370300200241086a200241f0006a41086a290300370300200220022903703703002000410c3a0000200241f0016a24000f0b200242003703082002420037030041002105200141086a220341002001280200200141046a280200200241102004100422012001417f461b2201411020014110491b20032802006a3602002001410f4d0d03200241086a2903002113200229030021140b0c010b200241186a22064200370300200241106a4200370300200241086a420037030020024200370300200141086a220541002001280200200141046a2207280200200241202004100422032003417f461b2203412020034120491b20052802006a22083602002003411f4d0d012002280003210320022f0001210420022d0000210a20022f0007210920022d0009210b20022f010a210c200228020c210d2002290310210f200241c1016a20062903003700002002200f3700b9012002200d3600b5012002200c3b00b3012002200b3a00b201200220093b01b00120072802002106200241003602002005410020012802002006200241042008100422012001417f461b22014104200141044922011b20052802006a36020020010d012002280200210920024190016a41186a200241b0016a41186a2d00003a000020024190016a41106a2201200241b0016a41106a29030037030020024190016a41086a2205200241b0016a41086a290300370300200220022903b001370390012005290300211320012d00002101200229039001211420022f00a701210620022800a301210720022f00a1012108410121050b200020022800d001360001200041033a0000200041386a200f370000200041306a2010370000200041186a2013370000200041106a20143700002000412c6a2009360000200041276a20063b0000200041236a2007360000200041216a20083b0000200041206a20013a00002000410c6a20033600002000410a6a20043b0000200041096a200a3a0000200041086a20053a0000200041056a200241d4016a2f00003b0000200041076a200241d6016a2d00003a0000200041e8006a200241286a290300370300200041e0006a200241206a290300370300200041d8006a200241186a290300370300200041d0006a200241106a290300370300200041c8006a200241086a290300370300200041c0006a2002290300370300200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b200241186a220a4200370300200241106a22064200370300200241086a2207420037030020024200370300200141086a220341002001280200200141046a280200200241202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d1e200a290300211320022903102114200228020c211120022f010a211220022d0009211820022f000721192002280003210320022f0001210420022d00002105200241f0006a41186a200a2d00003a0000200241f0006a41106a2006290000370300200241f0006a41086a2007290000370300200220022900003703704101211a0c030b200141046a280200210320024100360200200141086a2205410020012802002003200241042004100422012001417f461b2201410420014104491b20052802006a360200200141034d0d1d20022802002103200241f0006a41186a200241186a2d00003a0000200241f0006a41106a200241106a290200370300200241f0006a41086a200241086a290200370300200220022902003703704102211a0c010b20022001103620022802002203450d1c2002290204210f20022001103620022802002201450d1b200220022902043702d401200220013602d001200241f0006a41086a200241086a290200370300200241f0006a41106a200241106a290200370300200241f0006a41186a200241186a2d00003a0000200220022902003703702001411874200f422888a7722111200241d9016a330000200241db016a310000421086842113200f42ffffffffff1f832210421888a721122010421088a7211820022900d1012114200fa721194103211a0b0b0b200241186a2201200241f0006a41186a2d0000220a3a0000200241106a2206200241f0006a41106a290300220f370300200241086a2207200241f0006a41086a2903002210370300200241d0016a41086a22082010370300200241d0016a41106a2209200f370300200241d0016a41186a220b200a3a000020022002290370220f3703d0012002200f3703002000411d6a2013370000200041156a2014370000200041053a0000200041286a200c360000200041266a200e3b0000200041256a200d3a0000200041116a20113600002000410f6a20123b00002000410e6a20183a00002000410c6a20193b0000200041086a2003360000200041066a20043b0000200041056a20053a0000200041046a201a3a0000200020022f00b0013b0001200041036a200241b2016a2d00003a00002000412c6a20022903d001370000200041346a20082903003700002000413c6a2009290300370000200041c4006a200b2d00003a0000200041e8006a200241206a290300370300200041e0006a2001290300370300200041d8006a2006290300370300200041d0006a2007290300370300200041c8006a2002290300370300200241f0016a24000f0b200241186a220b4200370300200241106a4200370300200241086a220c420037030020024200370300200141086a220941002001280200200141046a220d280200200241202004100422032003417f461b2203412020034120491b20092802006a220e3602002003411f4d0d06200b290300210f20022903102110200228020c210320022f010a210420022d0009210520022f0007210a2002280003210620022f0001210720022d00002108200b4200370300200c42003703002002420037031020024200370300200941002001280200200d28020020024120200e1004220b200b417f461b220b4120200b4120491b20092802006a2218360200200b411f4d0d06200241186a290300211320022903102114200228020c210920022f010a210b20022d0009210c20022f0007210d2002280003210e20022f0001211120022d00002112200241003a00002001280200200141046a221a28020020024101201810042119200141086a22182018280200201941016a221941014b6a221b36020020194102490d0620022d00002119201a280200211a20024100360200201841002001280200201a20024104201b1004221a201a417f461b221a4104201a4104491b20182802006a221b360200201a41034d0d0620022802002118200141046a280200211a20024100360200200141086a221d41002001280200201a20024104201b100422012001417f461b2201410420014104491b201d2802006a360200200141034d0d06200228020021014101211a0c050b200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220341002001280200200141046a280200200241202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d052005290300210f20022903102110200228020c210320022f010a210420022d0009210520022f0007210a2002280003210620022f0001210720022d000021084102211a0c010b200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220341002001280200200141046a280200200241202004100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d042005290300210f20022903102110200228020c210320022f010a210420022d0009210520022f0007210a2002280003210620022f0001210720022d000021084103211a0b0c020b200241186a22054200370300200241106a4200370300200241086a420037030020024200370300200141086a220941002001280200200141046a220b280200200241202004100422032003417f461b2203412020034120491b20092802006a220c3602002003411f4d0d022005290300210f20022903102110200228020c210320022f010a210420022d0009210520022f0007210a2002280003210620022f0001210720022d00002108200241003a00002001280200200b28020020024101200c1004210120092009280200200141016a220141014b6a36020020014102490d0220022d000021124104211a0b0b200020022f00d0013b0001200041073a00002000413d6a2013370000200041356a20143700002000411d6a200f370000200041156a2010370000200041cc006a2001360000200041c8006a2018360000200041c5006a20193a0000200041316a20093600002000412f6a200b3b00002000412e6a200c3a00002000412c6a200d3b0000200041286a200e360000200041266a20113b0000200041256a20123a0000200041116a20033600002000410f6a20043b00002000410e6a20053a00002000410c6a200a3b0000200041086a2006360000200041066a20073b0000200041056a20083a0000200041046a201a3a0000200041036a200241d2016a2d00003a0000200041e8006a200241186a290300370300200041e0006a200241106a290300370300200041d8006a200241086a290300370300200041d0006a2002290300370300200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b2002420037030820024200370300200141086a220341002001280200200141046a280200200241102004100422012001417f461b2201411020014110491b20032802006a3602002001410f4d0d06200241086a290300211420022903002113200241a1016a2900002110200229009901210f200228009501210420022f009301210620022d009201210820022f0190012107410121030c020b200141046a220a280200210520024100360200200141086a2203410020012802002005200241042004100422042004417f461b2204410420044104491b20032802006a2205360200200441034d0d05200228020021042002420037030820024200370300200341002001280200200a280200200241102005100422052005417f461b2205411020054110491b20032802006a220a3602002005410f4d0d05200241086a220329030021102002290300210f200241186a22054200370300200241106a42003703002003420037030020024200370300200141086a220341002001280200200141046a28020020024120200a100422012001417f461b2201412020014120491b20032802006a3602002001411f4d0d052002280003210120022f0001210a20022d0000210c20022f0007210320022d0009210620022f010a2107200228020c210820022903102113200241c1016a20052903002217370000200220133700b901200220083600b501200220073b00b301200220063a00b201200220033b01b0012013423888201742088684a7210b2017423088a721072017421088a72109200241b0016a41086a290300211420022903b00121132017a72105410221030c040b2002420037030820024200370300200141086a220341002001280200200141046a280200200241102004100422012001417f461b2201411020014110491b20032802006a3602002001410f4d0d04200241086a290300211420022903002113200241e1016a290000211020022900d901210f20022800d501210420022f00d301210620022d00d201210820022f01d0012107410321030b0c010b200242003703082002420037030041042103200141086a220541002001280200200141046a280200200241102004100422012001417f461b2201411020014110491b20052802006a3602002001410f4d0d02200241086a2903002114200229030021130b0b200020022800d001360001200041093a0000200041386a2010370000200041306a200f370000200041186a2014370000200041106a20133700002000412c6a20043600002000412a6a20063b0000200041296a20083a0000200041276a20073b0000200041236a2009360000200041216a20053b0000200041206a200b3a00002000410c6a20013600002000410a6a200a3b0000200041096a200c3a0000200041086a20033a0000200041056a200241d4016a2f00003b0000200041076a200241d6016a2d00003a0000200041e8006a200241286a290300370300200041e0006a200241206a290300370300200041d8006a200241186a290300370300200041d0006a200241106a290300370300200041c8006a200241086a290300370300200041c0006a2002290300370300200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b200141046a220a280200210320024100360200200141086a2205410020012802002003200241042004100422032003417f461b2203410420034104491b20052802006a2206360200200341034d0d0620022802002104200241003a00002001280200200a2802002002410120061004210120052005280200200141016a220141014b6a36020020014102490d0620022d0000220a41034f0d06200241c1016a290000210f20022900b901211020022800b501210c20022f00b301210720022d00b201210820022f01b001210941012105410021034100210b0c050b200141046a28020021054100210320024100360200200141086a220a410020012802002005200241042004100422012001417f461b2201410420014104491b200a2802006a360200200141034d0d0520022802002104200241e1016a290000210f20022900d901211020022800d501210c20022f00d301210720022d00d201210820022f01d0012109410221054100210b0c040b200141046a28020021054100210320024100360200200141086a220a410020012802002005200241042004100422012001417f461b2201410420014104491b200a2802006a36020041032105200141034b0d010c040b41042105200141046a280200210a4100210320024100360200200141086a220641002001280200200a200241042004100422012001417f461b2201410420014104491b20062802006a360200200141034d0d030b200228020021044100210b0c010b200141046a220a2802002103200241003602d001200141086a2205410020012802002003200241d0016a41042004100422032003417f461b2203410420034104491b20052802006a2206360200200341034d0d0120022802d0012104200241003a00d0012001280200200a280200200241d0016a410120061004210120052005280200200141016a41014b22016a3602002001450d0120022d00d001210a20022800032203410876210b200241186a290300210f20022903102110200228020c210c20022f010a210720022d0009210820022f0007210920022f0001210620022d00002101410521050b200020022800d001360001200041043a0000200041286a200f370000200041206a20103700002000411c6a200c3600002000411a6a20073b0000200041196a20083a0000200041176a20093b0000200041116a20063b0000200041106a20013a00002000410c6a2004360000200041096a200a3a0000200041086a20053a0000200041056a200241d0016a41046a2f00003b0000200041076a200241d6016a2d00003a0000200041136a200b410874200341ff017172360000200041e8006a200241386a290300370300200041e0006a200241306a290300370300200041d8006a200241286a290300370300200041d0006a200241206a290300370300200041c8006a200241186a290300370300200041c0006a200241106a290300370300200041386a200241086a290300370300200041306a2002290300370300200241f0016a24000f0b2000410c3a0000200241f0016a24000f0b200fa7450d00200310010b200241186a200241f0006a41186a2d00003a0000200241106a200241f0006a41106a290300370300200241086a200241f0006a41086a290300370300200220022903703703002000410c3a0000200241f0016a24000f0b2000410c3a0000200241f0016a24000bcef10209057f017e027f017e067f057e077f047e017f230041e0076b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417f6a2204410b4b0d0002400240024020040e0c0008050602090a070c040b01000b200341f0066a41086a200141106a2903003703002003200141086a2903003703f006200341f0046a41206a200241206a280200360200200341f0046a41186a200241186a290200370300200341f0046a41106a200241106a290200370300200341f0046a41086a200241086a290200370300200320022902003703f004200341086a200341f0066a200341f0046a10cd02200328020c21042003280208210541012106410021070cfa010b200341d8026a41026a200141076a2d00003a0000200341b8036a41086a2001411c6a290200370300200341b8036a41106a200141246a280200360200200320012f00053b01d8022003200141146a2902003703b8032002411d6a350000200241216a310000422086842108200241026a2f0100200241046a2d0000411074722104200241196a2800002109200241156a280000210a2002410d6a290000210b200241096a280000210c200241056a280000210d200141106a28020021052001410c6a2802002107200141086a280200210620022d0001210e20022d0000210220012d0004220f4102460d0b200f4103470daa01200341f8056a41026a200341d8026a41026a220f2d00003a00002003418f066a200341b8036a41086a221029030037000020034197066a200341b8036a41106a22112d00003a00002003200536008306200320073600ff05200320063600fb05200320032f01d8023b01f805200320032903b80337008706200341f8026a41026a200f2d00003a000020034198036a41086a201029030037030020034198036a41106a20112d00003a0000200320032f01d8023b01f802200320032903b80337039803200241ff01710d11200e41ff01714101470d11200341b8026a411f6a200842208822123c0000200320083e00d302200320043b01b802200320093600cf022003200a3600cb022003200b3700c3022003200c3600bf022003200d3600bb022003200441107622023a00ba02200341d8036a411f6a20123c0000200320083e00f303200320023a00da03200320043b01d803200320093600ef032003200a3600eb032003200b3700e3032003200c3600df032003200d3600db03200341c8016a41086a22024200370300200342003703c80141f8f0c000410e200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d3720034190026a4200370300200341f8016a41106a4200370300200341f8016a41086a4200370300200342003703f801200341b8016a4110200341f8016a4120410010042202417f460dba012002411f4d0dba01200341b8026a41186a2202200341f8016a41186a290300370300200341b8026a41106a2204200341f8016a41106a290300370300200341b8026a41086a2209200341f8016a41086a290300370300200320032903f8013703b802200341f0046a41186a220a2002290300370300200341f0046a41106a22022004290300370300200341f0046a41086a22042009290300370300200320032903b8023703f004200341d0046a41186a200a2903002208370300200341d0046a41106a2002290300220b370300200341d0046a41086a20042903002212370300200341f0066a41086a2012370300200341f0066a41106a200b370300200341f0066a41186a2008370300200320032903f00422083703d004200320083703f0060c380b200141086a2d0000220f417e6a220441054b0daa012002411d6a350000200241216a310000422086842108200241026a2f0100200241046a2d0000411074722107200141106a2903002112200241196a2800002106200241156a280000210a2002410d6a290000210b200241096a280000210c200241056a280000210d2001410c6a280200210920022d0001210520022d0000210220012d0009210e024020040e0600201e1f1d22000b200241ff01710d3d200541ff01714101470d3d200141186a290300211320034198026a411f6a200842208822143c0000200320083e00b302200320073b019802200320063600af022003200a3600ab022003200b3700a3022003200c36009f022003200d36009b022003200741107622023a009a02200341f0066a411f6a20143c0000200320083e008b07200320023a00f206200320073b01f00620032006360087072003200a360083072003200b3700fb062003200c3600f7062003200d3600f306200341b8016a41086a22024200370300200342003703b80141a599c1004118200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803200341d8036a41104188f0c100410041001004417f460d42200342003703f804200342003703f004200341d8036a4110200341f0046a4110410010042202417f460dc2012002410f4d0dc201201220032903f004542013200341f8046a29030022085420132008511b450d4241bd99c1002105410d21040c430b200141086a2903004202520daa01412d21044101210741c1efc100410041c1efc100410320022d000120022d00001b41ff017122024102461b20024103461b22050df301200141106a2903002108200341c8016a41086a22024200370300200342003703c80141f2a1c1004113200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110100e0db501200310f00120032802004101470db40120032802040db401200341c8016a41086a22024200370300200342003703c80141a0a5c100410d200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460db002200342003703f004200341b8016a4110200341f0046a41084100100441016a41084d0da70120032903f004500db002200341c8016a41086a22024200370300200342003703c80141a0a5c100410d200341c8016a1002200341b8016a41086a22052002290300370300200320032903c8013703b8014200210b0240200341b8016a41104188f0c100410041001004417f460d00200342003703f004200341b8016a4110200341f0046a41084100100441016a41084d0db30120032903f004210b0b20024200370300200342003703c80141daa3c1004115200341c8016a100220052002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d43200342003703f004200341b8016a4110200341f0046a41084100100441016a41084d0db301200820032903f004200b7c540d440cb0020b200341a0016a41086a200141186a290300370300200341a0016a41106a200141206a2903003703002003200141106a2903003703a001200141086a280200417e6a220441044b0daa01200241026a2f0100200241046a2d0000411074722107200241056a2800002106200141286a29030021082001410c6a280200210a20022d0001210920022d00002105024020040e050019161715000b200541ff01710d2a200941ff01714101470d2a200141386a2903002114200141306a2903002115200241196a2800002109200241156a280000210c2002410d6a290000210b200241096a280000210d20032802b401210e20032802b001210f20032903a801211620032802a401210420032802a0012105200341d0046a411f6a2002411d6a350000200241216a31000042208684221242208822133c0000200320123e00eb04200320073b01d004200320093600e7042003200c3600e3042003200b3700db042003200d3600d704200320063600d3042003200741107622023a00d204200341c8066a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01c806200341f0066a411f6a20133c0000200320123e008b07200320023a00f206200320073b01f00620032009360087072003200c360083072003200b3700fb062003200d3600f706200320063600f306200a41ff01714101470d49200341f0046a200541067610ce0220032802f8042005413f7122024d0d5f200341b0046a41086a220420032802f004220620024105746a220241086a290000370300200341b0046a41106a2205200241106a290000370300200341b0046a41186a2207200241186a290000370300200320022900003703b004024020032802f404450d00200610010b200341d0046a41186a2007290300370300200341d0046a41106a2005290300370300200341d0046a41086a2004290300370300200320032903b0043703d00420032800b704210420032800b304210541000d980220033500cb04200341cf046a31000042208684210820032f01b00420032d00b20441107472210620032800c704210e20032800c304210f20032900bb0421160c93020b200341d0046a41046a22052001410e6a2f01003b0100200341d8036a41086a220a200141206a290300370300200341d8036a41106a220c200141286a2903003703002003200128010a3602d0042003200141186a2903003703d803200141106a290300210820022d0001210620022d0000210720012d00092109200141086a2d000022044102460d0c20044103460d0b20044104470daa0141efeec10041efeec100410041032006200741ff01711b41ff017122021b20024103461b22050d32200320093a00f004200341c8016a41086a22024200370300200342003703c80141eef1c0004119200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b80141012107200341b8016a4110200341f0046a410110030c520b200141086a2d0000417e6a220441094b0daa012002411d6a350000200241216a310000422086842108200241026a2f0100200241046a2d0000411074722107200141186a2903002113200141106a2903002112200241196a2800002109200241156a280000210a2002410d6a290000210b200241096a280000210c200241056a280000210d200141206a280200210f2001410c6a280200210e20022d0001210620022d00002102024020040e0a002d282b262e2f2c3127000b200241ff01710d44200641ff01714101470d44200341d8016a411f6a200842208822123c0000200320083e00f301200320073b01d801200320093600ef012003200a3600eb012003200b3700e3012003200c3600df012003200d3600db012003200741107622023a00da01200341d0046a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01d004200341f0066a411f6a20123c0000200320083e008b07200320023a00f206200320073b01f00620032009360087072003200a360083072003200b3700fb062003200c3600f7062003200d3600f306200341f0046a200341f0066a10c80120032d00f0044101470d5f419aeec0002105412321040c96020b20034198036a41026a200141076a2d00003a0000200341d0046a41086a200141186a290200370300200341d0046a410d6a2001411d6a290000370000200320012f00053b0198032003200141106a2902003703d0042002411d6a350000200241216a310000422086842108200241026a2f0100200241046a2d0000411074722104200241196a2800002105200241156a28000021062002410d6a290000210b200241096a2800002109200241056a280000210a2001410c6a2802002107200141086a280200210e20022d0001210c20022d0000210220012d0004220d4102460d06200d4103470daa01200141286a280200210f20012d00252110200341db066a200341d8046a290300370000200341e0066a200341dd046a290000370000200320073600cf062003200e3600cb06200320032f0198033b01c806200320032903d0043700d30620032003419a036a2d00003a00ca06200241ff01710d0d200c41ff01714101470d0d20034198026a411f6a200842208822123c0000200320083e00b302200320043b019802200320053600af02200320063600ab022003200b3700a3022003200936009f022003200a36009b022003200441107622023a009a02200341f8056a411f6a20123c0000200320083e009306200320023a00fa05200320043b01f8052003200536008f062003200636008b062003200b37008306200320093600ff052003200a3600fb05200341f8056a10cf02450d1f411510002202450dba01200342153702f404200320023602f004200341f0046a41c3c0c00041151025200341f0066a41086a220220032802f804360200200320032903f0043703f006200341c8066a200341f0066a101e2002280200210420032802f406210520032802f0062102200341c8016a41086a22064200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2006290300370300200320032903c8013703b80141002106200341b8016a41104188f0c100410041001004417f460d4a2003200341b8016a3602d803200341103602dc03200341003602f00420034100200341b8016a4110200341f0046a41044100100422042004417f461b2204410420044104491b22063602e003200441034d0dbf0120032802f0042117200341003602f004200341e0036a4100200341b8016a4110200341f0046a41042006100422042004417f461b2204410420044104491b20066a360200200441034d0dbf0120032802f0042118200341f0066a200341d8036a103620032802f0062206450dbf01200341f0066a41086a280200210a20032802f4062119200341f0046a200341d8036a103620032802f004220c450dbe01200341f0046a41086a280200211120032802f404211a2005450da0020c9f020b200341b0046a41026a220e2001412f6a2d00003a0000200320012f002d3b01b004200141286a3502002001412c6a31000042208684210820012f000d2001410f6a2d0000411074722107200141386a2903002112200141306a2903002113200141246a2802002109200141206a280200210a200141186a290200210b200141146a280200210c200141106a28020021062001410c6a2d0000210d20022d0001210420022d00002105200141086a280200220f4102460d06200f4103470daa01200141c8006a2903002114200141c0006a290300211520034190056a20084220883c00002003418c056a20083e020020034188056a200936020020034184056a200a360200200341fc046a200b370200200341f8046a200c36020020034191056a20032f01b0043b000020034193056a200341b2046a2d00003a0000200320063602f4042003200d3a00f004200320073b00f104200320074110763a00f30441efeec10041efeec100410041032004200541ff01711b41ff017122021b20024103461b22050d2f200d41ff01714101470d36200341d8036a200641067610ce0220032802e0032006413f7122024d0d46200341f8016a41086a220420032802d803220620024105746a220241086a290000370300200341f8016a41106a2205200241106a290000370300200341f8016a41186a2207200241186a290000370300200320022900003703f801024020032802dc03450d00200610010b20034198026a41186a200729030037030020034198026a41106a200529030037030020034198026a41086a2004290300370300200320032903f8013703980220033500930220034197026a31000042208684210820032f01f80120032d00fa01411074722107200328008f022109200328008b02210a200329008302210b20032800ff01210420032800fb0121054100450d470c94020b200341f0046a41386a200141c0006a290300370300200341f0046a41306a200141386a290300370300200341f0046a41286a200141306a290300370300200341f0046a41206a200141286a290300370300200341f0046a41186a200141206a290300370300200341f0046a41106a200141186a290300370300200341f0046a41086a200141106a2903003703002003200141086a2903003703f004200341f0066a41206a200241206a280200360200200341f0066a41186a200241186a290200370300200341f0066a41106a200241106a290200370300200341f0066a41086a200241086a290200370300200320022902003703f006200341386a200341f0046a200341f0066a10d002200328023c2104200328023821054100210941012107410121060cf3010b200341f0046a41206a200141286a290300370300200341f0046a41186a200141206a290300370300200341f0046a41106a200141186a290300370300200341f0046a41086a200141106a2903003703002003200141086a2903003703f004200341f0066a41206a200241206a280200360200200341f0066a41186a200241186a290200370300200341f0066a41106a200241106a290200370300200341f0066a41086a200241086a290200370300200320022902003703f006200341c0006a200341f0046a200341f0066a10d10220032802442104200328024021054100210a4101210741012106410121090cf3010b200341f8026a41026a22052001410b6a2d00003a0000200320012f00093b01f8022002411d6a350000200241216a310000422086842108200241026a2f0100200241046a2d0000411074722104200141386a2903002113200241196a2800002110200241156a28000021112002410d6a2900002112200241096a280000211a200241056a2800002119200141346a2802002118200141306a280200210d2001412c6a280200210e200141286a280200210f200141206a290300210b2001411c6a2802002107200141186a280200210a200141146a2802002109200141106a28020021062001410c6a280200210c20022d0001211b20022d00002117200141086a2d000022024102460d0420024103470da801200320093602a0032003200636029c032003200c360298032003200ba7221c3602c003200320073602bc032003200a3602b803201741ff01710d0b201b41ff01714101470d0b20034198026a411f6a2008422088220b3c0000200320083e00b302200320043b019802200320103600af02200320113600ab02200320123700a3022003201a36009f022003201936009b022003200441107622053a009a02200341b0046a411f6a200b3c0000200320083e00cb04200320053a00b204200320043b01b004200320103600c704200320113600c304200320123700bb042003201a3600b704200320193600b304200341f0046a200341b0046a201310ab01200341f0046a41086a280200210420032802f0044101470d1d20032802f404210520070d96020c97020b2001410c6a2802002107200141086a280200210a20012802042104200341d0046a41026a2205200241046a2d00003a0000200341d8036a41086a2206200241156a290000370300200341d8036a410d6a22092002411a6a2900003700002003200241026a2f01003b01d00420032002410d6a2900003703d80320044102470da801200241096a2800002104200241056a280000210d20022d0001210c20022d00002102200341f8056a41026a20052d00003a0000200341f0046a41086a2006290300370300200341f0046a410d6a2009290000370000200320032f01d0043b01f805200320032903d8033703f004024002400240200241ff01710d00200341c8066a41026a2202200341f8056a41026a2d00003a0000200341f0066a41086a2205200341f0046a41086a290300370300200341f0066a410d6a2206200341f0046a410d6a290000370000200320032f01f8053b01c806200320032903f0043703f006200c41ff01714101470d00200341ab026a2005290300370000200341b0026a20062900003700002003200436009f022003200d36009b02200320032f01c8063b019802200320032903f0063700a302200320022d00003a009a024100210520070d010c020b412a21044197efc10021052007450d010b200a10010b4100210c4101210741012106410121094101210a4101210d0cf2010b2003200536028006200320073602fc05200320063602f805200241ff01710d06200e41ff01714101470d06200341b8026a411f6a200842208822123c0000200320083e00d302200320043b01b802200320093600cf022003200a3600cb022003200b3700c3022003200c3600bf022003200d3600bb022003200441107622023a00ba02200341d8036a411f6a20123c0000200320083e00f303200320023a00da03200320043b01d803200320093600ef032003200a3600eb032003200b3700e3032003200c3600df032003200d3600db03200341c8016a41086a22024200370300200342003703c80141f8f0c000410e200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d2d200341f0016a4200370300200341d8016a41106a4200370300200341d8016a41086a4200370300200342003703d801200341b8016a4110200341d8016a4120410010042202417f460daf012002411f4d0daf01200341b8026a41186a2202200341d8016a41186a290300370300200341b8026a41106a2204200341d8016a41106a290300370300200341b8026a41086a2209200341d8016a41086a290300370300200320032903d8013703b802200341f0046a41186a220a2002290300370300200341f0046a41106a22022004290300370300200341f0046a41086a22042009290300370300200320032903b8023703f004200341d0046a41186a200a2903002208370300200341d0046a41106a2002290300220b370300200341d0046a41086a20042903002212370300200341f0066a41086a2012370300200341f0066a41106a200b370300200341f0066a41186a2008370300200320032903f00422083703d004200320083703f0060c2e0b200241ff01710d07200c41ff01714101470d0720034198026a411f6a200842208822123c0000200320083e00b302200320043b019802200320053600af02200320063600ab022003200b3700a3022003200936009f022003200a36009b022003200441107622023a009a02200341f8056a411f6a20123c0000200320083e009306200320023a00fa05200320043b01f8052003200536008f062003200636008b062003200b37008306200320093600ff052003200a3600fb05200341f8056a10cf02450d19200341003602f804200342013703f0042007200341f0046a101c20032802f404210420032802f804210520032802f004210220034198026a41186a2206420037030020034198026a41106a2209420037030020034198026a41086a220a420037030020034200370398022002200520034198026a100d200341d8036a41186a22052006290300370300200341d8036a41106a2009290300370300200341d8036a41086a2206200a29030037030020032003290398023703d80302402004450d00200210010b200341f0046a41186a2005290300370300200341f0046a41106a200341d8036a41106a290300370300200341f0046a41086a2006290300370300200320032903d8033703f004411910002202450db401200342193702f406200320023602f006200341f0066a41dfbfc00041191025200341c8066a41086a220220032802f806360200200320032903f0063703c806200341f0046a200341c8066a101e2002280200210420032802cc06210520032802c8062102200341c8016a41086a22064200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2006290300370300200320032903c8013703b801200341b8016a4110100e210402402005450d00200210010b2004450d4441a3b1c1002105411f21040ca3020b200241216a31000021142002411d6a3500002115200241046a2d00002111200241026a2f0100211a200241196a2800002119200241156a28000021172002410d6a2900002116200241056a280000210f200241096a2800002102200341f0066a41206a20084220883c00002003418c076a20083e0200200341f0066a41186a2009360200200341f0066a41146a200a360200200341f0066a410c6a200b370200200341f0066a41086a200c360200200341f0066a41216a20032f01b0043b000020034193076a200e2d00003a0000200320063602f4062003200d3a00f006200320073b00f106200320074110763a00f306200341d0046a41026a200341c8066a41026a2d00003a0000200320032f01c8063b01d0042002412a200541ff0171220e45200441ff017122104101467122051b2104200f4197efc10020051b2105200e0d8d0220104101470d8d022003201520144220868422143e009306200341f8056a411f6a20144220883c00002003201936008f062003201736008b062003201637008306200320043600ff05200320053600fb052003201a20114110747222023b01f805200320024110763a00fa05200d41ff01714101470d1a200341f0046a200641067610ce0220032802f8042006413f7122024d0d34200341f8016a41086a220420032802f004220620024105746a220241086a290000370300200341f8016a41106a2205200241106a290000370300200341f8016a41186a2207200241186a290000370300200320022900003703f801024020032802f404450d00200610010b20034198026a41186a200729030037030020034198026a41106a200529030037030020034198026a41086a2004290300370300200320032903f8013703980220032800ff01210c20032800fb0121064100450d5120062105200c21040c8d020b200141c0006a2903002115200141c8006a29030021142003200f3a00cf042003200b3700c704200320073600c3042003200a3600bf04200320093600bb04200320063600b7042003200c3600b304200320032f01f8023b01b004200320052d00003a00b204200320183602a0032003200d36029c032003200e360298032003200f3a00d7022003200b3700cf02200320073600cb022003200a3600c702200320093600c302200320063600bf022003200c3600bb02200320052d00003a00ba02200320032f01f8023b01b802201741ff01710d07201b41ff01714101470d0720034198026a411f6a2008422088220b3c0000200320083e00b302200320043b019802200320103600af02200320113600ab02200320123700a3022003201a36009f022003201936009b022003200441107622053a009a02200341d0046a411f6a200b3c0000200320083e00eb04200320053a00d204200320043b01d004200320103600e704200320113600e304200320123700db042003201a3600d704200320193600d304200341f0046a200341d0046a201410ab01200341f0046a41086a280200210420032802f0044101470d1a20032802f4042105200d0d8f020c90020b4100210541efeec10041efeec100410041032006200741ff01711b41ff017122021b20024103461b2202450d14412821044101210741012106410121094101210a4101210d4101210c4101210e4101210f2002210520012802002202410b4d0df0010cef010b200241216a31000021122002411d6a3500002113200241046a2d0000210f200241026a2f01002110200241196a280000210d200241156a280000210e2002410d6a290000210b200241096a2800002104200241056a2800002102200341d8016a41176a200a290300370000200341d8016a411f6a200c2d00003a0000200320093a00d801200320083700df01200320032802d0043600d901200320032903d8033700e701200320052f01003b00dd01200341f8016a41176a200a290300370000200341f8016a411f6a200c2d00003a0000200320093a00f801200320083700ff01200320032802d0043600f901200320052f01003b00fd01200320032903d80337008702200741ff01710d1d200641ff01714101470d1d20034198026a411f6a2013201242208684220842208822123c0000200320083e00b30220032010200f4110747222053b0198022003200d3600af022003200e3600ab022003200b3700a3022003200436009f022003200236009b022003200541107622073a009a02200341f0066a411f6a20123c0000200320083e008b07200320073a00f206200320053b01f0062003200d360087072003200e360083072003200b3700fb06200320043600f706200320023600f306200341f0046a41186a200341f8016a41186a290300370300200341f0046a41106a200341f8016a41106a290300370300200341f0046a41086a200341f8016a41086a290300370300200320032903f8013703f004411210002202450dac01200342123702fc05200320023602f805200341f8056a41daf2c00041121025200341c8066a41086a2202200328028006360200200320032903f8053703c806200341f0066a200341c8066a101e2002280200210720032802cc06210620032802c8062105412010002202450dad01200220032903f004370000200241186a200341f0046a41186a290300370000200241106a200341f0046a41106a290300370000200241086a200341f0046a41086a290300370000200341c8016a41086a22094200370300200342003703c80120052007200341c8016a1002200341b8016a41086a2009290300370300200320032903c8013703b801200341b8016a41102002412010032002100102402006450d00200510010b410021050c8a020b412a21044197efc10021050c480b412a21044197efc100210520070d280c470b412a21044197efc10021050c9d020b412a21044197efc10021050c9b020b4197efc1002105412a21042007450d8b020c8a020b4197efc1002105412a2104200d450d88020c87020b200320063600f304200320073b01f004200320074110763a00f204200541ff0171450d0220032801f2044104490d02411210002202450db201200342123702f404200320023602f004200341f0046a4197e5c0004112102520032802f004210620032802f404220520032802f80422026b41034b0d43200241046a22042002490d8f0220054101742207200420042007491b22074100480d8f022005450d61200710002204450dbd012004200620072005200520074b1b10f8021a200610010c620b41efeec10041efeec100410041032009200541ff01711b41ff017122021b20024103461b22050d1d200341a0016a41106a290300210b20032802a001210420032903a8012112419af0c0004115200a10a4022003200b3703f804200320123703f004200341b8016a41086a22024200370300200342003703b80141feefc000411c200341b8016a1002200341d8036a41086a22052002290300370300200320032903b8013703d803200341d8036a4110200341f0046a41101003200320083703f00420024200370300200342003703b80141b9c2c0004114200341b8016a100220052002290300370300200320032903b8013703d803200341d8036a4110200341f0046a4108100341ebc2c000410d200410a4020c030b200320063600f304200320073b01f004200320074110763a00f204200541ff0171450d0020032801f20441024f0d260b41c00021044181b0c00021050c80020b41efeec10041efeec100410041032009200541ff01711b41ff017122021b20024103461b22050d1a20032903a00121082003200341a0016a41086a2903003703f804200320083703f004200341b8016a41086a22024200370300200342003703b80141cdc2c000410c200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803200341d8036a4110200341f0046a411010030b410021050cfe010b41002106412821044101210741efeec10041efeec100410041032005200241ff01711b41ff017122021b20024103461b22050dd8012009109602410021060cf7010b200241ff01710d02200541ff01714101470d0220034198026a411f6a200842208822123c0000200320083e00b302200320073b019802200320063600af022003200a3600ab022003200b3700a3022003200c36009f022003200d36009b022003200741107622023a009a02200341f0066a411f6a20123c0000200320083e008b07200320023a00f206200320073b01f00620032006360087072003200a360083072003200b3700fb062003200c3600f7062003200d3600f306200341b8016a41086a22024200370300200342003703b80141bb9ac1004118200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803410021020240200341d8036a41104188f0c100410041001004417f460d00200341003a00f004200341d8036a4110200341f0046a41014100100441016a41014d0daf0120032d00f00421020b200e411874411875410776200e7341187441808080086a41187520024118744118754c0d3341d39ac1002105411d21040cf8010b4100210641efeec10041efeec100410041032005200241ff01711b41ff017122021b20024103461b2205450d1f200910a001200910010c030b200241ff01710d00200541ff01714101470d0020034198026a411f6a200842208822123c0000200320083e00b302200320073b019802200320063600af022003200a3600ab022003200b3700a3022003200c36009f022003200d36009b022003200741107622023a009a02200341f0066a411f6a20123c0000200320083e008b07200320023a00f206200320073b01f00620032006360087072003200a360083072003200b3700fb062003200c3600f7062003200d3600f306200341f0046a20091091022003280280052207450d3b2003418c056a2802002105200341f0046a41186a28020021042003280284052102200341206a200341f0066a20032902f404220842208620033502f00484220b200341fc046a350200422086200842208884220810d2022003280220450d4941a19ac1002105411a21042002450df601200710010cf6010b412a210441002106410121074197efc10021050cd6010b4100210641efeec10041efeec100410041032005200241ff01711b41ff017122021b20024103461b2205450d1e0b41282104410121070cd6010b200320083703f004200341c8016a41086a22024200370300200342003703c80141aff2c0004119200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a410810030cf7010b41d8c0c000210541142104200d4102460d8a020c8b020b41f8bfc0002105411721040c89020b200341f0046a410c6a290200210820034194056a2802002105200341f0046a41206a28020021102003418c056a2802002111200341f0046a41186a280200211a200341d0046a410c6a200341f0046a41146a3502003e0200200320083702d404200320053602ec04200320103602e804200320113602e4042003201a3602e004200320043602d004200341f0046a109e01200341f8056a41206a4200370300200341f8056a41146a4194acc200360200200341f8056a41086a4200370300200341bc066a200341b0046a41186a2204290300370200200341b4066a200341b0046a41106a2210290300370200200341ac066a200341b0046a41086a22112903003702002003428080808080013703900620034188f0c10036028806200341e8bdc0003602fc0541002105200341003602f805200320032903b0043702a4062003200341f0046a3602a006200341f0066a41186a2004290300370300200341f0066a41106a2010290300370300200341f0066a41086a2011290300370300200320032903b0043703f006200341c8066a200341f8056a200341f0066a200ead422086200fad842018ad422086200dad84200341d0046a200c2009200a201c108a024101210920032d00c806221a0d4b200341f0066a41086a2210200341f8056a41086a290300370300200341d8036a41086a200341fc066a280200360200200320032903f8053703f006200320032902f4063703d803200341d8026a200341d8036a10c10220034194066a28020022192003419c066a280200220941d8006c6a210f20034198066a2802002117201921042009450d4a200341f9066a211120192104034020042d00002109200341d8036a200441016a41d70010f8021a20094102460d4a201020093a00002003410a3a00f0062011200341d8036a41d70010f8021a200341f0066a10b401200441d8006a2204200f470d000b200f21040c4a0b200320083e00f301200341d8016a411f6a20084220883c0000200320093600ef012003200a3600eb012003200b3700e3012003200c3600df01200320063600db01200320073b01d801200320074110763a00da010cef010b200341f0046a410c6a290200210820034194056a2802002105200341f0046a41206a28020021092003418c056a280200210f200341f0046a41186a2802002110200341c8066a410c6a200341f0046a41146a3502003e0200200320083702cc06200320053602e406200320093602e0062003200f3602dc06200320103602d806200320043602c806200341f0046a109e01200341f8056a41206a4200370300200341f8056a41146a4194acc200360200200341f8056a41086a4200370300200341bc066a200341d0046a41186a2204290300370200200341b4066a200341d0046a41106a2205290300370200200341ac066a200341d0046a41086a22092903003702002003428080808080013703900620034188f0c10036028806200341e8bdc0003602fc05200341003602f805200320032903d0043702a4062003200341f0046a3602a006200341003602c003200342013703b803200341d8036a41186a2004290300370300200341d8036a41106a2005290300370300200341d8036a41086a2009290300370300200320032903d0043703d803200341f0066a41186a200341b8026a41186a290300370300200341f0066a41106a200341b8026a41106a290300370300200341f0066a41086a200341b8026a41086a290300370300200320032903b8023703f00620034198016a200341f8056a200341d8036a200341f0066a20132015200341c8066a200e2018200341b8036a108802200328029c0121044101210920032802980122050d4c200341f0066a41086a2211200341f8056a41086a290300370300200341d8036a41086a200341fc066a280200360200200320032903f8053703f006200320032902f4063703d803200341d8026a200341d8036a10c10220034194066a28020022192003419c066a280200220f41d8006c6a211020034198066a280200211720192109200f450d4b200341f9066a211a20192109034020092d0000210f200341d8036a200941016a41d70010f8021a200f4102460d4b2011200f3a00002003410a3a00f006201a200341d8036a41d70010f8021a200341f0066a10b401200941d8006a22092010470d000b201021090c4b0b200241ff01710d1c200641ff01714101470d1c200341d8016a411f6a200842208822143c0000200320083e00f301200320073b01d801200320093600ef012003200a3600eb012003200b3700e3012003200c3600df012003200d3600db012003200741107622023a00da01200341d0046a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01d004200341f0066a411f6a20143c0000200320083e008b07200320023a00f206200320073b01f00620032009360087072003200a360083072003200b3700fb062003200c3600f7062003200d3600f306200341c8016a41086a22024200370300200342003703c80141e7d0c0004112200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d40200342103702dc032003200341b8016a3602d803200341f0046a200341d8036a103620032802f0042202450da801200341f8046a280200210520032802f40421040c410b41002105412821044101210741efeec10041efeec100410041032006200241ff01711b41ff017122021b20024103461b2202450d2741012106410121094101210a4101210d4101210c4101210e4101210f2002210520012802002202410b4d0dd6010cd5010b200241ff01710d1b200641ff01714101470d1b2001412c6a3100002115200141286a3502002116200141246a28020021022012a72105200341d8016a411f6a200842208822143c0000200320083e00f301200320073b01d801200320093600ef012003200a3600eb012003200b3700e3012003200c3600df012003200d3600db012003200741107622043a00da01200341c8066a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01c806200341d8036a411f6a20143c0000200320083e00f303200320043a00da03200320073b01d803200320093600ef032003200a3600eb032003200b3700e3032003200c3600df032003200d3600db03200e41ff01714101470d34200341f0046a200541067610ce0220032802f8042005413f7122024d0d4a20034198026a41086a220420032802f004220620024105746a220241086a29000037030020034198026a41106a2205200241106a29000037030020034198026a41186a2207200241186a2900003703002003200229000037039802024020032802f404450d00200610010b200341d8016a41186a2007290300370300200341d8016a41106a2005290300370300200341d8016a41086a200429030037030020032003290398023703d80120033500b302200341b7026a31000042208684210820032f01980220032d009a024110747221074100210620032800af02210220032800ab02210f20032900a3022113200328009f022104200328009b0221050c4b0b200341c8066a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01c8060b412a21044197efc10021050cec010b200241ff01710d1b200641ff01714101470d1b200341d8016a411f6a200842208822123c0000200320083e00f301200320073b01d801200320093600ef012003200a3600eb012003200b3700e3012003200c3600df012003200d3600db012003200741107622023a00da01200341d8036a411f6a20123c0000200320083e00f303200320023a00da03200320073b01d803200320093600ef032003200a3600eb032003200b3700e3032003200c3600df032003200d3600db03200341f0046a200341d8036a10c80120032d00f0044101470d33200341fc046a290200210820034184056a290200210b2003418c056a350200211220034190056a310000211320032902f404211420032f00f104210220032d00f3042104200341c8066a41026a200341d0046a41026a2d00003a0000200320032f01d0043b01c806200341f0066a411f6a20133c0000200320123e008b07200320043a00f206200320023b01f0062003200b37008307200320083700fb06200320143700f306200341d0046a200341f0066a10b201024020032802d8042204200e4d0d00200341d8036a20032802d0042205200e4105746a2202460d5d2002200341d8036a412010fa02450d5d0b024020032802d404450d0020032802d00410010b41b1efc0002105411421040ceb010b41002105412821044101210741efeec10041efeec100410041032006200241ff01711b41ff017122021b20024103461b2202450d2341012106410121094101210a4101210d4101210c4101210e4101210f2002210520012802002202410b4d0dd3010cd2010b200241ff01710d18200641ff01714101470d18200341d8016a411f6a200842208822123c0000200320083e00f301200320073b01d801200320093600ef012003200a3600eb012003200b3700e3012003200c3600df012003200d3600db012003200741107622023a00da01200341d0046a41026a200341f0066a41026a2d00003a0000200320032f00f0063b01d004200341f0046a411f6a20123c0000200320083e008b05200320023a00f204200320073b01f00420032009360087052003200a360083052003200b3700fb042003200c3600f7042003200d3600f304200341c8016a41086a22024200370300200342003703c80141e7d0c0004112200341c8016a1002200341b8016a41086a22072002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d3b200342103702dc032003200341b8016a3602d803200341f0066a200341d8036a103620032802f0062204450da201200341f8066a280200210520032802f40621060c3c0b41efeec10041efeec100410041032006200241ff01711b41ff017122021b20024103461b22050d03200320123703f004200341c8016a41086a22024200370300200342003703c80141a2edc000411a200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a410810030c010b41efeec10041efeec100410041032006200241ff01711b41ff017122021b20024103461b22050d02200320123703f004200341c8016a41086a22024200370300200342003703c80141c6d2c0004117200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a410810030b410121070c210b41efeec10041efeec100410041032006200241ff01711b41ff017122021b20024103461b2205450d1f0b412821040ce4010b20034188076a4200370300200341f0066a41106a4200370300200341f0066a41086a4200370300200342003703f0060b0240200341d8036a200341f0066a412010fa02450d004186f1c0002105413b21040c220b200341c8016a41086a22024200370300200342003703c80141f8f0c000410e200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d1e200341b0026a420037030020034198026a41106a420037030020034198026a41086a42003703002003420037039802200341b8016a411020034198026a4120410010042202417f460d89012002411f4d0d8901200341b8026a41186a220220034198026a41186a290300370300200341b8026a41106a220420034198026a41106a290300370300200341b8026a41086a220920034198026a41086a29030037030020032003290398023703b802200341f0046a41186a220a2002290300370300200341f0046a41106a22022004290300370300200341f0046a41086a22042009290300370300200320032903b8023703f004200341d0046a41186a200a2903002208370300200341d0046a41106a2002290300220b370300200341d0046a41086a20042903002212370300200341b0046a41086a2012370300200341b0046a41106a200b370300200341b0046a41186a2008370300200320032903f00422083703d004200320083703b0040c1f0b20034188076a4200370300200341f0066a41106a4200370300200341f0066a41086a4200370300200342003703f0060b200341d8036a200341f0066a412010fa02450d01413b21044186f1c00021052007450d1f0b200610010c1e0b41d9c1c100410520062005100302402007450d00200610010b2003410b3b01f004200341f0046a10b4010c1c0b200320083e00f301200341f7016a20084220883c0000200320093600ef012003200a3600eb012003200b3700e3012003200c3600df01200320063600db01200320073b01d801200320074110763a00da01200c21040c110b412a21044197efc10021050c050b200341b8016a41086a22024200370300200342003703b80141f0f1c100410d200341b8016a1002200341c8016a41086a2002290300370300200320032903b8013703c801420021080240200341c8016a41104188f0c100410041001004417f460d00200342003703f004200341c8016a4110200341f0046a41084100100441016a41084d0d7920032903f00421080b20024200370300200342003703b80141e085c1004116200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803200341d8036a41104188f0c100410041001004417f460d26200342003703f004200341d8036a4110200341f0046a41084100100441016a41084d0d7920032903f004210b0c270b411210002202450d8a01200342123702f406200320023602f006200341f0066a4197e5c0004112102520032802f006210620032802f406220520032802f80622046b41034b0d1c200441046a22022004490de60120054101742207200220022007491b22074100480de6012005450d3a200710002202450d95012002200620072005200520074b1b10f8021a200610010c3b0b200341f0066a2012109402024020032802f80620094d0d00024020032802f006200941d8006c6a2202280200410d460d00200210a0010b2002410d360200200241046a200341f0046a41d40010f8021a0b411710002202450d8a01200342173702f404200320023602f004200341f0046a41b786c1004117102520032802f004210220032802f404220520032802f80422046b41084f0d1c200441086a22072004490de50120054101742206200720072006491b22074100480de5012005450d3c200710002206450d95012006200220072005200520074b1b10f802210520021001200521020c3d0b024020032802f404450d0020032802f00410010b418987c20021064115210c4101450d1d418987c2002105411521040cd8010b200341186a200341f0066a2012201310d2022003280218450d2441e399c1002105411a21040b200910a001200910010cd2010b20084205200b7c5a0dec010b41a882c300104f000b200341d0046a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01d0040c030b200341c8066a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01c8060c020b200341d0046a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01d0040c010b200341d0046a41026a200341f0066a41026a2d00003a0000200320032f00f0063b01d0040b412a2104410121074197efc10021050ca6010b200341c8066a411f6a20084220883c0000200320083e00e3062003200a41087622063b01c8062003200e3600df062003200f3600db06200320163700d306200320043600cf06200320053600cb06200320064110763a00ca060cc9010b024020032802dc03450d0020032802d80310010b418987c20021054115210441010dcd010b200521060b200320083e008b072003418f076a20084220883c000020032009360087072003200a360083072003200b3700fb06200320043600f706200320063600f306200320073b01f006200320074110763a00f206200341f0066a2013201210aa01200341f0066a2015201410d302410021050ccb010b20050dd4010cd5010b200e41014b0d13200341f0046a200741d00010f8021a200341013a00f006200341013602f406200341c8006a200341f0046a200341f0066a10cc0220034195056a2003280248453a0000200341fd046a200341e0036a29030037000020034185056a200341e8036a2903003700002003418d056a200341f0036a290300370000200341043a00f404200341073a00f004200320032903d8033700f504200341f0046a10b4010c3f0b411a10002202450d7d2003421a3702f404200320023602f004200341f0046a41ce86c100411a102520032802f004210620032802f404220520032802f80422026b41034b0d16200241046a22042002490dd40120054101742207200420042007491b22074100480dd4012005450d37200710002204450d8b012004200620072005200520074b1b10f8021a200610010c380b2003200e3602f004200341c8016a41086a22024200370300200342003703c8014193cfc0004119200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a410410030cc9010b2003200e3602f004200341c8016a41086a22024200370300200342003703c80141bcedc0004116200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a410410030cc8010b20012d00092104200341c8016a41086a22024200370300200342003703c80141b1d2c0004115200341c8016a1002200341b8016a41086a22052002290300370300200320032903c8013703b801200341b8016a41104188f0c10041001003200320043a00f00420024200370300200342003703c80141eef1c0004119200341c8016a100220052002290300370300200320032903c8013703b80141012107200341b8016a4110200341f0046a410110030b410121060cbe010b200341c8046a4200370300200341b0046a41106a4200370300200341b0046a41086a4200370300200342003703b0040b200341c8066a41186a2202200341b0046a41186a290300370300200341c8066a41106a2204200341b0046a41106a290300370300200341c8066a41086a2209200341b0046a41086a290300370300200320032903b0043703c806200341fa046a200929030037010020034182056a20042903003701002003418a056a20022903003701002003418b023b01f004200320032903c8063701f204200341f0046a10b40120034187056a20034198036a41086a2903003700002003418f056a20034198036a41106a2d00003a0000200320053600fb04200320073600f704200320063600f3042003200341fa026a2d00003a00f204200320032f01f8023b01f00420032003290398033700ff04200341c8016a41086a22024200370300200342003703c80141f8f0c000410e200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a412010030b410021050b4100210f4101210741012106410121094101210a4101210d4101210c4101210e20012802002202410b4d0da301412c211d0cd8010b20062104200521070c1e0b41fd99c1002105412421040cba010b20062102200521070c1e0b200521070c200b20033500930220034197026a31000042208684210820032f01f80120032d00fa01411074722107200328008f022109200328008b02210a200329008302210b0cb8010b0cb7010b2003201620154220868422083e009302200341f8016a411f6a20084220883c00002003200e41087622073b01f8012003200236008f022003200f36008b02200320133700830220032012422088a722043600ff01200320053600fb01200320074110763a00fa01410021060c160b024020032802f404450d0020032802f00410010b41152104418987c200210541010db8010cb3010b200341c8066a41026a200341d0046a41026a2d00003a0000200320032f01d0043b01c806411a21044197efc00021050cb7010b200341c8016a41086a22024200370300200342003703c80141e7d0c0004112200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d1f200342103702dc032003200341b8016a3602d803200341f0046a200341d8036a103620032802f0042202450d7c200341f8046a280200210420032802f40421050c200b200341c8016a41086a22024200370300200342003703c801418fc0c000411c200341c8016a1002200341b8016a41086a22042002290300370300200320032903c8013703b8014100210f0240200341b8016a41104188f0c100410041001004417f460d00200341003602f004200341b8016a4110200341f0046a41044100100441016a41044d0d6220032802f004210f0b20024200370300200342003703c801418fc0c000411c200341c8016a100220042002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d20200341003602f004200341b8016a4110200341f0046a41044100100441016a41044d0d6220032802f00441016a21020c210b42e807210b0b200341f0046a200941d00010f8021a200341f0066a200b20087c200341f0046a200e2012109202200341f8066a280200210420032802f406210220032802f00621052009100141012107410021062002410020054101461b21050c8f010b200341b8016a41086a22024200370300200342003703b80141ca99c1004119200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803410021040240200341d8036a41104188f0c100410041001004417f460d00200341003602f004200341d8036a4110200341f0046a41044100100441016a41044d0d6120032802f00421040b2003200441016a3602f004200341b8016a41086a22054200370300200342003703b80141ca99c1004119200341b8016a1002200341c8016a41086a2005290300370300200320032903b8013703c801200341c8016a4110200341f0046a41041003412010002202450d74200220032903f00637000020034184056a428180808010370200200241186a200341f0066a41186a290300370000200241106a200341f0066a41106a290300370000200241086a200341f0066a41086a290300370000200320123703f0042003200236028005200320133703f8042004200341f0046a109d0220054200370300200342003703b80141b885c1004115200341b8016a1002200341d8036a41086a2005290300370300200320032903b8013703d80341002102200341d8036a41104188f0c100410041001004417f460d1f200342103702fc052003200341d8036a3602f805200341f0046a200341f8056a103720032802f004220a450d7a20032902f4042208422088a72105200341f8046a280200210720032802f40421022008a721060c200b20062104200521070c210b200341f8016a41186a200341f0066a41186a290300370300200341f8016a41106a220a200341f0066a41106a290300370300200341f8016a41086a220c200341f0066a41086a290300370300200320032903f0063703f80120042002470d18200241016a22062002490dbc012002410174220d20062006200d491b220dad4205862212422088a70dbc012012a7220e4100480dbc012002450d29200e10002206450d7c20062007200e200241057422022002200e4b1b10f8021a200710010c2a0b410021020b2004410020021b2107410121062002410120021b2104024002402005410020021b200e4d0d000240200341f0066a2004200e4105746a2202460d002002200341f0066a412010fa024521060b02402007450d00200410010b2006450d01200341f0046a41186a200341f0066a41186a290300370300200341f0046a41106a200341f0066a41106a290300370300200341f0046a41086a200341f0066a41086a290300370300200320032903f0063703f004411c10002202450d792003421c3702dc03200320023602d803200341d8036a4196d1c000411c1025200341f8056a41086a220220032802e003360200200320032903d8033703f805200341f0046a200341f8056a101e2002280200210520032802fc05210720032802f8052102200341003602e003200342013703d803200f200341d8036a101b20122013200341d8036a109a0120032802dc03210620032802e003210920032802d8032104200341c8016a41086a220a4200370300200342003703c80120022005200341c8016a1002200341b8016a41086a200a290300370300200320032903c8013703b801200341b8016a411020042009100302402006450d00200410010b2007450da901200210010ca9010b2007450d00200410010b41ecd2c00021050c020b410021040b20024200370300200342003703c80141f9d0c000411d200341c8016a100220072002290300370300200320032903c8013703b801024002400240200341b8016a41104188f0c100410041001004417f460d00200341003602f006200341b8016a4110200341f0066a41044100100441016a41044d0d5320032802f00621022005410020041b210520040d010c020b410421022005410020041b21052004450d010b2006450d002004410120041b10010b200520024d0d01200341f0046a200e10b30121050b410d21040cab010b41c5efc0002105413921040caa010b200441d8006a21040b02400340200f2004460d0120042d00002109200441d8006a210420094102470d000b0b02402017450d00201910010b200341f8016a41186a200341b0046a41186a2204290300370300200341f8016a41106a200341b0046a41106a2209290300370300200341f8016a41086a200341b0046a41086a220f290300370300200341d8016a41086a200341c8066a41096a2210290000370300200341d8016a41106a200341c8066a41116a2211290000370300200341d8016a41186a200341c8066a41196a2219290000370300200320032903b0043703f801200320032900c9063703d801200341f0066a41086a41013a0000200341f0066a41096a20032903b004370000200341f0066a41116a200f290300370000200341f0066a41196a200929030037000020034191076a200429030037000020034199076a20032900c906370000200341a1076a2010290000370000200341a9076a2011290000370000200341b1076a20192900003700002003410a3a00f006200341f0066a10b401410021090b200341b0046a20032903d00420032903d804200341e0046a290300200341e8046a29030010a801200341d0066a28020021040240201a4101470d0020032802cc0621050b02402009450d00200341d8036a41086a200341f8056a410472220941086a280200360200200320092902003703d803200341f0066a200341d8036a10cf01200341f0066a10d00120034198066a280200450d0020034194066a28020010010b20070dac010cad010b200941d8006a21090b0240034020102009460d0120092d0000210f200941d8006a2109200f4102470d000b0b410021092017450d00201910010b200341d0046a20032903c80620032903d006200341d8066a290300200341e0066a29030010a801024020032802bc03450d0020032802b80310010b02402009450d00200341d8036a41086a200341f8056a410472220941086a280200360200200320092902003703d803200341f0066a200341d8036a10cf01200341f0066a10d00120034198066a280200450d0020034194066a28020010010b200d0da7010ca8010b024020032802f404450d0020032802f00410010b41012106418987c2002105411521040b200341d0046a41026a200341f0046a41026a2d00003a0000200320032f00f0043b01d00420060da201200320083e008b072003418f076a20084220883c000020032002360087072003200f36008307200320133700fb06200320043600f706200320053600f306200320073b01f006200320074110763a00f206200341f0046a200341d8036a10c80141012107024020032d00f0044101470d0041bdeec0002105412621040c7b0b200341c8016a41086a22024200370300200342003703c80141e7d0c0004112200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d14200342103702fc052003200341b8016a3602f805200341f0046a200341f8056a103620032802f0042209450d6f200341f8046a280200210220032802f404210c0c150b200710002204450d5b0b200420026a200a360000200341b8016a41086a22054200370300200342003703b8012004200241046a200341b8016a1002200341d8036a41086a2005290300370300200320032903b8013703d803200341d8036a4110100e210202402007450d00200410010b2002450d02200341b8016a41086a22024200370300200342003703b80141d9c2c0004112200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d8034100210502400240200341d8036a41104188f0c100410041001004417f460d00200342103702f4062003200341d8036a3602f006200341f0046a200341f0066a103b20032802f0042204450d60200320032902f40422083702f404200320043602f0042008422088a722052008a72202460d010c090b200341003602f804200342043703f00441042104410021020b200241016a22072002490dac0120024101742206200720072006491b2206ad4202862208422088a70dac012008a722074100480dac012002450d05200710002209450d5d20092004200720024102742202200220074b1b10f802210220041001200221040c060b200710002202450d5a0b200220046a200a360000200341d8036a41086a22054200370300200342003703d8032002200441046a2206200341d8036a1002200341c8016a41086a2005290300370300200320032903d8033703c8014100210402400240200341c8016a41104188f0c100410041001004417f460d00200341b0046a41186a22044200370300200341b0046a41106a4200370300200341b0046a41086a4200370300200342003703b0044100200341c8016a4110200341b0046a41204100100422052005417f461b220541204922090d56200341f0066a41186a220a2004290300370300200341f0066a41106a220c200341b0046a41106a290300370300200341f0066a41086a2204200341b0046a41086a290300370300200320032903b0043703f006200341c8066a41186a200a2903002208370300200341c8066a41106a200c290300220b370300200341c8066a41086a20042903002212370300200341f8016a41086a2012370300200341f8016a41106a200b370300200341f8016a41186a2008370300200320032903f00622083703f801200320083703c806200342003703f806200342003703f0064100200341c8016a4110200341f0066a41102005412020091b2209100422052005417f461b2205410f4d0d572004290300211220032903f0062113200341d0046a41186a4200370300200341d0046a41106a4200370300200341d0046a41086a4200370300200342003703d004200341c8016a4110200341d0046a41202005411020054110491b20096a220410042205417f460d4b2005411f4d0d4b200341f0066a41186a2205200341d0046a41186a290300370300200341f0066a41106a2209200341d0046a41106a290300370300200341f0066a41086a220a200341d0046a41086a290300370300200320032903d0043703f006200341c8066a41186a20052903002208370300200341c8066a41106a2009290300220b370300200341c8066a41086a200a290300221437030020034198026a41086a201437030020034198026a41106a200b37030020034198026a41186a2008370300200320032903f006220837039802200320083703c806200342003703f806200342003703f006200341c8016a4110200341f0066a4110200441206a10042204417f460d572004410f4d0d57200341f0066a41086a2205290300210820032903f006210b200341d8016a41186a2204200341f8016a41186a290300370300200341d8016a41106a2209200341f8016a41106a290300370300200341d8016a41086a220a200341f8016a41086a290300370300200341b8026a41086a220c20034198026a41086a290300370300200341b8026a41106a220d20034198026a41106a290300370300200341b8026a41186a220e20034198026a41186a290300370300200320032903f8013703d80120032003290398023703b802200341f0066a41186a220f2004290300370300200341f0066a41106a221020092903003703002005200a290300370300200341d8036a41086a2204200c290300370300200341d8036a41106a2209200d290300370300200341d8036a41186a220a200e290300370300200320032903d8013703f006200320032903b8023703d803200341f8056a41186a200f290300370300200341f8056a41106a2010290300370300200341f8056a41086a2005290300370300200341c8066a41086a2004290300370300200341c8066a41106a2009290300370300200341c8066a41186a200a290300370300200320032903f0063703f805200320032903d8033703c80620044200370300200342003703d80320022006200341d8036a1002200341b8016a41086a2004290300370300200320032903d8033703b801200341b8016a4110100820134220882012422086842114201242208821122013a72106410121040c010b0b200341f0066a41186a2209200341f8056a41186a290300370300200341f0066a41106a220a200341f8056a41106a290300370300200341f0066a41086a220c200341f8056a41086a290300370300200341d8036a41086a220d200341c8066a41086a290300370300200341d8036a41106a220e200341c8066a41106a290300370300200341d8036a41186a220f200341c8066a41186a290300370300200320032903f8053703f006200320032903c8063703d8034100210502402004450d00200341b8036a41186a2009290300370300200341b8036a41106a200a290300370300200341b8036a41086a200c29030037030020034198036a41086a200d29030037030020034198036a41106a200e29030037030020034198036a41186a200f290300370300200320032903f0063703b803200320032903d80337039803410121050b02402007450d00200210010b2005450d00200341f8026a41186a2202200341b8036a41186a290300370300200341f8026a41106a2204200341b8036a41106a290300370300200341f8026a41086a2205200341b8036a41086a290300370300200341d8026a41086a220720034198036a41086a290300370300200341d8026a41106a220920034198036a41106a290300370300200341d8026a41186a220a20034198036a41186a290300370300200320032903b8033703f80220032003290398033703d802200341f0046a41186a2008370300200341fc046a20123e020020034198056a2005290300370300200341a0056a2004290300370300200341a8056a2002290300370300200341b8056a2007290300370300200341c0056a2009290300370300200341c8056a200a2903003703002003200b37038005200320143702f404200320063602f004200320032903f80237039005200320032903d8023703b00520034180016a20034190056a200b200810d4020c9c010b41dff0c0002105411921040c9d010b200710002202450d580b200220046a20123700002003200441086a3602f404200320023602f004200341f0066a200341f0046a101a02402007450d00200210010b20032802f00621050240200341f0066a41086a2802002202450d00200241d8006c210420052102034002402002280200410d460d00200210280b200241d8006a2102200441a87f6a22040d000b0b20032802f406450d8801200510010c88010b200710002204450d570b200320063602f404200320043602f004200621020b200341f8046a200541016a360200200420054102746a200a360200200341f0046a10a0022002450d9601200410010c96010b200721062002210d0c110b410021020b2005410020021b210d2002410120021b22072004410020021b22064105746a2105200721020340200520026b41ff004d0d11200341f0066a2002460d122002200341f0066a412010fa02450d12200241206a2204200341f0066a460d122004200341f0066a412010fa02450d12200241c0006a2204200341f0066a460d122004200341f0066a412010fa02450d12200241e0006a2204200341f0066a460d1220024180016a21022004200341f0066a412010fa020d000c120b0b410121020b200320023602f004200341c8016a41086a22024200370300200342003703c801418fc0c000411c200341c8016a1002200341b8016a41086a22042002290300370300200320032903c8013703b801200341b8016a4110200341f0046a4104100320024200370300200342003703c80141abc0c0004118200341c8016a100220042002290300370300200320032903c8013703b80102400240200341b8016a41104188f0c100410041001004417f460d00200342103702f4062003200341b8016a3602f006200341f0046a200341f0066a103620032802f0042202450d5c200341f8046a280200210420032802f40421060c010b410021020b200341f8016a41186a200341d8036a41186a290300370300200341f8016a41106a200341d8036a41106a290300370300200341f8016a41086a200341d8036a41086a290300370300200320032903d8033703f8012002410120021b210502402004410020021b22042006410020021b2202470d00200241016a22062002490da00120024101742209200620062009491b2211ad4205862208422088a70da0012008a722064100480da0012002450d08200610002210450d5e20102005200620024105742202200220064b1b10f8021a200510010c090b20052110200221110c080b4108210a4100210741002106410021050b200341f0046a2009109c02200341f8016a41186a220c200341f0066a41186a290300370300200341f8016a41106a220d200341f0066a41106a290300370300200341f8016a41086a220e200341f0066a41086a290300370300200320032903f0063703f801024020052006470d0020022007470d00200241016a22052002490d9e0120024101742206200520052006491b2206ad42f8007e2208422088a70d9e012008a722104100480d9e012002450d09201010002205450d5d2005200a2010200241f8006c2202200220104b1b10f8021a200a10010c0a0b200a2105200221060c090b200710002204450d530b200420026a2009360000200341b8016a41086a22054200370300200342003703b8012004200241046a200341b8016a1002200341c8016a41086a2005290300370300200320032903b8013703c801200341c8016a4110100e210202402007450d00200410010b024002402002450d00200341286a200341f0066a10b0012003290328200341286a41086a29030084500d01200341fc046a200341f0066a41086a29030037020020034184056a200341f0066a41106a2903003702002003418c056a20034188076a290300370200200320093602f004200320032903f0063702f404411010002202450d56200342103702dc03200320023602d803200341d8036a41fb86c10041101025200341f8056a41086a220220032802e003360200200320032903d8033703f805200341f0046a200341f8056a1097022002280200210420032802fc05210520032802f8052102200341b8016a41086a22074200370300200342003703b80120022004200341b8016a1002200341c8016a41086a2007290300370300200320032903b8013703c801200341c8016a4110100e210402402005450d00200210010b20040d7d411310002202450d60200342133702f404200320023602f004200341f0046a41e886c1004113102520032802f004210620032802f404220520032802f80422026b41034b0d0e200241046a22042002490d9d0120054101742207200420042007491b22074100480d9d012005450d15200710002204450d642004200620072005200520074b1b10f8021a200610010c160b41f09ac1002105412221040c8c010b41929bc1002105413021040c8b010b200341d0046a41086a22072004417f6a2204360200200520044105746a220429000021082004290008210b20042900102112200241186a200441186a290000370000200220123700102002200b37000820022008370000200341f0046a41086a2007280200360200200320032903d0043703f004200341f0066a200341f0046a10c901411210002202450d5c200342123702f404200320023602f004200341f0046a4185efc00041121025200341f8056a41086a220220032802f804360200200320032903f0043703f805200341d8036a200341f8056a101e2002280200210420032802fc05210520032802f805210242002108200341c8016a41086a22074200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2007290300370300200320032903c8013703b801200341b8016a4110100802402005450d00200210010b200341f0046a41186a200341d8036a41186a290300370300200341f0046a41106a200341d8036a41106a290300370300200341f0046a41086a200341d8036a41086a290300370300200320032903d8033703f004200341c8016a41086a22024200370300200342003703c80141f0f1c100410d200341c8016a1002200341b8016a41086a22042002290300370300200320032903c8013703b8010240200341b8016a41104188f0c100410041001004417f460d00200342003703f805200341b8016a4110200341f8056a41084100100441016a41084d0d4220032903f80521080b20024200370300200342003703c80141c6d2c0004117200341c8016a100220042002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d0d200342003703f805200341b8016a4110200341f8056a41084100100441016a41084d0d4220032903f805210b410f2102410f10002204450d0e0c86010b410021090b2009410120091b220a2002410020091b4105746a2105200a21020340200520026b41ff004d0d0e200341d8036a2002460d0b2002200341d8036a412010fa02450d0b200341d8036a2106200241206a2204200341d8036a460d182004200341d8036a412010fa02450d0f200241c0006a2204200341d8036a460d182004200341d8036a412010fa02450d10200241e0006a2204200341d8036a460d1820024180016a21022004200341d8036a412010fa020d000b2004210620090d180c190b200610002210450d550b2010200441057422056a220220032903f801370000200241186a200341f8016a41186a290300370000200241106a200341f8016a41106a290300370000200241086a200341f8016a41086a290300370000200341003602f804200342013703f004200441016a2202200341f0046a101b024002402002450d00200541206a210c4100200341f0046a41086a28020022046b210920032802f004210a20032802f40421062010210d0340200d21020240200620096a411f4b0d00200441206a22052004490d9a012006410174220d20052005200d491b22054100480d9a0120051000210d024002402006450d00200d450d31200d200a20052006200620054b1b10f8021a200a10010c010b200d450d300b200d210a200521060b200241206a210d200a20046a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200941606a2109200441206a2104200c41606a220c0d000b200341f8046a2004360200200320063602f4042003200a3602f0040c010b200341f0046a41086a280200210420032802f404210620032802f004210a0b200341c8016a41086a22024200370300200342003703c80141abc0c0004118200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200a2004100302402006450d00200a10010b02402011450d00201010010b200341f0066a41186a200341d8036a41186a290300370300200341f0066a41106a200341d8036a41106a290300370300200341f0066a41086a200341d8036a41086a290300370300200320032903d8033703f006200341f0046a200741d00010f8021a411910002202450d49200342193702cc06200320023602c806200341c8066a41dfbfc00041191025200341b0046a41086a220220032802d006360200200320032903c8063703b004200341f0066a200341b0046a101e2002280200210520032802b404210620032802b0042102200341003602d006200342013703c806200341f0046a200341c8066a101c20032802cc06210920032802d006210a20032802c8062104200341c8016a41086a220c4200370300200342003703c80120022005200341c8016a1002200341b8016a41086a200c290300370300200320032903c8013703b801200341b8016a41102004200a100302402009450d00200410010b02402006450d00200210010b200341f0046a10a001200341f0066a41186a200341d8036a41186a290300370300200341f0066a41106a200341d8036a41106a290300370300200341f0066a41086a200341d8036a41086a290300370300200320032903d8033703f006412010002202450d4a2003418c056a4100360200200341fc046a428180808010370200200341f8056a41086a2903002108200341f8056a41106a290300210b20032903f8052112200241186a200341f8056a41186a290300370000200241106a200b370000200241086a2008370000200220123700002003420137028405200320023602f8042003200e3602f4042003200f3602f004411510002204450d4b200342153702cc06200320043602c806200341c8066a41c3c0c00041151025200341b0046a41086a220420032802d006360200200320032903c8063703b004200341f0066a200341b0046a101e20032802b404210520032802b00422062004280200200341f0046a10a30202402005450d00200610010b20021001200341fd046a200341f8056a41086a29030037000020034185056a200341f8056a41106a2903003700002003418d056a200341f8056a41186a29030037000020034195056a20032903d8033700002003419d056a200341d8036a41086a290300370000200341a5056a200341d8036a41106a290300370000200341ad056a200341d8036a41186a290300370000200341003a00f404200341073a00f004200320032903f8053700f504200341bc056a200e360200200341b8056a200f360200200341f0046a10b4010b20071001410021050c9f010b201010002205450d530b2005200741f8006c220a6a200341f0046a41d00010f80222022004360250200241ec006a200c290300370200200241e4006a200d290300370200200241dc006a200e290300370200200220032903f8013702542003200741016a22023602f804200320063602f404200320053602f004200341153602dc03200341b885c1003602d803200341f0046a200341d8036a101d02402002450d00200a41f8006a210420052102034020021028200241f8006a2102200441887f6a22040d000b0b02402006450d00200510010b200910a001200910014100210241012107200f4102470d750c7c0b200e10002206450d520b200620044105746a220220032903f801370000200241186a200341f8016a41186a290300370000200241106a200a290300370000200241086a200c29030037000041012107200341f0046a41186a200441016a36020020034184056a200d360200200320083703f8042003200b3703f0042003200536028c0520032006360280052009200341f0046a109d02410021060c7f0b024020022005460d000340200341f0066a2002460d022002200341f0066a412010fa02450d022005200241206a2202470d000b0b410f10002202450d592003420f3702f404200320023602f004200341f0046a41ddd2c000410f1025200341d8036a41086a220220032802f804360200200320032903f0043703d803200341f0066a200341d8036a101e2002280200210420032802dc03210520032802d80321022003427f3703f004200341c8016a41086a22094200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2009290300370300200320032903c8013703b801200341b8016a4110200341f0046a4108100302402005450d00200210010b200341b8026a41186a2204200341f0066a41186a290300370300200341b8026a41106a200341f0066a41106a290300370300200341b8026a41086a200341f0066a41086a290300370300200320032903f0063703b8022006200d470d0a200641016a22022006490d900120064101742205200220022005491b220dad4205862208422088a70d90012008a722024100480d90012006450d0b20021000220e450d5a200e2007200220064105742205200520024b1b10f8021a200710010c0c0b41fbedc0002105411f2104200d450d8301200710010c83010b20062104200521070c070b2002210620090d0d0c0e0b42e807210b410f2102410f100022040d780b200241011019000b4100210620022005460d090340200341d8036a2002460d082002200341d8036a412010fa02450d092005200241206a2202470d000c0a0b0b2004210620090d090c0a0b2004210620090d080c090b200710002204450d4e0b200420026a2009360000200341b8016a41086a22054200370300200342003703b8012004200241046a220a200341b8016a1002200341d8036a41086a2005290300370300200320032903b8013703d803410021020240200341d8036a41104188f0c100410041001004417f460d00200342103702fc052003200341d8036a3602f805200341f0046a200341f8056a103620032802f0042206450d4d200341f0046a41086a280200210520032802f404210220032902f4042108200341b8016a41086a220c4200370300200342003703b8012004200a200341b8016a1002200341c8016a41086a200c290300370300200320032903b8013703c801200341c8016a411010082008422088a7210a2008a7210c2007450d660c650b41012106410021054100210c4100210a20070d640c650b2007210e0c010b20021000220e450d4e0b200e200641057422056a220220032903b802370000200241186a2004290300370000200241106a200341b8026a41106a290300370000200241086a200341b8026a41086a290300370000200341003602f804200342013703f004200641016a2202200341f0046a101b024002402002450d00200541206a210a4100200341f0046a41086a28020022046b210620032802f004210920032802f4042107200e210c0340200c21020240200720066a411f4b0d00200441206a22052004490d87012007410174220c20052005200c491b22054100480d870120051000210c024002402007450d00200c450d41200c200920052007200720054b1b10f8021a200910010c010b200c450d400b200c2109200521070b200241206a210c200920046a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200641606a2106200441206a2104200a41606a220a0d000b200341f8046a2004360200200320073602f404200320093602f0040c010b200341f0046a41086a280200210420032802f404210720032802f00421090b200341c8016a41086a22024200370300200342003703c80141e7d0c0004112200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a411020092004100302402007450d00200910010b200d450d70200e10010c700b200341d8036a210620090d020c030b200221060b2009450d010b200c450d00200a10010b02402006450d0041e3eec0002105412221040c4c0b200341c8066a200341f0066a10b201200341f0046a41186a2205200341d8036a41186a290300370300200341f0046a41106a2207200341d8036a41106a290300370300200341f0046a41086a2204200341d8036a41086a290300370300200320032903d8033703f004024020032802d006220220032802cc06470d00200241016a22062002490d7f20024101742209200620062009491b220aad4205862208422088a70d7f2008a722064100480d7f024002402002450d0020032802c806210c200610002209450d492009200c20062002410574220d200d20064b1b10f8021a200c10010c010b200610002209450d480b2003200a3602cc06200320093602c8060b200341c8066a41086a2206200241016a36020020032802c80620024105746a220220032903f004370000200241086a2004290300370000200241106a2007290300370000200241186a200529030037000020042006280200360200200320032903c8063703f004200341f0066a200341f0046a10c901411210002202450d42200342123702f404200320023602f004200341f0046a4185efc00041121025200341f8056a41086a220220032802f804360200200320032903f0043703f805200341d8036a200341f8056a101e2002280200210420032802fc05210520032802f8052102200341c8016a41086a22074200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2007290300370300200320032903c8013703b801200341b8016a4110200341f0066a4120100302402005450d00200210010b410f10002202450d432003420f3702f404200320023602f004200341f0046a41ddd2c000410f1025200341f8056a41086a220220032802f804360200200320032903f0043703f805200341d8036a200341f8056a101e2002280200210420032802fc05210520032802f80521022003427f3703f004200341c8016a41086a22074200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2007290300370300200320032903c8013703b801200341b8016a4110200341f0046a410810032005450d6b200210010c6b0b41eac4c10041331042000b41b0cdc200104f000b41c0e6c200104f000b41d881c300104f000b4198cdc200104f000b41c4d5c200104f000b4180cdc200104f000b41b0acc200104f000b41b8b0c300104f000b41fcabc200104f000b4198e8c200104f000b41eac4c10041331042000b41eac4c10041331042000b20034184056a4101360200200341fc046a4101360200200341033602f406200341ecf1c1003602f006200341e0c3c1003602f804200341023602f4042003418882c3003602f0042003200341f0066a36028005200341f0046a419882c3001071000b41f081c300104f000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200541011019000b411241011019000b412041011019000b41eac4c10041331042000b411541011019000b411941011019000b41eac4c10041331042000b41eac4c10041331042000b2019450d00200610010b41eac4c10041331042000b200341c8066a41186a200341f0066a41186a290000370300200341c8066a41106a200341f0066a41106a290000370300200341c8066a41086a200341f0066a41086a290000370300200320032900f0063703c80641eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411241011019000b411241011019000b411741011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411a41011019000b200341c8066a41186a200341f0066a41186a290000370300200341c8066a41106a200341f0066a41106a290000370300200341c8066a41086a200341f0066a41086a290000370300200320032900f0063703c8060b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200741011019000b200741011019000b200741011019000b200741041019000b41eac4c10041331042000b411941011019000b412041011019000b411541011019000b412041011019000b200741011019000b200541011019000b411041011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411c41011019000b200641011019000b201041081019000b200e41011019000b41eac4c10041331042000b411241011019000b411341011019000b411241011019000b410f41011019000b41eac4c10041331042000b200741011019000b200641011019000b410f41011019000b200241011019000b4105211d0c400b4105211d0c3f0b4105211d0c3e0b4105211d0c3d0b4106211d0c3c0b4106211d0c3b0b4106211d0c3a0b4106211d0c390b4106211d0c380b4107211d0c370b4108211d0c360b410a211d0c350b410c211d0c340b412c211d0c330b410c211d0c320b412c211d0c310b410c211d0c300b412c211d0c2f0b410c211d0c2e0b200410010b200341f0046a41186a2204200341f0066a41186a290300370300200341f0046a41106a2207200341f0066a41106a290300370300200341f0046a41086a220d200341f0066a41086a290300370300200320032903f0063703f004024002400240200a200c470d0020022005470d00200241016a220a2002490d232002410174220c200a200a200c491b2217ad4205862208422088a70d232008a7220a4100480d232002450d01200a1000221a450d0a201a2006200a200241057422022002200a4b1b10f8021a200610010c020b2006211a200221170c010b200a1000221a450d080b201a20054105746a220220032903f004370000200241186a2004290300370000200241106a2007290300370000200241086a200d290300370000411310002202450d06200342133702f404200320023602f004200341f0046a41e886c1004113102520032802f004211002400240024020032802f404220220032802f80422116b41044f0d00201141046a22042011490d2320024101742207200420042007491b22194100480d232002450d01201910002204450d0b2004201020192002200220194b1b10f802210220101001200221100c020b200221190c010b201910002210450d090b201020116a2009360000200341003602f804200342013703f004200541016a2202200341f0046a101b024002402002450d00200541057441206a210c4100200341f0046a41086a28020022046b210620032802f004210a20032802f4042107201a210d0340200d21020240200720066a411f4b0d00200441206a22052004490d242007410174220d20052005200d491b22054100480d2420051000210d024002402007450d00200d450d09200d200a20052007200720054b1b10f8021a200a10010c010b200d450d080b200d210a200521070b200241206a210d200a20046a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200641606a2106200441206a2104200c41606a220c0d000b200341f8046a2004360200200320073602f4042003200a3602f0040c010b200341f8046a280200210420032802f404210720032802f004210a0b200341b8016a41086a22024200370300200342003703b8012010201141046a200341b8016a1002200341c8016a41086a2002290300370300200320032903b8013703c801200341c8016a4110200a2004100302402007450d00200a10010b02402019450d00201010010b2017450d00201a10010b200341fc046a200341f0066a41086a29030037020020034184056a200341f0066a41106a2903003702002003418c056a20034188076a290300370200200320093602f004200320032903f0063702f404411010002202450d03200342103702dc03200320023602d803200341d8036a41fb86c10041101025200341f8056a41086a220220032802e003360200200320032903d8033703f805200341f0046a200341f8056a1097022002280200210520032802fc05210720032802f8052104410110002202450d042002200e3a0000200341b8016a41086a22064200370300200342003703b80120042005200341b8016a1002200341d8036a41086a2006290300370300200320032903b8013703d803200341d8036a4110200241011003200210012007450d00200410010b4101210241012107200f4102460d070b200f4105470d070c080b200541011019000b411041011019000b410141011019000b411341011019000b200a41011019000b201941011019000b20020d010b410021060c030b200910a00120091001410021060c020b2003420f3702fc05200320043602f805200341f8056a41ddd2c00020021025200341c8066a41086a2202200328028006360200200320032903f8053703c806200341f0046a200341c8066a101e2002280200210420032802cc06210520032802c80621022003200b20087c3703f805200341c8016a41086a22074200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2007290300370300200320032903c8013703b801200341b8016a4110200341f8056a410810032005450d00200210010b410021050c070b410121094101210a4101210d4101210c4101210e4101210f41002105024020012802002202410b4d0d00412c211d0c1e0b410c211d0c1d0b200341b8016a41086a22024200370300200342003703b80141feefc000411c200341b8016a1002200341d8036a41086a22092002290300370300200320032903b8013703d8034100210702400240024002400240024002400240200341d8036a41104188f0c100410041001004417f460d00200342003703f804200342003703f004200341d8036a4110200341f0046a411041001004220a417f460d02200a410f4d0d02200341f8046a290300210b20032903f00421130c010b420021134200210b0b20024200370300200342003703b801419af0c0004115200341b8016a100220092002290300370300200320032903b8013703d80302400240200341d8036a41104188f0c100410041001004417f460d00200341003602f004200341d8036a4110200341f0046a41044100100441016a41044d0d0120032802f00421070b200341e8006a201520142007ad420010fc02200341d8006a2003290368200341e8006a41086a29030042c0843d420010fb02200341f8006a200341f0066a2013200329035822122012201354200341d8006a41086a2903002212200b542012200b511b22021b2213200b201220021b220b10d20202402003280278450d0041c5f0c0002105411a21040c0c0b200341b8016a41086a22024200370300200342003703b80141aff0c0004116200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803410021070240200341d8036a41104188f0c100410041001004417f460d00200341003602f004200341d8036a4110200341f0046a41044100100441016a41044d0d0320032802f00421070b2003200741016a3602f004200341b8016a41086a22024200370300200342003703b80141aff0c0004116200341b8016a1002200341d8036a41086a2002290300370300200320032903b8013703d803200341d8036a4110200341f0046a41041003200341cf056a20084220883c0000200341cb056a20083e0000200341f0046a41186a200b370300200341c7056a200e360000200341c3056a200f360000200341bb056a2016370000200341b7056a2004360000200341b3056a2005360000200341a8056a200341f0066a41186a290300370300200341a0056a200341f0066a41106a29030037030020034198056a200341f0066a41086a290300370300200320063b01b005200341b2056a20064110763a0000200320143703f804200320153703f0042003201337038005200320032903f00637039005411210002202450d03200342123702dc03200320023602d803200341d8036a4197e5c0004112102520032802d803210202400240024020032802dc03220420032802e00322056b41044f0d00200541046a22062005490d1a20044101742209200620062009491b220a4100480d1a2004450d01200a10002206450d0720062002200a20042004200a4b1b10f802210420021001200421020c020b2004210a0c010b200a10002202450d050b200220056a2007360000200341003602e003200342013703d80320034190056a200341d8036a101e200341f8046a290300210820032903f004210b024002400240024020032802dc03220920032802e00322046b41104f0d00200441106a22062004490d1b2009410174220c20062006200c491b220c4100480d1b2009450d0120032802d803210d200c10002206450d092006200d200c20092009200c4b1b10f8021a200d10010c020b20032802d80321060c020b200c10002206450d070b2003200c3602dc03200320063602d8030b200620046a220620083700082006200b370000200341e0036a2206200441106a360200200341b0056a200341d8036a101e20034188056a2903002108200341f0046a41106a290300210b024002400240024020032802dc03220c200628020022066b41104f0d00200641106a22042006490d1b200c4101742209200420042009491b22094100480d1b200c450d0120032802d803210d200910002204450d0a2004200d2009200c200c20094b1b10f8021a200d10010c020b20032802d8032104200c21090c020b200910002204450d080b200320093602dc03200320043602d8030b200420066a220c2008370008200c200b370000200341b8016a41086a220c4200370300200342003703b8012002200541046a200341b8016a1002200341d8036a41086a200c290300370300200320032903b8013703d803200341d8036a41102004200641106a100302402009450d00200410010b0240200a450d00200210010b200341fc046a200736020041002105200341f8046a41003a0000200341093a00f004200341f0046a10b4010c0a0b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411241011019000b200a41011019000b200c41011019000b200941011019000b41002106410121074106211d0c1b0b200320083e00f303200341f7036a20084220883c0000200320093600ef032003200a3600eb032003200b3700e3032003200c3600df03200320063600db03200320073b01d803200320074110763a00da03024002400240411410002202450d00200342143702f404200320023602f004200341f0046a41eeefc10041141025200341c8066a41086a220220032802f804360200200320032903f0043703c806200341f8056a200341c8066a101e2002280200210420032802cc06210520032802c8062102200341c8016a41086a22074200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2007290300370300200320032903c8013703b8014100210402400240200341b8016a41104188f0c100410041001004417f460d00200342003703f804200342003703f004200341b8016a4110200341f0046a4110410010042204417f460d012004410f4d0d01200341f8046a290300211e20032903f004211f410121042005450d040c030b20050d020c030b41eac4c10041331042000b411441011019000b200210010b024002400240411410002202450d00200342143702f404200320023602f004200341f0046a41eeefc10041141025200341c8066a41086a220220032802f804360200200320032903f0043703c806200341d8036a200341c8066a101e2002280200210520032802cc06210720032802c806210242002108200341c8016a41086a22064200370300200342003703c80120022005200341c8016a1002200341b8016a41086a2006290300370300200320032903c8013703b80102400240200341b8016a41104188f0c100410041001004417f460d00200342003703f804200342003703f004200341b8016a4110200341f0046a4110410010042205417f460d012005410f4d0d01200341f8046a290300211520032903f00421082007450d040c030b4200211520070d020c030b41eac4c10041331042000b411441011019000b200210010b4200210b200341c8016a41086a22024200370300200342003703c80141e7f5c10041fbf5c10020082015845022051b4114200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b80102400240024002400240200341b8016a41104188f0c100410041001004417f460d00200342003703f804200342003703f004200341b8016a4110200341f0046a4110410010042202417f460d022002410f4d0d02200341f8046a290300211620032903f004210b0c010b420021160b02402013200b7c22202013542202201220167c2002ad7c221420125420142012511b450d0041f58bc2002105412821040c060b0240201f420020041b221f20207d2221201f56201e420020041b221e20147d201f202054ad7d2214201e562014201e511b4101470d00419d8cc2002105411d21040c060b2005450d02200341c8016a41086a22024200370300200342003703c80141bef0c100411b200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d02200342003703f804200342003703f004200341b8016a4110200341f0046a4110410010042202417f460d012002410f4d0d01201320032903f004542012200341f8046a29030022205420122020511b450d0241ba8cc2002105411f21040c050b41eac4c10041331042000b41eac4c10041331042000b200341106a200341f8056a10ca01024020032802102205450d00200328021421040c030b0240200820137c22202008542202201520127c2002ad7c220820155420082015511b450d0041d98cc2002105412d21040c030b200341f8056a200341d8036a412010fa02450d00200341f8056a2021201410aa0142002114200341c8016a41086a22024200370300200342003703c80141d9f0c1004116200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801024002400240200341b8016a41104188f0c100410041001004417f460d00200342003703f804200342003703f004200341b8016a4110200341f0046a4110410010042202417f460d022002410f4d0d02200341f8046a290300211520032903f00421140c010b420021150b02402014200b7d221e201456201520167d2014200b54ad7d221420155620142015511b0d002003201e3703f004200320143703f804200341c8016a41086a22024200370300200342003703c80141d9f0c1004116200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200341f0046a411010030b200341d8036a2020200810c2021a200341f0046a41086a41023a0000200341f9046a20032903f80537000020034181056a200341f8056a41086a29030037000020034189056a200341f8056a41106a29030037000020034191056a200341f8056a41186a29030037000020034199056a20032903d803370000200341a1056a200341d8036a41086a290300370000200341a9056a200341d8036a41106a290300370000200341b1056a200341d8036a41186a290300370000200341013a00f004200341d8056a2016370300200341d0056a200b370300200341c8056a2012370300200341c0056a2013370300200341f0046a10b4010c010b41eac4c10041331042000b410021050b0b410121074105211d0c170b410121070b41012106410121094101210a4101210d4101210c4101210e4101210f024020012802002202410b4d0d00412c211d0c160b410c211d0c150b200e10010b4101210920024102470d020c030b200a10010b02402006450d00200c10010b4100210920024102460d010b20024103470d012009450d0102402006450d00200c10010b2007450d01200a10010c010b2009200d45720d00200e10010b4100210e4101210741012106410121094101210a4101210d4101210c410b211d0c0e0b200210010b0240024002400240024002402006450d002003200c3602b803200f2017470d012006200a4105746a210920062102410021050340200920026b41ff004d0d03200341f8056a2002460d0420052002200341f8056a412010fa0222044100476a21052004450d04200241206a2204200341f8056a460d0420052004200341f8056a412010fa0222044100476a21052004450d04200241c0006a2204200341f8056a460d0420052004200341f8056a412010fa0222044100476a21052004450d04200241e0006a2204200341f8056a460d0420024180016a210220052004200341f8056a412010fa0222044100476a210520040d000c040b0b41ecc0c000210541132104200d4102460d0e0c0f0b41ffc0c0002105411021042019450d0b0c0a0b20022009460d012006200a4105746a21090340200341f8056a2002460d0120052002200341f8056a412010fa0222044100476a21052004450d014100210f2009200241206a2202470d000c030b0b4101210f0c010b4100210f0b200c20114105746a210e200c210241002104024002400240024002400240024002400240024002400240024002400240024002400340200e20026b41ff004d0d01200341f8056a2002460d0220042002200341f8056a412010fa0222094100476a21042009450d02200241206a2209200341f8056a460d0220042009200341f8056a412010fa0222094100476a21042009450d02200241c0006a2209200341f8056a460d0220042009200341f8056a412010fa0222094100476a21042009450d02200241e0006a2209200341f8056a460d0220024180016a210220042009200341f8056a412010fa0222094100476a210420090d000c020b0b2002200e460d020340200341f8056a2002460d0120042002200341f8056a412010fa0222094100476a21042009450d0141002109200e200241206a2202470d000c020b0b410121090b201041ff0171450d010c020b41002109201041ff01710d010b20090d01200341f0046a41186a2204200341f8056a41186a290300370300200341f0046a41106a2209200341f8056a41106a290300370300200341f0046a41086a221b200341f8056a41086a290300370300200320032903f8053703f0040240024002400240024002402011201a470d00201a41016a2202201a490d12201a410174220e20022002200e491b2222ad4205862208422088a70d122008a7220e4100480d12201a450d01200e10002202450d042002200c200e201a410574221a201a200e4b1b10f8021a200c10010c020b200c2102201a21220c020b200e10002202450d020b200320023602b803200220114105746a210e0b200e20032903f004370000200e41186a2004290300370000200e41106a2009290300370000200e41086a201b290300370000201141016a21110240200f450d00200a20054d0d022006200a417f6a220a4105746a220429000021082004290008210b20042900102112200620054105746a220541186a200441186a290000370000200520123700102005200b370008200520083700000b2002210c2006211b2019211c2022211a0c040b200e41011019000b41c8acc2002005200a104e000b200f0d00200341f0046a41186a2205200341f8056a41186a290300370300200341f0046a41106a220e200341f8056a41106a290300370300200341f0046a41086a220f200341f8056a41086a290300370300200320032903f8053703f004024002400240200a2019470d00201941016a22022019490d0e2019410174221b20022002201b491b221cad4205862208422088a70d0e2008a722024100480d0e2019450d0120021000221b450d05201b2006200220194105742219201920024b1b10f8021a200610010c020b2006211b2019211c0c010b20021000221b450d030b201b200a4105746a220220032903f004370000200241186a2005290300370000200241106a200e290300370000200241086a200f290300370000200a41016a210a2009450d01201120044d0d03200c2011417f6a22114105746a220229000021082002290008210b20022900102112200c20044105746a220441186a200241186a290000370000200420123700102004200b370008200420083700000c010b418fc1c00021054116210420190d100c110b20034195056a20032903c806370000200341fd046a200341f8056a41086a29030037000020034185056a200341f8056a41106a2903003700002003418d056a200341f8056a41186a2903003700002003419d056a200341c8066a41086a290300370000200341a5056a200341c8066a41106a290300370000200341ad056a200341c8066a41186a290300370000200341013a00f404200341073a00f004200320032903f8053700f504200341bc056a2011360200200341b8056a200a360200200341b5056a20103a0000200341f0046a10b401200341f0046a109e02200341f0046a41086a2802002104024020032802f0042202450d0020032802f404450d00200210010b02400240200a20184f22050d0041002004410020021b220220116b2204200420024b1b2018490d002003418c056a201136020020034188056a201a36020020034180056a200a360200200341fc046a201c3602002003200c360284052003201b3602f804200320183602f404200320173602f004411510002202450d01200342153702f406200320023602f006200341f0066a41c3c0c00041151025200341e0036a220220032802f806360200200320032903f0063703d803200341c8066a200341d8036a101e20032802dc03210420032802d80322052002280200200341f0046a10a3022004450d0820051001201c0d090c0a0b024002402005450d00200341fd046a200341c8066a41086a29030037000020034185056a200341c8066a41106a2903003700002003418d056a200341e0066a290300370000200341023a00f404200341073a00f004200320032903c8063700f504200341f0046a10b401411910002202450d05200342193702f404200320023602f004200341f0046a41dfbfc00041191025200341f0066a41086a220220032802f804360200200320032903f0043703f006200341c8066a200341f0066a101e2002280200210420032802f406210520032802f0062102200341c8016a41086a22064200370300200342003703c80120022004200341c8016a1002200341b8016a41086a2006290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d01200342103702b4042003200341b8016a3602b004200341f0046a200341b0046a103820032802f0042206410d460d06200341f0066a200341f0046a410472220941cc0010f8021a200341f0046a41086a220a4200370300200342003703f00420022004200341f0046a1002200341b0046a41086a200a290300370300200320032903f0043703b004200341b0046a41101008200341d8036a200341f0066a41cc0010f8021a200341f0066a200341d8036a41cc0010f8021a02402005450d00200210010b200320063602f0042009200341f0066a41cc0010f8021a200341013a00d803200320183602dc03200341d0006a200341f0046a200341d8036a10cc0220034195056a2003280250453a0000200341fd046a200341c8066a41086a29030037000020034185056a200341c8066a41106a2903003700002003418d056a200341e0066a290300370000200341043a00f404200341073a00f004200320032903c8063700f504200341f0046a10b401411521024115100022040d080c110b200341fd046a200341d0066a29030037000020034185056a200341d8066a2903003700002003418d056a200341e0066a290300370000200341033a00f404200341073a00f004200320032903c8063700f504200341f0046a10b4010c060b200341d8036a200341f0066a41cc0010f8021a2005450d0520021001411521024115100022040d060c0f0b411541011019000b200241011019000b41c8acc20020042011104e000b411941011019000b41eac4c10041331042000b41152102411510002204450d090b200342153702f404200320043602f004200341f0046a41c3c0c00020021025200341f0066a41086a220220032802f804360200200320032903f0043703f006200341c8066a200341f0066a101e2002280200210520032802f406210620032802f0062104200341c8016a41086a22024200370300200342003703c80120042005200341c8016a1002200341b8016a41086a22052002290300370300200320032903c8013703b801200341b8016a4110100802402006450d00200410010b20024200370300200342003703c80141abc0c0004118200341c8016a100220052002290300370300200320032903c8013703b80141002106024002400240200341b8016a41104188f0c100410041001004417f460d00200342103702f4062003200341b8016a3602f006200341f0046a200341f0066a103620032802f0042202450d0a410021112002410120021b210f20032802f40421192002452117200341f0046a41086a280200410020021b2206450d02200341c8066a200f6b21104100210a200f210e41002111410021020340024002402011450d00200241057421040340200220064f0d0b20102004460d02200f20046a2205200341c8066a412010fa02450d02200a20026a220920064f0d0d200e20046a22092005290000370000200941186a200541186a290000370000200941106a200541106a290000370000200941086a200541086a290000370000200441206a21042006200241016a2202470d000c060b0b200f20024105746a21040340200220064f0d0a200341c8066a2004460d012004200341c8066a412010fa02450d01200441206a21042006200241016a2202470d000c040b0b200e41606a210e200a417f6a210a201141016a2111200241016a22022006470d000c030b0b4101210f410121170b410021110b200341003602f804200342013703f004200620116b2202200341f0046a101b024002402002450d00200641057420114105746b21104100200341f0046a41086a280200220e6b210920032802f004210a20032802f40421064100210203400240200620096a411f4b0d00200e20026a220541206a22042005490d0720064101742205200420042005491b22044100480d07200410002105024002402006450d002005450d0b2005200a20042006200620044b1b10f8021a200a10010c010b2005450d0a0b2005210a200421060b200a200e6a20026a2204200f20026a2205290000370000200441186a200541186a290000370000200441106a200541106a290000370000200441086a200541086a290000370000200941606a21092010200241206a2202470d000b200341f8046a200e20026a2204360200200320063602f4042003200a3602f0040c010b200341f8046a280200210420032802f404210620032802f004210a0b200341c8016a41086a22024200370300200342003703c80141abc0c0004118200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a4110200a2004100302402006450d00200a10010b2017201945720d00200f10010b201c450d010b201b10010b0240201a450d00200c10010b410021050c080b1018000b41b08dc20020022006104e000b200441011019000b41c08dc20020092006104e000b41eac4c10041331042000b200241011019000b200610010b201a450d0020032802b8031001200d4102460d010c020b200d4102470d010b200710a001200710010b4100210d4101210741012106410121094101210a4109211d0c010b200320083703f004200341c8016a41086a22024200370300200342003703c80141a0a5c100410d200341c8016a1002200341b8016a41086a22052002290300370300200320032903c8013703b801200341b8016a4110200341f0046a41081003200341013a00f00420024200370300200342003703c80141f2a1c1004113200341c8016a100220052002290300370300200320032903c8013703b801200341b8016a4110200341f0046a4101100320024200370300200342003703c80141daa3c1004115200341c8016a100220052002290300370300200320032903c8013703b8010240024002400240200341b8016a41104188f0c100410041001004417f460d00200342003703f004200341b8016a4110200341f0046a41084100100441016a41084d0d0220032903f004210b0c010b4205210b0b200341c8016a41086a22024200370300200342003703c80141cbbac1004112200341c8016a1002200341b8016a41086a22062002290300370300200320032903c8013703b8014100210541012107024002400240200341b8016a41104188f0c100410041001004417f460d00200342003703f004200341b8016a4110200341f0046a41084100100441016a41084d0d0220032903f0042112410021090c010b410121090b200320083703f00420024200370300200342003703c80141cbbac1004112200341c8016a100220062002290300370300200320032903c8013703b801200341b8016a4110200341f0046a41081003024002400240024002402012500d00024020090d00427f200b200b7c22132013200b541b220b4200510d042008200b8022082012200b80220b580d0302402008200b42017c2212510d00200341c8016a41086a22024200370300200342003703c80141c8f2c0004112200341c8016a1002200341b8016a41086a2002290300370300200320032903c8013703b801200341b8016a41104188f0c100410041001004417f460d06200342103702f4062003200341b8016a3602f006200341f0046a200341f0066a103620032802f0042211450d032011450d06200341f8046a280200220c450d062011410120111b211020032802f404211a2012a7200c70210f2008200b427f857ca722022002200c6e220e200c6c6b210d024002400240200c20024d0d00200e41016a220e450d0c41002102200f210541002107410041ff017122064101470d010c020b41002106200f21094100210a410021050340200521072006210520092102024002400240024002400240024002400240200a41ff017122064101460d0020064102470d012005200f490d040c050b2002200c4f0d054101210a200241016a21090c010b2002200c4f0d01200241016a21094100210a0b20052106200741016a2105200e2007200d496a2207450d060c050b2005200f4f0d030b200541016a21064102210a2002210920052102200741016a2105200e2007200d496a2207450d040c030b4102211d0c100b4102211d0c0f0b4102211d0c0e0b0240200c20024d0d00200341f0046a41186a201020024105746a220241186a290000370300200341f0046a41106a200241106a290000370300200341f0046a41086a200241086a290000370300200320022900003703f004200341f0046a200710ad010c010b0b4131211d0c0c0b4133211d0c0b0b4138211d0c0a0b4105211d0c090b4105211d0c080b4105211d0c070b41eac4c10041331042000b41e484c300104f000b41cc84c300104f000b418c85c300104f000b41eac4c10041331042000b41eac4c10041331042000b41002106417f2105200f210741002102024002400240024002400340024002400240200241ff017122024101460d0020024102470d012006200f490d020c040b2007200c4f0d0441012102200741016a2107200541016a2205200d490d020c060b02402007200c4f0d00200741016a210741002102200541016a2205200d490d020c070b2006200f4f0d040b200641016a210641022102200541016a2205200d490d000b4102211d0c050b4102211d0c040b4102211d0c030b4102211d0c020b4102211d0c010b4102211d0b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240201d0e3a050a3637380b0c0d0e0f101112171318192e2f30311a1b292a2b2c222324141516252627281c1d1e1f2d20213233343500390102040607030809090b200c20024d0d704132211d0c720b200741016a2107200341f0046a41186a201020024105746a220241186a290000370300200341f0046a41106a200241106a290000370300200341f0046a41086a200241086a290000370300200320022900003703f004200341f0046a200e10ad012009210520062102200a41ff017122064101460d384133211d0c710b20064102470d6f4137211d0c700b2002200f490d3b0c3c0b2005200c4f0d394100211d0c6e0b200541016a21094100210a0c370b2002200f4f0d3b4136211d0c6c0b200241016a21064102210a200521092007200d490d330c340b2005200c4f0d384139211d0c6a0b4101210a200541016a21094101211d0c690b20022106200521022007200d490d380c390b410121064106211d0c670b410121094107211d0c660b4101210a4108211d0c650b4101210d4109211d0c640b4101210c410a211d0c630b4101210e410b211d0c620b4101210f20012802002202410b4b0d36410c211d0c610b024020020e0c003700000038393a3b3c003d000b410e211d0c600b2000200436020420002005360200200341e0076a24000f0b200a450d48411f211d0c5e0b200141086a2d00004102470d484120211d0c5d0b2001410c6a22012802001028200128020010010c480b200e450d38410f211d0c5b0b200141086a2d000022024102490d384110211d0c5a0b20024102470d544115211d0c590b200141306a280200450d374116211d0c580b2001412c6a28020010010c370b2006450d474126211d0c560b200141086a2d000022024105460d524127211d0c550b20024102470d464128211d0c540b2001410c6a22012802001028200128020010010c460b2007450d47412b211d0c520b200141086a10290c470b200d450d37411c211d0c500b20012d00044102470d37411d211d0c4f0b2001410c6a22012802001028200128020010010c370b2009450d3a4122211d0c4d0b200141086a2802004102470d3a4123211d0c4c0b200141106a280200450d3a4124211d0c4b0b2001410c6a28020010010c3a0b200c450d2c4118211d0c490b20012802044102490d2c4119211d0c480b2001410c6a280200450d2c411a211d0c470b200141086a28020010010c2c0b2001410c6a22012802001028200128020010010c390b200141106a280200450d404112211d0c440b2001410c6a28020010014113211d0c430b2001411c6a280200450d234114211d0c420b200141186a28020010010c230b200f450d37412d211d0c400b20012d00044102470d37412e211d0c3f0b2001410c6a280200450d37412f211d0c3e0b200141086a28020010010c370b41002105410121072011450d0e4103211d0c3c0b201a450d0e4104211d0c3b0b201010010c0e0b41fc84c3002002200c104e000b4138211d0c380b4130211d0c370b4102211d0c360b4101211d0c350b4135211d0c340b4136211d0c330b4102211d0c320b4102211d0c310b4102211d0c300b4130211d0c2f0b4102211d0c2e0b4105211d0c2d0b4105211d0c2c0b4105211d0c2b0b412c211d0c2a0b412a211d0c290b4125211d0c280b4121211d0c270b411e211d0c260b411b211d0c250b4117211d0c240b410d211d0c230b410e211d0c220b410e211d0c210b410e211d0c200b410e211d0c1f0b410e211d0c1e0b410e211d0c1d0b410e211d0c1c0b410e211d0c1b0b410e211d0c1a0b410e211d0c190b410e211d0c180b410e211d0c170b410e211d0c160b410e211d0c150b410e211d0c140b410e211d0c130b410e211d0c120b410e211d0c110b410e211d0c100b410e211d0c0f0b410e211d0c0e0b410e211d0c0d0b410e211d0c0c0b410e211d0c0b0b410e211d0c0a0b410e211d0c090b410e211d0c080b410e211d0c070b410e211d0c060b410e211d0c050b4111211d0c040b4113211d0c030b4129211d0c020b4131211d0c010b4134211d0c000b0bf710010a7f230041d0006b2203240002402001280200417e6a220441054b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e06000402030105000b200241096a2800002104200241056a2800002105200141086a280200210620022d0001210720022d0000210820012802042109200341cc006a41026a220a200241046a2d00003a0000200341106a41086a220b200241156a290000370300200341106a410d6a220c2002411a6a2900003700002003200241026a2f01003b014c20032002410d6a29000037031020080d07200341c8006a41026a200a2d00003a0000200341306a41086a200b290300370300200341306a410d6a200c290000370000200320032f014c3b01482003200329031037033041012108200741ff01714101470d07200341106a41026a200341c8006a41026a2d00003a0000200341236a200341386a290300370000200341286a2003413d6a2900003700002003200436001720032005360013200320032f01483b01102003200329033037001b02402006450d00200910010b4100210a41012106410121090c0c0b41002108200141086a28020021042001280204210a41efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b2207450d07410121062004450d04200a10010c040b200241096a2800002104200241056a2800002105200141086a280200210a20022d0001210720022d0000210820012802042106200341cc006a41026a2209200241046a2d00003a0000200341106a41086a220b200241156a290000370300200341106a410d6a220c2002411a6a2900003700002003200241026a2f01003b014c20032002410d6a29000037031020080d04200341c8006a41026a20092d00003a0000200341306a41086a200b290300370300200341306a410d6a200c290000370000200320032f014c3b01482003200329031037033041012108200741ff01714101470d04200341106a41026a200341c8006a41026a2d00003a0000200341236a200341386a290300370000200341286a2003413d6a2900003700002003200436001720032005360013200320032f01483b01102003200329033037001b0240200a450d00200610010b41002109410121064101210a0c0a0b410121064101210841efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b22070d02200341106a200141086a2903001088014184c4c100410a200328021022022003280218100302402003280214450d00200210010b410021074101210841012106410121094101210a0c0a0b4100210741c1efc100410041c1efc100410320022d000120022d00001b41ff017122024102461b20024103461b2202450d05412d21044101210841012106410121094101210a200221070c090b2001410c6a2802002108200141086a28020021092001280204210a41efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b2207450d0502402008450d00200841186c2104200a210203400240200241046a280200450d00200228020010010b0240200241106a280200450d002002410c6a28020010010b200241186a2102200441686a22040d000b0b41012108410021062009450d00200a10010b412821042001280200417e6a220241054b0d08024020020e0600100d090e0f000b200141086a280200450d0f200128020410010c0f0b412a210441002109410121084197efc10021070240200a450d00200610010b410121064101210a0c060b412a21044100210a410121084197efc100210702402006450d00200910010b41012106410121090c050b41d9c1c1004105200a2001410c6a28020010034101210802402004450d00200a10010b410021060c020b200341086a10f00141012108024020032802084101470d0041012106410121094101210a200328020c4101460d040b200341246a41013602002003411c6a410136020020034103360234200341dcc3c100360230200341e0c3c10036021820034102360214200341a08ac3003602102003200341306a360220200341106a41b08ac3001071000b02402008450d00200a200841186c6a2104200a210203402002280200200241086a2802002002410c6a280200200241146a2802001003200241186a22022004470d000b2008450d00200841186c2104200a210203400240200241046a280200450d00200228020010010b0240200241106a280200450d002002410c6a28020010010b200241186a2102200441686a22040d000b0b4101210602402009450d00200a10010b410021080b410121094101210a0b410021070b2001280200417e6a220241054b0d00024020020e06000802010304000b200a450d07200141086a280200450d07200128020410010c070b200110290c060b2009450d05200141086a280200450d05200128020410010c050b2006450d04200141086a280200450d04200128020410010c040b2008450d0302402001410c6a2802002208450d0020012802042102200841186c210803400240200241046a280200450d00200228020010010b0240200241106a280200450d002002410c6a28020010010b200241186a2102200841686a22080d000b0b200141086a280200450d03200141046a28020010010c030b200141086a280200450d02200128020410010c020b2008450d01200141086a280200450d01200128020410010c010b2006450d0002402001410c6a2802002208450d0020012802042102200841186c210803400240200241046a280200450d00200228020010010b0240200241106a280200450d002002410c6a28020010010b200241186a2102200841686a22080d000b0b200141086a280200450d00200141046a28020010010b2000200436020420002007360200200341d0006a24000f0b41888ac300104f000b9d0301077f230041306b22022400024002400240024002400240411010002203450d002002421037022420022003360220200241206a41c785c2004110102520022802202103024002400240024020022802242204200228022822056b41044f0d00200541046a22062005490d0520044101742207200620062007491b22074100480d052004450d01200710002208450d072008200320072004200420074b1b10f802210420031001200421030c020b200541046a21060c020b200710002203450d050b200721040b200320056a2001360000200241206a41086a220542003703002002420037032020032006200241206a1002200241086a2005290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103620022802202205450d0320002002290224370204200020053602002004450d060c050b200041003602082000420137020020040d040c050b411041011019000b1018000b41eac4c10041331042000b200741011019000b200310010b200241306a24000b960201097f230041106b220124002001109e0220012802002202410820021b2203200141086a280200410020021b220441286c6a21052001280204210620032107024002400340200520076b419f014d0d014101210820072000460d0220072000412010fa02450d02200741286a22092000460d0220092000412010fa02450d02200741d0006a22092000460d0220092000412010fa02450d02200741f8006a22092000460d02200741a0016a210720092000412010fa020d000c020b0b024020052007460d002003200441286c6a210903404101210820002007460d0220072000412010fa02450d022009200741286a2207470d000b0b410021080b02402002450d002006450d00200310010b200141106a240020080b82b901090b7f047e047f017e037f027e047f027e0f7f230041e0036b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280200417e6a220441084b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e09000502030106070408000b2001410c6a2802002105200141086a2802002106200141106a280200210720012802042108200241096a2800002104200241056a280000210920022d0001210a20022d00002101200341f0026a41026a220b200241046a2d00003a0000200341c8016a41086a220c200241156a290000370300200341c8016a410d6a220d2002411a6a2900003700002003200241026a2f01003b01f00220032002410d6a2900003703c80120010d0f20034198036a41026a200b2d00003a0000200341b8026a41086a200c290300370300200341b8026a410d6a200d290000370000200320032f01f0023b019803200320032903c8013703b802200a41ff01714101470d0f200341db016a200341b8026a41086a290300220e370000200341e0016a200341b8026a410d6a290000220f370000200341d8026a41026a20034198036a41026a2d000022013a0000200341f0026a41086a200e370300200341f0026a410d6a200f370000200320043600cf01200320093600cb01200320032f01980322023b01c801200320032903b802220e3700d301200320023b01d8022003200e3703f002200320013a00ca01410021010c100b200141386a2903002110200141306a2903002111200141286a2802002112200341a4016a41026a200141076a2d00003a000020034188016a41086a200141186a29020037030020034188016a410d6a2001411d6a290000370000200320012f00053b01a4012003200141106a29020037038801200141086a28020021092001410c6a280200210820012d0004210b200241096a2800002104200241056a280000210620022d0001210c20022d0000210a200341b8036a41026a220d200241046a2d00003a0000200341c8016a41086a2207200241156a290000370300200341c8016a410d6a22052002411a6a2900003700002003200241026a2f01003b01b80320032002410d6a2900003703c801200a0d0820034198036a41026a200d2d00003a0000200341a8016a41086a2007290300370300200341a8016a410d6a2005290000370000200320032f01b8033b019803200320032903c8013703a801200c41ff01714101470d08200341db016a200341a8016a41086a290300220e370000200341e0016a200341a8016a410d6a290000220f370000200341d8026a41026a20034198036a41026a2d000022023a0000200341b8036a41086a200e370300200341b8036a410d6a200f370000200320043600cf01200320063600cb01200320032f019803220a3b01c801200320032903a801220e3700d3012003200a3b01d8022003200e3703b803200320023a00ca01410021020c090b2001280204210d200241096a2800002104200241056a280000210620022d0001210820022d00002109200341f0026a41026a220a200241046a2d00003a0000200341c8016a41086a220b200241156a290000370300200341c8016a410d6a220c2002411a6a2900003700002003200241026a2f01003b01f00220032002410d6a2900003703c80120090d0920034198036a41026a200a2d00003a0000200341b8026a41086a200b290300370300200341b8026a410d6a200c290000370000200320032f01f0023b019803200320032903c8013703b802200841ff01714101470d09200341db016a200341b8026a41086a290300220e370000200341e0016a200341b8026a410d6a290000220f370000200341d8026a41026a20034198036a41026a2d000022023a0000200341f0026a41086a200e370300200341f0026a410d6a200f370000200320043600cf01200320063600cb01200320032f01980322093b01c801200320032903b802220e3700d301200320093b01d8022003200e3703f002200320023a00ca01410021020c0a0b20012802042108200241096a2800002104200241056a280000210620022d0001210a20022d00002109200341f0026a41026a220b200241046a2d00003a0000200341c8016a41086a220c200241156a290000370300200341c8016a410d6a220d2002411a6a2900003700002003200241026a2f01003b01f00220032002410d6a2900003703c80120090d0a20034198036a41026a200b2d00003a0000200341b8026a41086a200c290300370300200341b8026a410d6a200d290000370000200320032f01f0023b019803200320032903c8013703b802200a41ff01714101470d0a200341db016a200341b8026a41086a290300220e370000200341e0016a200341b8026a410d6a290000220f370000200341d8026a41026a20034198036a41026a2d000022023a0000200341f0026a41086a200e370300200341f0026a410d6a200f370000200320043600cf01200320063600cb01200320032f01980322093b01c801200320032903b802220e3700d301200320093b01d8022003200e3703f002200320023a00ca01410021020c0b0b4100210641efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b22090d042003200141086a2903003703b803200341c8016a41086a22024200370300200342003703c801419ac7c100411c200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110200341b8036a410810030c6b0b200141306a28020021122001412c6a280200211320012802042114200341a4016a41026a2001410b6a2d00003a000020034188016a41086a2001411c6a29020037030020034188016a410d6a200141216a290000370000200320012f00093b01a4012003200141146a29020037038801200141086a2d0000210b2001410c6a2802002109200141106a2802002108200241096a2800002104200241056a280000210620022d0001210c20022d0000210a200341b8036a41026a220d200241046a2d00003a0000200341c8016a41086a2207200241156a290000370300200341c8016a410d6a22052002411a6a2900003700002003200241026a2f01003b01b80320032002410d6a2900003703c801200a0d0c20034198036a41026a200d2d00003a0000200341a8016a41086a2007290300370300200341a8016a410d6a2005290000370000200320032f01b8033b019803200320032903c8013703a801200c41ff01714101470d0c200341db016a200341a8016a41086a290300220e370000200341e0016a200341a8016a410d6a290000220f370000200341d8026a41026a20034198036a41026a2d000022023a0000200341b8036a41086a200e370300200341b8036a410d6a200f370000200320043600cf01200320063600cb01200320032f019803220a3b01c801200320032903a801220e3700d3012003200a3b01d8022003200e3703b803200320023a00ca01410021020c0d0b4100210641efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b22090d02200320012802043602b803200341c8016a41086a22024200370300200342003703c80141c9c6c1004114200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110200341b8036a410410030c690b200341d4026a41026a2208200141076a2d00003a0000200341d8026a41086a220a200141186a290200370300200341d8026a410d6a220b2001411d6a290000370000200320012f00053b01d4022003200141106a2902003703d80241efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b22090d012001410c6a2802002104200141086a280200210620012d0004210220034188016a41026a20082d00003a0000200341b8026a41086a200a290300370300200341b8026a410d6a200b290000370000200320032f01d4023b018801200320032903d8023703b802200241ff01714101470d12200341c8016a200641067610ce0220032802d0012006413f7122024d0d17200341b4036a41026a220920032802c801220b20024105746a220241026a2d00003a000020034198036a41086a2208200241136a29000037030020034198036a410d6a220a200241186a290000370000200320022f00003b01b4032003200229000b370398032002280007210420022800032106024020032802cc01450d00200b10010b200341c8016a41136a2008290300220e370000200341c8016a41186a200a290000220f37000020034194036a41026a20092d000022023a0000200341b8036a41086a200e370300200341b8036a410d6a200f370000200320043600cf01200320063600cb01200320023a00ca01200320032f01b40322023b01c8012003200329039803220e3700d301200320023b0194032003200e3703b803410021020c180b4100210641efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b2209450d0b0b412821040c6b0b41012102412a21044197efc10021060b200341b4036a41026a220a200341d8026a41026a2d00003a0000200341b8026a41086a220c200341b8036a41086a290300370300200341b8026a41106a200341b8036a41106a290300370300200320032f01d8023b01b403200320032903b8033703b80220020d5f200341f0026a41136a200c290300370000200341f0026a41186a200341b8026a410d6a2202290000370000200320032f01b4033b01f002200320043600f702200320063600f302200320032903b8023700fb022003200a2d00003a00f20220034194036a41026a200341a4016a41026a2d00003a0000200341d8026a41086a20034188016a41086a290300370300200341d8026a410d6a220420034188016a410d6a290000370000200320032f01a4013b01940320032003290388013703d802200b41ff01714101470d09200341c8016a200941067610ce0220032802d0012009413f7122024d0d0f200341b4036a41026a220420032802c801220b20024105746a220241026a2d00003a000020034198036a41086a2206200241136a29000037030020034198036a410d6a220a200241186a290000370000200320022f00003b01b4032003200229000b370398032002280007210820022800032109024020032802cc01450d00200b10010b200341c8016a41136a2006290300220e370000200341c8016a41186a200a290000220f370000200341d4026a41026a20042d000022023a0000200341b8026a41086a200e370300200341b8026a410d6a200f370000200320083600cf01200320093600cb01200320023a00ca01200320032f01b40322023b01c8012003200329039803220e3700d301200320023b01d4022003200e3703b802410021020c100b410121024197efc1002106412a21040b200341c4016a41026a2209200341d8026a41026a2d00003a0000200341a8016a41086a2208200341f0026a41086a290300370300200341a8016a41106a200341f0026a41106a290300370300200320032f01d8023b01c401200320032903f0023703a80120020d5d200341cb036a2008290300370000200341d0036a200341b5016a290000370000200320032f01c4013b01b803200320043600bf03200320063600bb03200320032903a8013700c303200320092d00003a00ba03200341c8016a41086a22024200370300200342003703c80141f2c6c1004114200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110100e450d0941dceac10021060c640b410121024197efc1002106412a21040b200341c4016a41026a2209200341d8026a41026a2d00003a0000200341a8016a41086a220a200341f0026a41086a290300370300200341a8016a41106a200341f0026a41106a290300370300200320032f01d8023b01c401200320032903f0023703a80120020d5b200341cb036a200a290300370000200341d0036a200341b5016a290000370000200320032f01c4013b01b803200320043600bf03200320063600bb03200320032903a8013700c303200320092d00003a00ba03411610002202450d2f200342163702cc01200320023602c801200341c8016a4181c8c10041161025200341f0026a41086a220220032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2002280200210420032802f402210620032802f0022102200341c8016a41086a22094200370300200342003703c80120022004200341c8016a1002200341b8026a41086a2009290300370300200320032903c8013703b802200341b8026a4110100e210402402006450d00200210010b2004450d0941c3ebc10021060c620b410121014197efc1002109412a21040b200341c4016a41026a2202200341d8026a41026a2d00003a0000200341a8016a41086a220a200341f0026a41086a290300370300200341a8016a41106a200341f0026a41106a290300370300200320032f01d8023b01c401200320032903f0023703a801024020010d00200341cb036a200a290300370000200341d0036a200341b5016a290000370000200320032f01c4013b01b803200320043600bf03200320093600bb03200320032903a8013700c303200320022d00003a00ba03200341c8016a41086a22014200370300200342003703c80141f2c6c1004114200341c8016a1002200341b8026a41086a2001290300370300200320032903c8013703b802200341b8026a4110100e450d074186e8c1002109412e21040b2006450d630c5f0b410121024197efc1002106412a21040b200341b4036a41026a220a200341d8026a41026a2d00003a0000200341b8026a41086a220c200341b8036a41086a290300370300200341b8026a41106a200341b8036a41106a290300370300200320032f01d8023b01b403200320032903b8033703b80220020d57200341f0026a41136a200c290300370000200341f0026a41186a200341b8026a410d6a2202290000370000200320032f01b4033b01f002200320043600f702200320063600f302200320032903b8023700fb022003200a2d00003a00f20220034194036a41026a200341a4016a41026a2d00003a0000200341d8026a41086a20034188016a41086a290300370300200341d8026a410d6a220420034188016a410d6a290000370000200320032f01a4013b01940320032003290388013703d802200b41ff01714101470d02200341c8016a200941067610ce0220032802d0012009413f7122024d0d09200341b4036a41026a220420032802c801220b20024105746a220241026a2d00003a000020034198036a41086a2206200241136a29000037030020034198036a410d6a220a200241186a290000370000200320022f00003b01b4032003200229000b370398032002280007210820022800032109024020032802cc01450d00200b10010b200341c8016a41136a2006290300220e370000200341c8016a41186a200a290000220f370000200341d4026a41026a20042d000022023a0000200341b8026a41086a200e370300200341b8026a410d6a200f370000200320083600cf01200320093600cb01200320023a00ca01200320032f01b40322023b01c8012003200329039803220e3700d301200320023b01d4022003200e3703b802410021020c0a0b2003200141086a2903003703b803200341c8016a41086a22024200370300200342003703c8014186c7c1004114200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110200341b8036a410810030c5b0b200341c8016a41026a20034194036a41026a2d000022063a0000200341c8016a41136a200341d8026a41086a290300220e370000200341c8016a41186a2004290000220f370000200341d4026a41026a20063a0000200341b8026a41086a200e3703002002200f370000200320083600cf01200320093600cb01200320032f01940322023b01c801200320032903d802220e3700d301200320023b01d4022003200e3703b802410021020c060b200341c8016a41026a20034194036a41026a2d000022063a0000200341c8016a41136a200341d8026a41086a290300220e370000200341c8016a41186a2004290000220f370000200341d4026a41026a20063a0000200341b8026a41086a200e3703002002200f370000200320083600cf01200320093600cb01200320032f01940322023b01c801200320032903d802220e3700d301200320023b01d4022003200e3703b802410021020c070b411410002202450d2c200342143702cc01200320023602c801200341c8016a41c8e8c10041141025200341f0026a41086a220220032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2002280200210420032802f402210620032802f0022102200341c8016a41086a22094200370300200342003703c80120022004200341c8016a1002200341b8026a41086a2009290300370300200320032903c8013703b802200341b8026a4110100e210402402006450d00200210010b2004450d0a200341c8016a41086a22024200370300200342003703c80141b6c7c100410e200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d12200342103702f4022003200341b8026a3602f002200341c8016a200341f0026a103620032802c8012202450d35200341d0016a280200210420032802cc0121060c130b200341c8016a41086a22014200370300200342003703c80141bfc8c1004111200341c8016a1002200341b8026a41086a2001290300370300200320032903c8013703b802410021010240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d2520032802c80121010b20072001470d08411410002201450d31200342143702cc01200320013602c801200341c8016a41c8e8c10041141025200341f0026a41086a220120032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2001280200210220032802f402210420032802f0022101200341c8016a41086a22094200370300200342003703c80120012002200341c8016a1002200341b8026a41086a2009290300370300200320032903c8013703b802200341b8026a4110100e210202402004450d00200110010b2002450d130c530b200341c8016a41086a22044200370300200342003703c80141a9c8c1004116200341c8016a1002200341b8026a41086a22062004290300370300200320032903c8013703b802410021024100210d0240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d2520032802c801210d0b20044200370300200342003703c8014197c8c1004112200341c8016a100220062004290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d09200342103702f4022003200341b8026a3602f002200341c8016a200341f0026a103620032802c8012202450d2d200341d0016a280200210420032802cc0121060c0a0b200341c8016a41026a20034188016a41026a2d000022023a0000200341db016a200341b8026a41086a290300220e370000200341e0016a200341b8026a410d6a290000220f37000020034194036a41026a20023a0000200341b8036a41086a200e370300200341b8036a410d6a200f370000200320043600cf01200320063600cb01200320032f01880122023b01c801200320032903b802220e3700d301200320023b0194032003200e3703b803410021020c050b024020032802cc01450d0020032802c80110010b4101210241152108418987c20021090b200341c4016a41026a2204200341d4026a41026a2d00003a0000200341a8016a41086a2206200341b8026a41086a220a290300370300200341a8016a41106a200341b8026a41106a290300370300200320032f01d4023b01c401200320032903b8023703a80102402002450d00200821042009210620012802004102460d570c580b200341cb036a2006290300370000200341d0036a200341b5016a290000370000200320032f01c4013b01b803200320083600bf03200320093600bb03200320032903a8013700c303200320042d00003a00ba03200341c8016a41086a22024200370300200342003703c8014111210441bfc8c1004111200341c8016a1002200a2002290300370300200320032903c8013703b802410021020240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d2020032802c80121020b4195ecc100210620122002470d4e200341c8016a41086a22024200370300200342003703c80141f2c6c1004114200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d0a2003200341b8026a3602a801200341103602ac01200342003703c80120034100200341b8026a4110200341c8016a41084100100422022002417f461b22024108200241084922041b22023602b00120040d26200341003602c801200341b0016a4100200341b8026a4110200341c8016a41042002100422042004417f461b22044104200441044922041b20026a36020020040d26200341c8016a200341a8016a103620032802c8012215450d2620032902cc012116200341c8016a41086a22144200370300200342003703c80141c4c7c1004118200341c8016a1002200341b8026a41086a22132014290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d10200342103702ac012003200341b8026a3602a80120034180016a200341a8016a1035200328028001450d1e200328028401220bad220e421c88a70d3a200e420486a72202417f4c0d3a2002450d142002100022080d15200241081019000b024020032802cc01450d0020032802c80110010b41012102418987c2002109411521080b200341c4016a41026a2204200341d4026a41026a2d00003a0000200341a8016a41086a2206200341b8026a41086a220a290300370300200341a8016a41106a200341b8026a41106a290300370300200320032f01d4023b01c401200320032903b8023703a80102402002450d00200821042009210620012802004102460d550c560b200341cb036a2006290300370000200341d0036a200341b5016a290000370000200320032f01c4013b01b803200320083600bf03200320093600bb03200320032903a8013700c303200320042d00003a00ba03200341c8016a41086a22024200370300200342003703c80141f2c6c1004114200341c8016a1002200a2002290300370300200320032903c8013703b8020240200341b8026a4110100e450d004181e9c10021064126210420012802004102460d550c560b411410002202450d2c200342143702cc01200320023602c801200341c8016a41c8e8c10041141025200341b8026a41086a220220032802d001360200200320032903c8013703b802200341f0026a200341b8026a101e2002280200210620032802bc02210920032802b8022104200341c8016a41086a22084200370300200342003703c80120042006200341c8016a100220022008290300370300200320032903c8013703b802410021020240200341b8026a41104188f0c100410041001004417f460d00200341003602c80141012102200341b8026a4110200341c8016a41044100100441016a41044d0d240b02402009450d00200410010b2002450d09411410002202450d31200342143702cc01200320023602c801200341c8016a41c8e8c10041141025200341b8026a41086a220220032802d001360200200320032903c8013703b802200341b8036a200341b8026a101e2002280200210620032802bc02210920032802b8022104200341c8016a41086a22084200370300200342003703c80120042006200341c8016a100220022008290300370300200320032903c8013703b80241002102200341b8026a41104188f0c100410041001004417f460d15200341003602c80141012102200341b8026a4110200341c8016a41044100100441016a41044d0d2620032802c80121082009450d4a0c490b024020032802cc01450d0020032802c80110010b4101210241152104418987c20021060b200341c4016a41026a220920034194036a41026a2d00003a0000200341a8016a41086a2208200341b8036a41086a290300370300200341a8016a41106a200341b8036a41106a290300370300200320032f0194033b01c401200320032903b8033703a80120020d4a20034183036a2008290300370000200341f0026a41186a200341b5016a290000370000200320032f01c4013b01f002200320043600f702200320063600f302200320032903a8013700fb02200320092d00003a00f202200341c8016a109e024100210420032802cc01410020032802c80122021b21152002410820021b21050240200341c8016a41086a280200410020021b41286c2206450d000340200341c8016a41206a200520046a220241206a290300370300200341c8016a41186a200241186a290300370300200341c8016a41106a200241106a290300370300200341c8016a41086a200241086a290300370300200320022903003703c801200341c8016a200341f0026a412010fa020d062006200441286a2204470d000b0b4100210c410821072015450d05200510014100210d0c0f0b41b4e8c10021094114210420060d4f0c530b41faeac10021060c060b0b2006410020021b21072004410020021b21092002410120021b210202402008200d470d0020082009460d380b41e1ebc100210641162104200820094f0d38200341e0016a4200370300200341d8016a4200370300200341d0016a4200370300200342003703c801200220084105746a220a200341c8016a460d37200a200341c8016a412010fa020d380c370b200341b8036a41206a2209200341c8016a41206a290300370300200341b8036a41186a2208200341c8016a41186a290300370300200341b8036a41106a220a200341c8016a41106a290300370300200341b8036a41086a220b200341c8016a41086a290300370300200320032903c8013703b803412810002207450d28200720032903b803370300200741206a2009290300370300200741186a2008290300370300200741106a200a290300370300200741086a200b290300370300200641586a2004460d08200241286a2102200620046b41b07f6a21064101210c4101210d0340200341c8016a41206a2209200241206a290300370300200341c8016a41186a2208200241186a290300370300200341c8016a41106a220a200241106a290300370300200341c8016a41086a220b200241086a290300370300200320022903003703c80102400240024002400240200341c8016a200341f0026a412010fa02450d00200341b8036a41206a22042009290300370300200341b8036a41186a22122008290300370300200341b8036a41106a2214200a290300370300200341b8036a41086a2213200b290300370300200320032903c8013703b8032009200429030037030020082012290300370300200a2014290300370300200b2013290300370300200320032903b8033703c801200d200c470d03200c41016a2204200c490d3f200c4101742212200420042012491b2212ad42287e220e422088a70d3f200ea722044100480d3f200c450d01200410002214450d21201420072004200c41286c220c200c20044b1b10f802210420071001200421070c020b20060d030c0e0b200410002207450d1f0b2012210c0b2007200d41286c6a220420032903c801370300200441206a2009290300370300200441186a2008290300370300200441106a200a290300370300200441086a200b290300370300200d41016a210d2006450d0b0b200241286a2102200641586a21060c000b0b4100210d0c090b41a6ecc1002106412d210420012802004102460d4b0c4c0b41a7e9c10021060b4118210420012802004102460d490c4a0b410021020b2006410020021b21082002410120021b2109024002400240200d2004410020021b22024f0d002009200d4105746a2204200341b8036a460d022004200341b8036a412010fa02450d0241aaebc10021064119210420080d010c420b4192ebc1002106411821042008450d410b2009100120012802004102460d480c490b200320023602d001200320083602cc01200320093602c801200341b8036a200d200341c8016a10ef024200210e200341c8016a41086a22024200370300200342003703c80141dce8c1004112200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b80241002106200341b8026a41104188f0c100410041001004417f460d09200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042202417f460d252002410f4d0d25200341d0016a290300210f20032903c801210e0c0a0b4200210e200341c8016a41086a22014200370300200342003703c80141dce8c1004112200341c8016a1002200341b8026a41086a2001290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d0a200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042201417f460d252001410f4d0d25200341d0016a290300210f20032903c801210e0c0b0b410021084100211741002118410021194100210a0c050b4101210c4101210d0b2015450d00200510010b2003200d3602d0012003200c3602cc01200320073602c801200341c8016a10a1020240200c450d00200710010b410021060c3a0b410821080b02400240200b450d00200341a8016a41086a220c280200210420032802ac01210d20032802a801210741002106200b2102410021090340200342003703d001200342003703c801200c41002007200d200341c8016a411020041004220a200a417f461b220a4110200a411049220a1b20046a2204360200200a0d0a200341c8016a41086a290300210e20032903c801210f024020092002470d00200241016a220a2002490d3020024101742205200a200a2005491b2205ad420486221a422088a70d30201aa7220a4100480d30024002402002450d00200a10002212450d1320122008200a200241047422022002200a4b1b10f802210220081001200221080c010b200a10002208450d120b200521020b200820066a220a200e370308200a200f370300200641106a2106200941016a2209200b490d000c020b0b41002102410021090b2008450d082008211720082118200821192008210a0b20144200370300200342003703c80141b6c7c100410e200341c8016a100220132014290300370300200320032903c8013703b80202400240200341b8026a41104188f0c100410041001004417f460d00200342103702ac012003200341b8026a3602a801200341c8016a200341a8016a103620032802c8012204450d1d200341d0016a280200210620032802cc01210c0c010b410021040b4200210e200341c8016a41086a220b4200370300200342003703c80141aeeec100411c200341c8016a1002200341b8026a41086a200b290300370300200320032903c8013703b80202400240200341b8026a41104188f0c100410041001004417f460d00200342003703d001200342003703c801200341b8026a4110200341c8016a411041001004220b417f460d16200b410f4d0d16200341d0016a290300210e20032903c801210f0c010b4201210f0b4200211a200341f0006a200f200e2006410020041b2214ad420010fc02411410002206450d18200341f0006a41086a290300210e2003290370211b200342143702cc01200320063602c801200341c8016a41eeefc10041141025200341b8026a41086a220620032802d001360200200320032903c8013703b802200341f0026a200341b8026a101e2006280200210d20032802bc02210720032802b802210b200341c8016a41086a22054200370300200342003703c801200b200d200341c8016a100220062005290300370300200320032903c8013703b8020240200341b8026a41104188f0c100410041001004417f460d00200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042206417f460d162006410f4d0d16200341d0016a290300210f20032903c801211a410121062007450d230c220b4200210f4101210620070d210c220b20090d330c340b4200210f0b200341b8036a200e200f10e1020c390b4200210f0b2003200341b8036a200e200f10d202024020032802002209450d002003280204210420060d390c3d0b200341c8016a41086a22014200370300200342003703c80141b6c7c100410e200341c8016a1002200341b8026a41086a2001290300370300200320032903c8013703b80202400240200341b8026a41104188f0c100410041001004417f460d00200342103702f4022003200341b8026a3602f002200341c8016a200341f0026a103620032802c8012202450d1c200341d0016a280200210920032802cc01210a0c010b410021020b200341c8016a41186a220b200341b8036a41186a290300370300200341c8016a41106a200341b8036a41106a2903003703002001200341b8036a41086a290300370300200320032903b8033703c8012002410120021b21040240024002402009410020021b2201200a410020021b2214470d00200141016a22022001490d2920014101742209200220022009491b2214ad420586220e422088a70d29200ea722024100480d292001450d01200210002212450d1e20122004200220014105742209200920024b1b10f8021a200410010c020b200421120c010b200210002212450d1c0b2012200141057422046a220220032903c801370000200241186a200b290300370000200241106a200341c8016a41106a290300370000200241086a200341c8016a41086a2202290300370000200341003602d001200342013703c801200141016a2201200341c8016a101b024002402001450d00200441206a210c4100200228020022026b210a20032802c801210b20032802cc0121092012210d0340200d210102402009200a6a411f4b0d00200241206a22042002490d2a2009410174220d20042004200d491b22044100480d2a20041000210d024002402009450d00200d450d13200d200b20042009200920044b1b10f8021a200b10010c010b200d450d120b200d210b200421090b200141206a210d200b20026a22042001290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a290000370000200a41606a210a200241206a2102200c41606a220c0d000b200341d0016a2002360200200320093602cc012003200b3602c8010c010b2002280200210220032802cc01210920032802c801210b0b200341c8016a41086a22014200370300200342003703c80141b6c7c100410e200341c8016a1002200341b8026a41086a2001290300370300200320032903c8013703b802200341b8026a4110200b2002100302402009450d00200b10010b2014450d3320121001411421014114100022020d340c350b41e89fc300104f000b2002450d00200810010b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411641011019000b200a41081019000b200441081019000b41eac4c10041331042000b41eac4c10041331042000b411441011019000b41eac4c10041331042000b200441011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411441011019000b411441011019000b411441011019000b41eac4c10041331042000b412841081019000b41eac4c10041331042000b411441011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200241011019000b200b10010b20024100200a1b210d200c410020041b21072004200620041b210502400240024002400240024002400240201a201b54200f200e54200f200e511b450d0041d3ecc1002106412e210420070d010c020b200341c8016a41086a22024200370300200342003703c80141eec7c1004113200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802024002400240024002400240200341b8026a41104188f0c100410041001004417f460d00200342103702ac012003200341b8026a3602a801200341c8016a200341a8016a103e20032802c8012212450d0b200341c8016a41086a280200221c450d0a20032802cc01211d41e8edc10021064123210420112012290300562010201241086a290300220f562010200f511b450d0520094100200a1b211e20194108200a1b211920184108200a1b211f20174108200a1b2118200341c8016a109e0220032802cc01410020032802c80122021b21132002410820021b220c200341c8016a41086a280200410020021b221741286c6a210b200c2102410021060340200b20026b419f014d0d022002200341b8036a460d0320062002200341b8036a412010fa0222094100476a21062009450d03200241286a2209200341b8036a460d0320062009200341b8036a412010fa0222094100476a21062009450d03200241d0006a2209200341b8036a460d0320062009200341b8036a412010fa0222094100476a21062009450d03200241f8006a2209200341b8036a460d03200241a0016a210220062009200341b8036a412010fa0222094100476a210620090d000c030b0b4181edc10021064131210420070d050c060b200b2002460d01200c201741286c6a210b0340200341b8036a2002460d0120062002200341b8036a412010fa0222094100476a21062009450d01200b200241286a2202470d000c020b0b20062016422088a74f0d010b02402013450d00200c10010b200341c8016a200341b8036a10eb02418beec100210620032802c8014101470d01200341d0016a280200211320032802cc012117200341e8006a20192019201e4104746a102e200328026c2003280268220a6b41047622022014201420024b1b2214450d04200521024100210642002120420021210340411410002204450d09200342143702cc01200320043602c801200341c8016a41c8e8c10041141025200341b8026a41086a2209200341c8016a41086a2204280200360200200320032903c8013703b8022002200341b8026a101e2009280200210b20032802bc02210c20032802b802210820044200370300200342003703c8012008200b200341c8016a100220092004290300370300200320032903c8013703b802410021090240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d0c20032802c801210b410121090b0240200c450d00200810010b200641016a210602402009450d00200b2017490d00200341c8016a200210f0024200210f4200211a0240200428020020134d0d00200a41086a290300420020032802c80120136a2d000022041b211a200a290300420020041b210f0b024020032802cc01450d0020032802c80110010b201a20217c200f20207c2220200f54ad7c21210b200241206a2102200a41106a210a20062014490d000c060b0b41b2edc1002106413621042013450d00200c10010b0240201d450d00201210010b2007450d010b200510010b0240200d450d0020084108200a1b10010b2016a7450d190c090b42002120420021210b2012201c41306c6a210620122102024002400240024002400240024002400240024002400240024002400340200620026b41bf014d0d01200241106a2204200341b8036a460d022004200341b8036a412010fa02450d02200241c0006a2204200341b8036a460d022004200341b8036a412010fa02450d02200241f0006a2204200341b8036a460d022004200341b8036a412010fa02450d02200241a0016a2204200341b8036a460d02200241c0016a21022004200341b8036a412010fa020d000c020b0b024020022006460d000340200241106a2202200341b8036a460d022002200341b8036a412010fa02450d02200241206a22022006470d000b0b20112020852010202185844200520d01200341b8036a41086a290300210e200341b8036a41106a290300210f200341b8036a41186a290300211a20032903b803211b2012201037030820122011370300200341c8016a41186a201a370300200341c8016a41106a200f370300200341c8016a41086a200e3703002012201b370310201241186a200e370300201241206a200f370300201241286a201a3703002003201b3703c801201c41144b0d02201c41014d0d03201c417f6a210b0340201c200b2202417f6a220b490d0b0240201c200b6b220a4102490d002012200241306c6a22042903002012200b41306c6a220929030022105a200441086a2202290300220f200941086a2206290300220e5a200f200e511b0d00200341c8016a41186a2217200941286a2208290300370300200341c8016a41106a2218200941206a220c290300370300200341c8016a41086a2219200941186a2214290300370300200320092903103703c8012009200429030037030020062002290300370300200941106a200441106a2903003703002014200441186a290300370300200c200441206a2903003703002008200441286a290300370300410121130240200a4103490d00410321064102210c410121130340200c2208200a4f0d102009200841306c6a220229030020105a200241086a220c290300220f200e5a200f200e511b0d012008417f6a2204200a4f0d0f2009200441306c6a22042002290300370300200441286a200241286a290300370300200441206a200241206a290300370300200441186a200241186a290300370300200441106a200241106a290300370300200441086a200c29030037030002402006200a4f0d002006210c200641016a220420064921142004210620082113200221042014450d010c020b0b20082113200221040b200420103703002004200e3703082009201341306c6a220241286a2017290300370300200241206a2018290300370300200241186a2019290300370300200220032903c8013703100b200b0d000c040b0b200341386a200341f0026a201b200e10ae014116210441caeec1002106201d450d120c110b200341d0006a200341f0026a201b200e10ae01410f210441e0eec1002106201d0d100c110b201c4101762222ad42307e220e422088a70d0d200ea72202417f4c0d0d024002402002450d00200210002223450d082023210c0c010b410821234108210c0b201241506a2124201241f07e6a2125410421184100212641002127201c21280340202821144100212841012106024002400240024002400240024002400240024002402014417f6a2209450d0002400240024002402012200941306c6a22022903002012201441306c220b6a220441a07f6a290300220f54200241086a2903002210200441a87f6a290300220e542010200e511b450d002025200b6a2102034020094101460d02200f20022903002211542104200e200241086a2903002210512106200e2010542108200241506a21022009417f6a21092011210f2010210e2004200820061b0d000c030b0b2014417e6a210a2025200b6a210241002128410021040340200a2004460d0c200f200229030022115a2106200e200241086a2903002210512109200e20105a2108200241506a2102200441016a21042011210f2010210e2006200820091b0d000b200441016a2106201420046b417f6a22090d020c0a0b410021090b20142009490d042014201c4b0d070240201420096b22064101762208450d002024200b6a21022012200941306c6a21040340200341c8016a41286a220a200441286a220b290300370300200341c8016a41206a2213200441206a2217290300370300200341c8016a41186a2219200441186a221e290300370300200341c8016a41106a2229200441106a2228290300370300200341c8016a41086a222a200441086a222b290300370300200320042903003703c801200241086a222c290300210e200241106a222d290300210f200241186a222e2903002110200241206a222f29030021112002290300211a200b200241286a223029030037030020172011370300201e20103703002028200f370300202b200e3703002004201a3703002030200a290300370300202f2013290300370300202e2019290300370300202d2029290300370300202c202a290300370300200220032903c801370300200441306a2104200241506a21022008417f6a22080d000b0b2009450d080b0240200641094d0d002009212820272026470d0b0c0a0b2014201c4b0d04034020142009417f6a2228490d060240201420286b22064102490d002012200941306c6a22042903002012202841306c6a220829030022105a200441086a2202290300220f200841086a2209290300220e5a200f200e511b0d00200341c8016a41186a2219200841286a220a290300370300200341c8016a41106a221e200841206a220b290300370300200341c8016a41086a2229200841186a2213290300370300200320082903103703c8012008200429030037030020092002290300370300200841106a200441106a2903003703002013200441186a290300370300200b200441206a290300370300200a200441286a29030037030041012117024020064103490d00410321094102210b410121170340200b220a20064f0d052008200a41306c6a220229030020105a200241086a220b290300220f200e5a200f200e511b0d01200a417f6a220420064f0d062008200441306c6a22042002290300370300200441286a200241286a290300370300200441206a200241206a290300370300200441186a200241186a290300370300200441106a200241106a290300370300200441086a200b2903003703000240200920064f0d002009210b200941016a2204200949211320042109200a2117200221042013450d010c020b0b200a2117200221040b200420103703002004200e3703082008201741306c6a220241286a2019290300370300200241206a201e290300370300200241186a2029290300370300200220032903c8013703100b2028450d01202821092006410a490d000b0b20272026470d090c080b41d08ac300200a2006104e000b41e08ac30020042006104e000b20092014107a000b20142009417f6a22284f0d010b20282014107a000b2014201c1076000b2009212820272026460d010c020b2014210620272026470d010b202641016a22022026490d1720264101742204200220022004491b2204ad420386220e422088a70d17200ea722024100480d17024002402026450d00200210002209450d0920092018200220264103742208200820024b1b10f802210220181001200221180c010b200210002218450d080b200421260b201820274103746a22022006360204200220283602000240202741016a22274102490d00024003400240024002400240201820272213417f6a22274103746a2202280200450d00201820134103746a220841746a2802002209200228020422044d0d00201341024d0d0520182013417d6a22024103746a2802042206200420096a4d0d01201341034d0d05200841646a280200200620096a4d0d010c050b20134103490d012002280204210420182013417d6a22024103746a28020421060b20062004490d010b2013417e6a21020b2013200241016a222a4d0d05201320024d0d06201820024103746a2219280204222b20192802006a22022018202a4103746a221e2802002229490d072002201c4b0d08201941046a212c2012202941306c6a2214201e280204221741306c22046a2109200241306c210602400240024002400240200220296b220a20176b220220174f0d0020232009200241306c220410f8021a200c20046a210820174101480d0120024101480d01202420066a21062009210203402006200241506a2209200841506a220a200a290300200929030054200841586a290300220e200241586a290300220f54200e200f511b220b1b2204290300370300200641286a200441286a290300370300200641206a200441206a290300370300200641186a200441186a290300370300200641106a200441106a290300370300200641086a200441086a2903003703002008200a200b1b2108201420092002200b1b22024f0d04200641506a2106200c2104200c2008490d000c050b0b20232014200410f8021a200c20046a210820174101480d01200a20174c0d01201220066a210b200c21042014210203402002200920042009290300200429030054200941086a290300220e200441086a290300220f54200e200f511b220a1b2206290300370300200241286a200641286a290300370300200241206a200641206a290300370300200241186a200641186a290300370300200241106a200641106a290300370300200241086a200641086a2903003703002004200441306a200a1b2104200241306a2102200941306a2009200a1b2209200b4f0d04200820044b0d000c040b0b200921020c010b201421020b200c21040b20022004200820046b220620064130706b10f8021a202c202b20176a36020020192029360200201e201e41086a2013202a417f736a41037410f9021a202741014b0d000c020b0b201321270b20280d000b02402026450d00201810010b2022450d00202310010b2003201c3602d0012003201d3602cc01200320123602c801200341c8016a10a2020240201d450d00201210010b02402007450d00200510010b0240200d450d00201f10010b410021062016a7450d25201510010c250b41c08ac300202a2013104e000b41c08ac30020022013104e000b20292002107a000b2002201c1076000b200241041019000b200241081019000b200b201c107a000b41e08ac3002004200a104e000b41d08ac3002008200a104e000b41888bc30041004100104e000b41eac4c10041331042000b411441011019000b102c000b41eac4c10041331042000b201210010b02402007450d00200510010b0240200d450d00201810010b2016a7450d100b2015100120012802004102460d170c180b4200210e200341c8016a41086a22044200370300200342003703c80141d0c8c1004115200341c8016a1002200341b8026a41086a2004290300370300200320032903c8013703b80202400240200341b8026a41104188f0c100410041001004417f460d00200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042204417f460d062004410f4d0d06200341d0016a290300210e20032903c801210f0c010b4209210f0b200341306a200341b8036a200f200e10d2022003280230450d0141f7ebc1002106411e21040b2007450d0d2002100120012802004102460d150c160b200341c8016a41086a22044200370300200342003703c80141bfc8c1004111200341c8016a1002200341b8026a41086a2004290300370300200320032903c8013703b802410021040240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d0420032802c80121040b411610002206450d04200342163702cc01200320063602c801200341c8016a4181c8c10041161025200341f0026a41086a220620032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2006280200210b20032802f402210c20032802f002210a410410002206450d0520062004360000410810002204450d06200420062800003600002006100120042008360004200341c8016a41086a22064200370300200342003703c801200a200b200341c8016a1002200341b8026a41086a2006290300370300200320032903c8013703b802200341b8026a4110200441081003200410010240200c450d00200a10010b0240024002400240024020082009470d00200341c8016a41186a2204200341b8036a41186a290300370300200341c8016a41106a2206200341b8036a41106a290300370300200341c8016a41086a2209200341b8036a41086a290300370300200320032903b8033703c80120082007470d01200841016a220a2008490d052008410174220b200a200a200b491b2207ad420586220e422088a70d05200ea7220a4100480d052008450d02200a10002205450d0d20052002200a2008410574220b200b200a4b1b10f8021a200210010c030b200341c8016a41186a2206200341b8036a41186a290300370300200341c8016a41106a220a200341b8036a41106a290300370300200341c8016a41086a220b200341b8036a41086a290300370300200320032903b8033703c801200920084d0d0b200220084105746a220420032903c801370000200441186a2006290300370000200441106a200a290300370000200441086a200b290300370000200221050c030b200221050c010b200a10002205450d0a0b200520084105746a220220032903c801370000200241186a2004290300370000200241106a2006290300370000200241086a2009290300370000200841016a21090b200341003602d001200342013703c8012009200341c8016a101b024002402009450d002009410574210b4100200341c8016a41086a28020022046b210820032802c801210a20032802cc0121092005210c0340200c21020240200920086a411f4b0d00200441206a22062004490d042009410174220c20062006200c491b22064100480d0420061000210c024002402009450d00200c450d07200c200a20062009200920064b1b10f8021a200a10010c010b200c450d060b200c210a200621090b200241206a210c200a20046a22062002290000370000200641186a200241186a290000370000200641106a200241106a290000370000200641086a200241086a290000370000200841606a2108200441206a2104200b41606a220b0d000b200341d0016a2004360200200320093602cc012003200a3602c8010c010b200341d0016a280200210420032802cc01210920032802c801210a0b200341c8016a41086a22024200370300200342003703c8014197c8c1004112200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110200a2004100302402009450d00200a10010b02402007450d00200510010b2003200d41016a3602f002200341c8016a41086a22024200370300200342003703c80141a9c8c1004116200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a4110200341f0026a410410030c0b0b1018000b200641011019000b41eac4c10041331042000b41eac4c10041331042000b411641011019000b410441011019000b410841011019000b41b08bc30020082009104e000b200a41011019000b200410010b02400240024002400240024002402002450d00200341c8016a41086a22024200370300200342003703c80141bfc8c1004111200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802410021020240200341b8026a41104188f0c100410041001004417f460d00200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d0520032802c80121020b20122002470d01200341c8016a41086a22024200370300200342003703c801419feac100411b200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d02200341003602c801200341b8026a4110200341c8016a41044100100441016a41044d0d052008201220032802c8016b4f0d030c060b41f3e9c1002106412c210420012802004102460d0f0c100b41bfe9c10021064116210420012802004102460d0e0c0f0b2008201241016b490d030b41d5e9c10021060c0b0b41eac4c10041331042000b41eac4c10041331042000b200341c8016a41086a22024200370300200342003703c80141b6c7c100410e200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b8020240024002400240024002400240024002400240200341b8026a41104188f0c100410041001004417f460d00200342103702ac012003200341b8026a3602a801200341c8016a200341a8016a103620032802c8012202450d02200341d0016a280200210a20032802cc0121040c010b410021020b2004410020021b210b2002410120021b210941caeac100210641122104024002402014200a410020021b220c4f0d000240200920144105746a2202200341f0026a460d002002200341f0026a412010fa020d010b41baeac1002106411021042013200c4f0d00200920134105746a2202200341b8036a460d012002200341b8036a412010fa02450d010b200b450d0a2009100120012802004102460d120c130b20034198036a200341b8036a10f00220032802a00321022003280298032106200341c8016a41086a22044200370300200342003703c8014197c8c1004112200341c8016a1002200341b8026a41086a2004290300370300200320032903c8013703b8024100211202400240200341b8026a41104188f0c100410041001004417f460d00200342103702ac012003200341b8026a3602a801200341c8016a200341a8016a103620032802c8012215450d03200341d0016a280200210420032802cc0121180c010b410021150b2015410120151b211702402004410020151b22042002200220044b1b220a450d0041002104200341e0016a210d200341d8016a2107200341d0016a21052017210203400240200620046a2d0000450d00200d42003703002007420037030020054200370300200342003703c801200341c8016a2002460d002002200341c8016a412010fa02450d00200341c8016a200210eb024101211220032802c8014101470d0020032802cc0120084d0d020b200241206a2102200441016a2204200a490d000b410021120b02402015450d002018450d00201710010b0240200328029c03450d00200610010b2003200c3602d0012003200b3602cc01200320093602c801200341f0026a200341b8036a20121b2014201320121b200341c8016a10ef024200210e200341c8016a41086a22024200370300200342003703c80141dce8c1004112200341c8016a1002200341b8026a41086a2002290300370300200320032903c8013703b802200341b8026a41104188f0c1004100410010042102024002400240024002402012450d002002417f460d01200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042202417f460d072002410f4d0d07200341d0016a290300210e20032903c801210f0c020b2002417f460d02200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042202417f460d072002410f4d0d07200341d0016a290300211120032903c801210e0c030b4200210f4200210e0b200341086a200341f0026a200f200e10d402200341d5016a200341f8026a290300370000200341dd016a20034180036a290300370000200341e5016a20034188036a290300370000200341013a00cc01200341053a00c801200320032903f0023700cd01200341c8016a10b4010c0a0b420021110b200341206a200341f0026a10b001024002402003290320200341286a29030084500d00411810002202450d07200342183702cc01200320023602c801200341c8016a4193f1c10041181025200341b8026a41086a220220032802d001360200200320032903c8013703b802200341b8036a200341b8026a101e2002280200210620032802bc02210920032802b80221044200210f200341c8016a41086a22084200370300200342003703c80120042006200341c8016a100220022008290300370300200320032903c8013703b802200341b8026a41104188f0c100410041001004417f460d01200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042202417f460d062002410f4d0d06200341d0016a290300211020032903c801210f2009450d090c080b41fb84c20021064122210420012802004102460d120c130b4200211020090d060c070b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b411841011019000b200410010b0240411410002202450d00200342143702cc01200320023602c801200341c8016a41eeefc10041141025200341b8026a41086a220220032802d001360200200320032903c8013703b802200341f0026a200341b8026a101e2002280200210620032802bc02210920032802b80221044200211a200341c8016a41086a22084200370300200342003703c80120042006200341c8016a100220022008290300370300200320032903c8013703b802024002400240200341b8026a41104188f0c100410041001004417f460d00200342003703d001200342003703c801200341b8026a4110200341c8016a4110410010042202417f460d022002410f4d0d02200341d0016a290300211620032903c801211a0c010b420021160b20112010200f200e56201020115620102011511b22021b2111200e200f20021b210e02402009450d00200410010b200341f0026a201a200e7c221b201620117c201b201a54ad7c10aa01200341b8036a200f200e7d201020117d200f200e54ad7d10d302200341d5016a200341b8036a41086a290300370000200341dd016a200341b8036a41106a290300370000200341e5016a200341b8036a41186a290300370000200341ed016a20032903f002370000200341f5016a200341f0026a41086a290300370000200341fd016a200341f0026a41106a29030037000020034185026a200341f0026a41186a29030037000041002106200341003a00cc01200341053a00c801200320032903b8033700cd01200341c8016a10b4010c080b41eac4c10041331042000b411441011019000b410021060c050b20012802004102460d070c080b41142101411410002202450d010b200342143702cc01200320023602c801200341c8016a41c8e8c10020011025200341f0026a41086a220120032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2001280200210220032802f402210420032802f0022101200320073602f002200341c8016a41086a22094200370300200342003703c80120012002200341c8016a1002200341b8026a41086a2009290300370300200320032903c8013703b802200341b8026a4110200341f0026a4104100302402004450d00200110010b411310002201450d01200342133702cc01200320013602c801200341c8016a41eee8c10041131025200341f0026a41086a220120032802d001360200200320032903c8013703f002200341b8036a200341f0026a101e2001280200210420032802f402210920032802f0022101200341003602d001200342013703c80120082005200341c8016a108d0120032802cc01210a20032802d001210b20032802c8012102200341c8016a41086a220c4200370300200342003703c80120012004200341c8016a1002200341b8026a41086a200c290300370300200320032903c8013703b802200341b8026a41102002200b10030240200a450d00200210010b02402009450d00200110010b02402006450d00200810010b410021090c070b200141011019000b411341011019000b20012802004102460d020c030b200810010c030b411e210420012802004102470d010b200141086a280200450d00200128020410010b200621090b2000200436020420002009360200200341e0036a24000bd57205087f027e057f027e0f7f230041a0026b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00002204417e6a220541044b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e050005020301000b200141046a2802002106200241096a2800002105200241056a280000210720022d0001210820022d00002101200341d8016a41026a2204200241046a2d00003a0000200341d8006a41086a2209200241156a290000370300200341d8006a410d6a220a2002411a6a2900003700002003200241026a2f01003b01d80120032002410d6a29000037035820010d07200341086a41026a20042d00003a000020034180026a41086a200929030037030020034180026a410d6a200a290000370000200320032f01d8013b01082003200329035837038002200841ff01714101470d07200341eb006a20034180026a41086a290300220b370000200341f0006a20034180026a410d6a290000220c370000200341c8016a41026a200341086a41026a2d000022023a0000200341d8016a41086a200b370300200341d8016a410d6a200c3700002003200536005f2003200736005b200320032f010822013b01582003200329038002220b370063200320013b01c8012003200b3703d801200320023a005a410021010c080b4100210841efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b22070d022003200141086a290300370358200341286a41086a220242003703002003420037032841e9b0c100411a200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a4110200341d8006a4108100320044102470d3a0c390b200341206a200141196a290000370300200341186a200141116a290000370300200341086a41086a200141096a29000037030020032001290001370308200241096a2800002105200241056a280000210820022d0001210920022d00002107200341d8016a41026a220a200241046a2d00003a0000200341d8006a41086a220d200241156a290000370300200341d8006a410d6a220e2002411a6a2900003700002003200241026a2f01003b01d80120032002410d6a29000037035820070d03200341c8016a41026a200a2d00003a000020034180026a41086a200d29030037030020034180026a410d6a200e290000370000200320032f01d8013b01c8012003200329035837038002200941ff01714101470d03200341eb006a20034180026a41086a290300220b370000200341f0006a20034180026a410d6a290000220c370000200341c8006a41026a200341c8016a41026a2d000022023a0000200341d8016a41086a200b370300200341d8016a410d6a200c3700002003200536005f2003200836005b200320032f01c80122073b01582003200329038002220b370063200320073b01482003200b3703d801200320023a005a410021020c040b4100210841efeec10041efeec1004100410320022d000120022d00001b41ff017122021b20024103461b2207450d080b412821050c380b200141216a2d0000210f200341c0016a200141196a290000370300200341b8016a200141116a290000370300200341a8016a41086a200141096a290000370300200320012900013703a801200241096a2800002105200241056a280000210820022d0001210920022d00002107200341d8016a41026a220a200241046a2d00003a0000200341d8006a41086a220d200241156a290000370300200341d8006a410d6a220e2002411a6a2900003700002003200241026a2f01003b01d80120032002410d6a29000037035820070d04200341c8016a41026a200a2d00003a0000200341086a41086a200d290300370300200341086a410d6a200e290000370000200320032f01d8013b01c80120032003290358370308200941ff01714101470d04200341eb006a200341086a41086a290300220b370000200341f0006a200341086a410d6a290000220c370000200341c8006a41026a200341c8016a41026a2d000022023a0000200341d8016a41086a200b370300200341d8016a410d6a200c3700002003200536005f2003200836005b200320032f01c80122073b015820032003290308220b370063200320073b01482003200b3703d801200320023a005a410021020c050b41012102412a21054197efc10021080b200341c4006a41026a2207200341c8006a41026a2d00003a0000200341286a41086a2209200341d8016a41086a290300370300200341286a41106a200341d8016a41106a290300370300200320032f01483b0144200320032903d80137032820020d32200341bb016a2009290300370000200341c0016a200341356a290000370000200320032f01443b01a801200320053600af01200320083600ab01200320032903283700b301200320072d00003a00aa01200341a8016a10cf02450d05411c10002202450d162003421c37025c20032002360258200341d8006a41d4b1c100411c1025200341d8016a41086a22022003280260360200200320032903583703d801200341086a200341d8016a101e2002280200210520032802dc01210720032802d8012102200341286a41086a220842003703002003420037032820022005200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a4110100e210502402007450d00200210010b2005450d09200341d8006a200341086a10df0220032802602209450d0f2003290264220b422088220ca7220a450d100c210b410121014197efc1002107412a21050b200341c4006a41026a2208200341c8016a41026a2d00003a0000200341286a41086a2202200341d8016a41086a290300370300200341286a41106a200341d8016a41106a290300370300200320032f01c8013b0144200320032903d80137032820010d1c200341bb016a2002290300370000200341c0016a200341286a410d6a290000370000200320032f01443b01a801200320053600af01200320073600ab01200320032903283700b301200320082d00003a00aa01200242003703002003420037032841f0f1c100410d200341286a1002200341c8016a41086a2002290300370300200320032903283703c8014200210b0240200341c8016a41104188f0c100410041001004417f460d0020034200370358200341c8016a4110200341d8006a41084100100441016a41084d0d1b2003290358210b0b200341286a41086a220242003703002003420037032841e9b0c100411a200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a41104188f0c100410041001004417f460d0520034200370358200341c8016a4110200341d8006a41084100100441016a41084d0d192003290358210c0c060b410121024197efc1002108412a21050b200341c4006a41026a2207200341c8006a41026a2d00003a0000200341286a41086a2209200341d8016a41086a290300370300200341286a41106a200341d8016a41106a290300370300200320032f01483b0144200320032903d80137032820020d2e20034193026a200929030037000020034180026a41186a2202200341356a290000370000200320032f01443b018002200320053600870220032008360083022003200329032837008b02200320072d00003a00820220034180026a10cf02450d02200341d8006a41186a200341a8016a41186a290300370300200341d8006a41106a200341a8016a41106a290300370300200341d8006a41086a200341a8016a41086a29030037030020034180016a20034180026a41086a29030037030020034188016a20034180026a41106a29030037030020034190016a2002290300370300200320032903a8013703582003200329038002370378411b10002202450d112003421b3702dc01200320023602d801200341d8016a419faec100411b1025200341086a41086a220220032802e001360200200320032903d801370308200341d8006a200341086a10af0220022802002105200328020c210720032802082102200341286a41086a220842003703002003420037032820022005200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a41104188f0c100410041001004417f460d06200341003a00d801200341c8016a4110200341d8016a41014100100441016a41014d0d0f20032d00d80121052007450d1c0c1b0b2003200141086a290300370358200341286a41086a220242003703002003420037032841e9b2c100411b200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a4110200341d8006a4108100320044102460d2e0c2f0b419eb2c1002108412b210520044102460d2d0c2e0b41f0b1c1002108412e210520044102460d2c0c2d0b4203210c0b200341d8006a109e0220032802582207410820071b2208200341d8006a41086a280200410020071b220941286c6a2105200c200b7c210b200328025c2104200821020340200520026b419f014d0d032002200341a8016a460d042002200341a8016a412010fa02450d04200241286a2201200341a8016a460d052001200341a8016a412010fa02450d05200241d0006a2201200341a8016a460d052001200341a8016a412010fa02450d05200241f8006a2201200341a8016a460d05200241a0016a21022001200341a8016a412010fa020d000c050b0b41c9b2c10021084120210520044102460d290c2a0b4102210520070d140c150b4102210120052002460d022008200941286c6a21050340200341a8016a2002460d012002200341a8016a412010fa02450d012005200241286a2202470d000c030b0b200221010b200141206a290300200b5621010b2001410247200171210202402007450d002004450d00200810010b024002402002450d0020034100360260200342013703582006200341d8006a101c200328025c21082003280260210420032802582107200341d8006a41186a22024200370300200341d8006a41106a22014200370300200341d8006a41086a220542003703002003420037035820072004200341d8006a100d20034180026a41186a2204200229030037030020034180026a41106a2209200129030037030020034180026a41086a220a2005290300370300200320032903583703800202402008450d00200710010b20022004290300370300200120092903003703002005200a2903003703002003200329038002370358411810002202450d07200342183702dc01200320023602d801200341d8016a4188a3c10041181025200341086a41086a220220032802e001360200200320032903d801370308200341d8006a200341086a101e20022802002101200328020c210520032802082102200341286a41086a220742003703002003420037032820022001200341286a1002200341c8016a41086a2007290300370300200320032903283703c801200341c8016a4110100e210102402005450d00200210010b2001450d0141a3b1c1002107411f21050c110b4183b1c1002107412021050c100b200341d8006a20034180026a10df02024020032802602202450d0020032802642101200329035821124200210c200341286a41086a220542003703002003420037032841f0f1c100410d200341286a1002200341c8016a41086a2005290300370300200320032903283703c8010240200341c8016a41104188f0c100410041001004417f460d00200342003703d801200341c8016a4110200341d8016a41084100100441016a41084d0d0a20032903d801210c0b02402001450d00200210010b200c20125a0d0041c2b1c1002107411221050c100b200341d8006a109f022003280258450d02200341c8006a41086a200341d8006a41086a280200220436020020032003290358370348200328024c21020c030b4200210b410121094200422088220ca7220a0d110b200341d8006a41186a200341a8016a41186a290300370300200341d8006a41106a200341a8016a41106a290300370300200341d8006a41086a200341a8016a41086a290300370300200320032903a80137035841002107200341d8006a21050c110b410021022003410036025020034208370348410021040b200341d8006a41186a220120034180026a41186a290300370300200341d8006a41106a220520034180026a41106a290300370300200341d8006a41086a220720034180026a41086a290300370300200320032903800237035802400240024020042002470d00200241016a22082002490d1920024101742209200820082009491b220aad42287e220c422088a70d19200ca722084100480d19024002402002450d002003280248210d200810002209450d032009200d2008200241286c2202200220084b1b10f8021a200d10010c010b200810002209450d020b2003200a36024c200320093602480b200341c8006a41086a200441016a221836020020032802482219200441286c6a2202200b37030020022003290358370308200241106a2007290300370300200241186a2005290300370300200241206a2001290300370300024002400240201841144b0d0020184102490d010340201820042202417f6a2204490d0b0240201820046b22084102490d002019200241286c6a22012903002019200441286c6a2209290300220b5a0d00200341d8006a41186a220f200941206a2202290300370300200341d8006a41106a2211200941186a2205290300370300200341d8006a41086a2216200941106a22072903003703002003200929030837035820092001290300370300200941086a200141086a2903003703002007200141106a2903003703002005200141186a2903003703002002200141206a2903003703004101210e024020084103490d00410321054102210a4101210e0340200a220720084f0d102009200741286c6a2202290300200b5a0d012007417f6a220120084f0d0f2009200141286c6a22012002290300370300200141206a200241206a290300370300200141186a200241186a290300370300200141106a200241106a290300370300200141086a200241086a2903003703000240200520084f0d002005210a200541016a2201200549210d200121052007210e20022101200d450d010c020b0b2007210e200221010b2001200b3703002009200e41286c6a22022003290358370308200241206a200f290300370300200241186a2011290300370300200241106a20162903003703000b20040d000c020b0b2018410176221aad42287e220b422088a70d03200ba72202417f4c0d03024002402002450d0020021000221b450d03201b210a0c010b4108211b4108210a0b201941586a211c201941887f6a211d410421114100211e4100211720182115024003402015210d41002115410121050240024002400240024002400240024002400240024002400240200d417f6a2207450d0002400240024002402019200741286c6a2903002019200d41286c22046a41b07f6a290300220b5a0d00201d20046a2102034020074101460d022007417f6a2107200b2002290300220c542101200241586a2102200c210b20010d000c030b0b200d417e6a2107201d20046a21014100211541002102034020072002460d0c200241016a2102200b2001290300220c5a2105200141586a2101200c210b20050d000b200241016a2105200d20026b417f6a22070d020c0a0b410021070b200d2007490d04200d20184b0d070240200d20076b22054101762208450d002019200741286c6a2102201c20046a21010340200341d8016a41206a2204200241206a2209290300370300200341d8016a41186a220e200241186a220f290300370300200341d8016a41106a2216200241106a2210290300370300200341d8016a41086a2214200241086a2215290300370300200320022903003703d801200141086a221f290300210b200141106a2220290300210c200141186a22212903002112200129030021132009200141206a2222290300370300200f20123703002010200c3703002015200b37030020022013370300202220042903003703002021200e29030037030020202016290300370300201f2014290300370300200120032903d801370300200241286a2102200141586a21012008417f6a22080d000b0b2007450d080b0240200541094d0d00200721152017201e470d0b0c0a0b200d20184b0d040340200d2007417f6a2215490d060240200d20156b22054102490d002019200741286c6a22012903002019201541286c6a2204290300220b5a0d00200341d8006a41186a2216200441206a2202290300370300200341d8006a41106a2210200441186a2207290300370300200341d8006a41086a2214200441106a22082903003703002003200429030837035820042001290300370300200441086a200141086a2903003703002008200141106a2903003703002007200141186a2903003703002002200141206a2903003703004101210f024020054103490d0041032107410221094101210f03402009220820054f0d052004200841286c6a2202290300200b5a0d012008417f6a220120054f0d062004200141286c6a22012002290300370300200141206a200241206a290300370300200141186a200241186a290300370300200141106a200241106a290300370300200141086a200241086a2903003703000240200720054f0d0020072109200741016a2201200749210e200121072008210f20022101200e450d010c020b0b2008210f200221010b2001200b3703002004200f41286c6a22022003290358370308200241206a2016290300370300200241186a2010290300370300200241106a20142903003703000b2015450d01201521072005410a490d000b0b2017201e470d090c080b41d08ac30020082005104e000b41e08ac30020012005104e000b2007200d107a000b200d2007417f6a22154f0d010b2015200d107a000b200d20181076000b200721152017201e460d010c020b200d21052017201e470d010b201e41016a2202201e490d1f201e4101742201200220022001491b2201ad420386220b422088a70d1f200ba722024100480d1f02400240201e450d00200210002207450d03200720112002201e4103742208200820024b1b10f802210220111001200221110c010b200210002211450d020b2001211e0b201120174103746a220220053602042002201536020002400240024002400240201741016a22174102490d000340024002400240024020112017220e417f6a22174103746a2202280200450d002011200e4103746a220841746a2802002207200228020422014d0d00200e41024d0d0b2011200e417d6a22024103746a2802042205200120076a4d0d01200e41034d0d0b200841646a280200200520076a4d0d010c0b0b200e4103490d01200228020421012011200e417d6a22024103746a28020421050b20052001490d010b200e417e6a21020b200e200241016a221f4d0d02200e20024d0d03201120024103746a2216280204222020162802006a22022011201f4103746a22102802002214490d04200220184b0d05201641046a21212019201441286c6a220d2010280204220f41286c22016a2107200241286c210502400240024002400240200220146b2204200f6b2202200f4f0d00201b2007200241286c220110f8021a200a20016a2108200f4101480d0120024101480d01201c20056a21052007210203402005200241586a2207200841586a2204200429030020072903005422091b2201290300370300200541206a200141206a290300370300200541186a200141186a290300370300200541106a200141106a290300370300200541086a200141086a2903003703002008200420091b2108200d2007200220091b22024f0d04200541586a2105200a2101200a2008490d000c050b0b201b200d200110f8021a200a20016a2108200f4101480d012004200f4c0d01201920056a2109200a2101200d21020340200220072001200729030020012903005422041b2205290300370300200241206a200541206a290300370300200241186a200541186a290300370300200241106a200541106a290300370300200241086a200541086a2903003703002001200141286a20041b2101200241286a2102200741286a200720041b220720094f0d04200820014b0d000c040b0b200721020c010b200d21020b200a21010b20022001200820016b220520054128706b10f8021a20212020200f6a360200201620143602002010201041086a200e201f417f736a41037410f9021a201741014b0d000b0b20150d060c070b41c08ac300201f200e104e000b41c08ac3002002200e104e000b20142002107a000b200220181076000b200241041019000b200e211720150d000b0b0240201e450d00201110010b201a450d00201b10010b200341c8006a10a502200341d8016a41186a20034180026a41186a290300370300200341d8016a41106a20034180026a41106a290300370300200341d8016a41086a20034180026a41086a29030037030020032003290380023703d801200341d8006a200641d00010f8021a02400240024002400240411810002202450d002003421837020c20032002360208200341086a4188a3c10041181025200341286a41086a2202200328021036020020032003290308370328200341d8016a200341286a101e20022802002107200328022c2108200328022821012003410036021020034201370308200341d8006a200341086a101c200328020c21042003280210210920032802082105200242003703002003420037032820012007200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a411020052009100302402004450d00200510010b02402008450d00200110010b200341d8006a10a001200341d8006a41186a20034180026a41186a290300370300200341d8006a41106a20034180026a41106a290300370300200341d8006a41086a20034180026a41086a2903003703002003200329038002370358412010002202450d01200341a8016a41086a290300210b200341a8016a41106a290300210c20032903a8012112200241186a200341a8016a41186a290300370000200241106a200c370000200241086a200b37000020022012370000411c10002201450d022003421c3702dc01200320013602d801200341d8016a41d4b1c100411c1025200341086a41086a220120032802e001360200200320032903d801370308200341d8006a200341086a101e2001280200210a200328020c210d20032802082104200341003602e001200342013703d8014101200341d8016a101b20032802d801210902400240024020032802dc01220820032802e00122076b411f4b0d00200741206a22012007490d2120084101742205200120012005491b22054100480d212005100021012008450d012001450d072001200920052008200820054b1b10f8021a200910010c020b20092101200821050c010b2001450d050b200120076a22082002290000370000200341d8016a41086a200741206a2207360200200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200320053602dc01200320013602d801200341286a41086a22084200370300200342003703282004200a200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a411020012007100302402005450d00200110010b0240200d450d00200410010b20021001200341d8006a41186a20034180026a41186a290300370300200341d8006a41106a20034180026a41106a290300370300200341d8006a41086a20034180026a41086a29030037030020034180016a200341a8016a41086a29030037030020034188016a200341a8016a41106a29030037030020034190016a200341a8016a41186a2903003703002003200329038002370358200320032903a801370378200341013a0044411b10002202450d032003421b3702dc01200320023602d801200341d8016a419faec100411b1025200341086a41086a220220032802e001360200200320032903d801370308200341d8006a200341086a10af0220022802002101200328020c210520032802082102200341286a41086a220742003703002003420037032820022001200341286a1002200341c8016a41086a2007290300370300200320032903283703c801200341c8016a4110200341c4006a4101100302402005450d00200210010b0240200328024c450d00200328024810010b20061001410021070c2a0b411841011019000b412041011019000b411c41011019000b411b41011019000b200541011019000b200241081019000b200841081019000b102c000b41eac4c10041331042000b411841011019000b411b41011019000b411c41011019000b41eac4c10041331042000b20042018107a000b41e08ac30020012008104e000b41d08ac30020072008104e000b41eac4c10041331042000b41eac4c10041331042000b41c082c300104f000b200610a001200610010c160b200210010b02400240024002400240200541ff01714102470d00200341d8016a41186a200341a8016a41186a290300370300200341d8016a41106a200341a8016a41106a290300370300200341d8016a41086a200341a8016a41086a290300370300200320032903a8013703d8010240024002400240411c10002202450d002003421c37025c20032002360258200341d8006a41d4b1c100411c1025200341086a41086a2202200328026036020020032003290358370308200341d8016a200341086a101e20022802002105200328020c210920032802082107200341c8016a41086a22024200370300200342003703c80120072005200341c8016a1002200341d8006a41086a2002290300370300200320032903c801370358410021020240200341d8006a41104188f0c100410041001004417f460d002003421037022c2003200341d8006a360228200341086a200341286a103620032802082208450d02200329020c210b200341c8016a41086a22024200370300200342003703c80120072005200341c8016a1002200341286a41086a2002290300370300200320032903c801370328200341286a41101008200b422088a72105200ba721022009450d040c030b410121084100210520090d020c030b411c41011019000b41eac4c10041331042000b200710010b200341d8006a41186a220720034180026a41186a290300370300200341d8006a41106a220920034180026a41106a290300370300200341d8006a41086a220a20034180026a41086a290300370300200320032903800237035802400240024020052002470d00200241016a220d2002490d102002410174220e200d200d200e491b2210ad420586220b422088a70d10200ba7220d4100480d102002450d01200d10002211450d0720112008200d200241057422022002200d4b1b10f8021a200810010c020b20082111200221100c010b200d10002211450d050b201120054105746a22022003290358370000200241186a2007290300370000200241106a2009290300370000200241086a200a290300370000411c10002202450d032003421c37025c20032002360258200341d8006a41d4b1c100411c1025200341086a41086a2202200328026036020020032003290358370308200341d8016a200341086a101e20022802002114200328020c2115200328020821162003410036026020034201370358200541016a2202200341d8006a101b024002402002450d00200541057441206a210d4100200341d8006a41086a28020022056b21092003280258210a200328025c21082011210e0340200e21020240200820096a411f4b0d00200541206a22072005490d112008410174220e20072007200e491b22074100480d1120071000210e024002402008450d00200e450d07200e200a20072008200820074b1b10f8021a200a10010c010b200e450d060b200e210a200721080b200241206a210e200a20056a22072002290000370000200741186a200241186a290000370000200741106a200241106a290000370000200741086a200241086a290000370000200941606a2109200541206a2105200d41606a220d0d000b200341e0006a20053602002003200836025c2003200a3602580c010b200341d8006a41086a2802002105200328025c21082003280258210a0b200341286a41086a220242003703002003420037032820162014200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a4110200a2005100302402008450d00200a10010b02402015450d00201610010b2010450d00201110010b200341d8006a41186a200341a8016a41186a290300370300200341d8006a41106a200341a8016a41106a290300370300200341d8006a41086a200341a8016a41086a29030037030020034180016a20034180026a41086a29030037030020034188016a20034180026a41106a29030037030020034190016a20034180026a41186a290300370300200320032903a80137035820032003290380023703782003200f3a0048411b10002202450d012003421b3702dc01200320023602d801200341d8016a419faec100411b1025200341086a41086a220220032802e001360200200320032903d801370308200341d8006a200341086a10af0220022802002105200328020c210720032802082102200341286a41086a220842003703002003420037032820022005200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a4110200341c8006a410110032007450d14200210010c140b200741011019000b411b41011019000b411c41011019000b200d41011019000b410021020240200a4101460d0041002102200a210503402005410176220720026a22082002200920084105746a200341a8016a412010fa024101481b2102200520076b220541014b0d000b0b200920024105746a200341a8016a412010fa022207450d01200341d8006a41186a200341a8016a41186a290300370300200341d8006a41106a200341a8016a41106a290300370300200341d8006a41086a200341a8016a41086a290300370300200320032903a801370358200341d8006a210520022007411f766a2207200a4d0d0041e88ec200104f000b0240200a200ba7470d00200a41016a2202200a490d07200ca7220d4101742208200220022008491bad22124205862213422088a70d072013a722024100480d07200a450d0220021000220f450d05200f20092002200d410574220820022008491b10f8021a200910010c030b2009210f0c030b4184b3c1002108412a2105200ba7450d0e2009100120044102460d0f0c100b20021000220f450d020b200b42808080807083201284210b0b200f20074105746a220241206a2002200a20076b41057410f9021a200241186a200541186a290000370000200241106a200541106a290000370000200241086a200541086a29000037000020022005290000370000200341286a41086a220242003703002003420037032841f0f1c100410d200341286a1002200341c8016a41086a22052002290300370300200320032903283703c80142002112024002400240200341c8016a41104188f0c100410041001004417f460d0020034200370358200341c8016a4110200341d8006a41084100100441016a41084d0d01200329035821120b200242003703002003420037032841e9b2c100411b200341286a100220052002290300370300200320032903283703c80102400240200341c8016a41104188f0c100410041001004417f460d0020034200370358200341c8016a4110200341d8006a41084100100441016a41084d0d032003290358211341012105411c2102411c10002207450d010c050b42e807211341012105411c2102411c100022070d040b200220051019000b41eac4c10041331042000b41eac4c10041331042000b200241011019000b2003421c37025c20032007360258200341d8006a41a0a3c10020021025200341d8016a41086a22022003280260360200200320032903583703d801200341086a200341d8016a101e2002280200211620032802dc01211020032802d80121112003410036026020034201370358410810002202450d042002201320127c37000020034288808080800137025c20032002360258200ca7220720056a2202200341d8006a101b024002402002450d00200741057441206a210d4100200341d8006a41086a28020022056b21092003280258210a200328025c2108200f210e0340200e21020240200820096a411f4b0d00200541206a22072005490d042008410174220e20072007200e491b22074100480d0420071000210e024002402008450d00200e450d08200e200a20072008200820074b1b10f8021a200a10010c010b200e450d070b200e210a200721080b200241206a210e200a20056a22072002290000370000200741186a200241186a290000370000200741106a200241106a290000370000200741086a200241086a290000370000200941606a2109200541206a2105200d41606a220d0d000b200341e0006a20053602002003200836025c2003200a3602580c010b200341e0006a2802002105200328025c21082003280258210a0b200341286a41086a220242003703002003420037032820112016200341286a1002200341c8016a41086a2002290300370300200320032903283703c801200341c8016a4110200a2005100302402008450d00200a10010b200ba7210202402010450d00201110010b02402002450d00200f10010b200341d8006a109f0241002107200328025c4100200328025822051b21172005410820051b2111024002400240200341d8006a41086a2202280200410020051b41286c2208450d000340200341d8006a41206a201120076a220541206a290300370300200341d8006a41186a200541186a290300370300200341d8006a41106a200541106a2903003703002002200541086a2903003703002003200529030037035820034180026a41186a200241186a29000037030020034180026a41106a200241106a29000037030020034180026a41086a200241086a290000370300200320022900003703800220034180026a200341086a412010fa020d022008200741286a2207470d000b0b200341003602602003420837035802402017450d00201110010b200341d8006a10a5020c010b200341d8016a41206a2202200341d8006a41206a290300370300200341d8016a41186a2209200341d8006a41186a290300370300200341d8016a41106a220a200341d8006a41106a290300370300200341d8016a41086a220d200341d8006a41086a290300370300200320032903583703d801412810002216450d08201620032903d801370300201641206a2002290300370300201641186a2009290300370300201641106a200a290300370300201641086a200d29030037030002400240200841586a2007460d00200541286a2102200820076b41b07f6a2108200341d8006a41086a21054101210f4101210e0340200341d8006a41206a2209200241206a290300370300200341d8006a41186a220a200241186a290300370300200341d8006a41106a220d200241106a2903003703002005200241086a2903003703002003200229030037035820034180026a41186a200541186a29000037030020034180026a41106a200541106a29000037030020034180026a41086a200541086a29000037030020032005290000370380020240024002400240024020034180026a200341086a412010fa02450d00200341d8016a41206a22072009290300370300200341d8016a41186a2210200a290300370300200341d8016a41106a2214200d290300370300200341d8016a41086a22152005290300370300200320032903583703d80120092007290300370300200a2010290300370300200d201429030037030020052015290300370300200320032903d801370358200e200f470d03200f41016a2207200f490d09200f4101742210200720072010491b2210ad42287e220b422088a70d09200ba722074100480d09200f450d01200710002214450d0c201420162007200f41286c220f200f20074b1b10f802210720161001200721160c020b20080d030c060b200710002216450d0a0b2010210f0b2016200e41286c6a22072003290358370300200741206a2009290300370300200741186a200a290300370300200741106a200d290300370300200741086a2005290300370300200e41016a210e2008450d030b200241286a2102200841586a21080c000b0b4101210f4101210e0b02402017450d00201110010b2003200e3602602003200f36025c20032016360258200341d8006a10a502200f450d00201610010b200341d8006a41186a200341086a41186a290300370300200341d8006a41106a200341086a41106a290300370300200341d8006a41086a200341086a41086a29030037030020032003290308370358411c10002202450d052003421c3702dc01200320023602d801200341d8016a41d4b1c100411c102520034180026a41086a220220032802e001360200200320032903d80137038002200341d8006a20034180026a101e2002280200210520032802840221072003280280022102200341286a41086a220842003703002003420037032820022005200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a4110100802402007450d00200210010b200341d8006a41186a200341086a41186a290300370300200341d8006a41106a200341086a41106a290300370300200341d8006a41086a200341086a41086a29030037030020032003290308370358411810002202450d06200342183702dc01200320023602d801200341d8016a4188a3c1004118102520034180026a41086a220220032802e001360200200320032903d80137038002200341d8006a20034180026a101e2002280200210520032802840221072003280280022102200341286a41086a220842003703002003420037032820022005200341286a1002200341c8016a41086a2008290300370300200320032903283703c801200341c8016a4110100802402007450d00200210010b200341d8006a109e022003280258220f4108200f1b2111200328025c21160240200341d8006a41086a220e2802004100200f1b2202450d00200241286c2108200341f8006a210520112102034020052002290000370000200341d8006a41186a200341086a41186a290300370300200341d8006a41106a200341086a41106a290300370300200e200341086a41086a290300370300200541086a200241086a290000370000200541106a200241106a290000370000200541186a200241186a29000037000020032003290308370358411b10002207450d032003421b3702dc01200320073602d801200341d8016a419faec100411b102520034180026a41086a2207200341d8016a41086a280200360200200320032903d80137038002200341d8006a20034180026a10af0220072802002109200328028402210a2003280280022107200341286a41086a220d42003703002003420037032820072009200341286a1002200341c8016a41086a200d290300370300200320032903283703c801200341c8016a411010080240200a450d00200710010b200241286a2102200841586a22080d000b0b200f450d082016450d08201110014100210820044102460d0a0c0b0b1018000b411b41011019000b200741011019000b200741081019000b410841011019000b411c41011019000b411841011019000b412841081019000b410021080b20044102470d010b41000d00200141046a280200220210a001200210010b200821070b2000200536020420002007360200200341a0026a24000be90506057f017e017f027e017f027e230041306b22042400024002400240411410002205450d002004421437022420042005360220200441206a41eeefc10041141025200441106a41086a22052004280228360200200420042903203703102001200441106a101e20052802002106200428021421072004280210210842002109200441206a41086a220a42003703002004420037032020082006200441206a10022005200a2903003703002004200429032037031002400240200441106a41104188f0c100410041001004417f460d002004420037032820044200370320200441106a4110200441206a4110410010042205417f460d012005410f4d0d01200441286a290300210b200429032021092007450d040c030b4200210b20070d020c030b41eac4c10041331042000b411441011019000b200810010b0240024020092002542208200b200354200b2003511b450d00419e87c2002105411521010c010b200441086a200110ca01024020042802082205450d00200428020c21010c010b024002400240411810002205450d002004421837022420042005360220200441206a4193f1c10041181025200441106a41086a22052004280228360200200420042903203703102001200441106a101e200528020021072004280214210a200428021021064200210c200441206a41086a220d42003703002004420037032020062007200441206a10022005200d2903003703002004200429032037031002400240200441106a41104188f0c100410041001004417f460d002004420037032820044200370320200441106a4110200441206a4110410010042205417f460d012005410f4d0d01200441286a290300210e2004290320210c200a450d040c030b4200210e200a0d020c030b41eac4c10041331042000b411841011019000b200610010b2001200c20027c220f200e20037c200f200c54ad7c10d3022001200920027d200b20037d2008ad7d10aa01410021050b2000200136020420002005360200200441306a24000bbf0b06017f017e017f017e037f017e230041306b2203240042002104200341106a41086a220542003703002003420037031041bef0c100411b200341106a1002200341086a2005290300370300200320032903103703000240024002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a29030021062003290320210441182105411810002207450d010c030b42002106411821054118100022070d020b200541011019000b41eac4c10041331042000b2003421837022420032007360220200341206a4193f1c10020051025200341106a41086a22052003280228360200200320032903203703102000200341106a101e2005280200210820032802142109200328021021072003200237032820032001370320200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030020034110200341206a4110100302402009450d00200710010b02402004200158200620025820062002511b0d00024002400240411810002205450d002003421837022420032005360220200341206a4193f1c10041181025200341106a41086a22052003280228360200200320032903203703102000200341106a101e20052802002108200328021421092003280210210742002106200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d012005410f4d0d01200341286a2903002104200329032021062009450d040c030b4200210420090d020c030b41eac4c10041331042000b411841011019000b200710010b42002102200341106a41086a220542003703002003420037031041d9f0c1004116200341106a1002200341086a20052903003703002003200329031037030002400240024002400240024002400240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a2903002101200329032021020c010b420021010b0240200220067d220a200256200120047d2002200654ad7d220220015620022001511b0d002003200a37032020032002370328200341106a41086a220542003703002003420037031041d9f0c1004116200341106a1002200341086a20052903003703002003200329031037030020034110200341206a411010030b411810002205450d022003421837022420032005360220200341206a4193f1c10041181025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021082003280214210920032802102107200542003703002003420037031020072008200341106a1002200341086a20052903003703002003200329031037030020034110100802402009450d00200710010b411410002205450d032003421437022420032005360220200341206a41eeefc10041141025200341106a41086a22052003280228360200200320032903203703102000200341106a101e200528020021082003280214210920032802102107200542003703002003420037031020072008200341106a1002200341086a2005290300370300200320032903103703000240200341104188f0c100410041001004417f460d00200342003703282003420037032020034110200341206a4110410010042205417f460d022005410f4d0d02200341286a290300210220032903202101410021052009450d060c050b4101210520090d040c050b41eac4c10041331042000b41eac4c10041331042000b411841011019000b411441011019000b200710010b20012002844200522005410173710d00200010f1020b200341306a24000bd50504057f017e017f067e230041306b22042400024002400240411810002205450d002004421837022420042005360220200441206a4193f1c10041181025200441106a41086a22052004280228360200200420042903203703102001200441106a101e20052802002106200428021421072004280210210842002109200441206a41086a220a42003703002004420037032020082006200441206a10022005200a2903003703002004200429032037031002400240200441106a41104188f0c100410041001004417f460d002004420037032820044200370320200441106a4110200441206a4110410010042205417f460d012005410f4d0d01200441286a290300210b200429032021092007450d040c030b4200210b20070d020c030b41eac4c10041331042000b411841011019000b200810010b20012009200220092009200256200b200356200b20035122051b22081b220c7d200b2003200b20081b220d7d2009200c54ad7d10d3024200210e200441206a41086a220142003703002004420037032041d9f0c1004116200441206a1002200441106a41086a200129030037030020042004290320370310024002400240200441106a41104188f0c100410041001004417f460d002004420037032820044200370320200441106a4110200441206a4110410010042201417f460d022001410f4d0d02200441286a290300210f2004290320210e0c010b4200210f0b0240200e200c7d2210200e56200f200d7d200e200c54ad7d220e200f56200e200f511b0d00200420103703002004200e370308200441206a41086a220142003703002004420037032041d9f0c1004116200441206a1002200441106a41086a200129030037030020042004290320370310200441106a41102004411010030b20002002200c7d370308200041106a2003200d7d2002200c54ad7d37030020002009200254200b20035420051bad370300200441306a24000f0b41eac4c10041331042000b885f05057f037e057f047e067f230041c0076b22022400200241003a00a006200241a0066a2001280200220320012802042204410047220510f8021a02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020042005490d00200141046a200420056b22063602002001200320056a2205360200024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004450d0020022d00a0062204410c4b0d0a024020040e0d00090607030a0c080e050d0204000b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8101200141046a200620046b3602002001200520046a3602002006450dbe0120022d00a006450d0f0cbe010b2000410d360200200241c0076a24000f0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a22043602002006450d7c20022d00a0062205450d0e20054101470d7c200241a8056a200110960120022802a805450d7c200241b8056a290300210720022903b005210820024198056a2001109701200228029805450d7c20022903a005210920024190056a2001103a200228029005450d7c2002280294052204417f4c0d8c012004450d68200410002205450daa0120054100200410f7021a0c690b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a220a3602002006450d4e20022d00a006220b41094b0d4e4102210c0240200b0e0a4e004547434a4b484d444e0b200241a0016a2001103a20022802a001450d4e20022802a4012204410876210d4103210c0c480b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d800141042103200141046a200620046b220e3602002001200520046a22043602002006450d1820022d00a0062205450d0d20054101470d18200241a0066a200e4120200e41204922061b22056a41004100412020056b2005411f4b1b10f7021a200241a0066a2004200510f8021a41042103200141046a200e20056b3602002001200420056a36020020060d17200220022f00a1063b01ce0520022d00a006210120022800a306210420022900a706210920022900af06210720022800b706210520022800bb06210620022d00bf06210e200220022f01ce0522033b01a006200220033b01cc05200220033b01ca05410321030cb7010b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b3602002001200520046a3602002006450db80120022d00a006450d090cb8010b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b3602002001200520046a3602002006450d0e20022d00a0062204450d0c20044101470d0e200241a0066a200110a20120022d00a00622044102460d0e20022d00a306210520022f00a106210e200241ac066a2902002109200241bc066a2902002107200241b8066a2802002106200241b4066a280200210320022902a4062108200241f8006a20011096012002280278450d0e200241f8006a41106a290300210f2002290380012110200241e0006a20011096012002280260450d0e200e2005411074722101200241f0006a290300211141032105200229036821120c0d0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a22043602002006450d3220022d00a0062205450d1120054101460d1020054102470d32200241003a00a006200241a0066a20042003410047220510f8021a20032005490d8d0141042106200141046a200320056b3602002001200420056a3602002003450d3220022d00a00641017121010c120b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a22043602002006450d1b20022d00a006220541044b0d1b024020050e05001d171916000b200241a0066a200110d50220022802a0062101200241f0066a200241a0066a41047241cc0010f8021a2001410d460d1b200241d0056a200241f0066a41cc0010f8021a41d00010002204450d9b0120042001360200200441046a200241d0056a41cc0010f8021a410221050c1a0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a22053602002006450d7020022d00a006220641054b0d704103210e024020060e06005d2627242a000b200241186a2001103a2002280218450d70200228021c2205417f4c0d85012005450d58200510002204450da00120044100200510f7021a0c590b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d8001200141046a200620046b22033602002001200520046a22043602002006450d4b20022d00a006220541054b0d4b024020050e06002a2728242b000b200241a0066a200110d50220022802a0062105200241f0066a200241a0066a41047241cc0010f8021a2005410d460d4b200241d0056a200241f0066a41cc0010f8021a41d00010002204450d9c0120042005360200200441046a200241d0056a41cc0010f8021a20024188026a2001109601200229038802a7450d4a20024198026a29030021072002290390022109410221060c2b0b2000410d360200200241c0076a24000f0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d7f200141046a200620046b3602002001200520046a3602002006450da80120022d00a006220441084b0da801024020040e09003431323035373338000b200241c0026a2001103a20022802c002450da80120022802c4022213417f4c0d82012013450d60201310002206450da2012013ad2109200141046a210341002114034020032802002104200241003a00a006200241a0066a2001280200220e2004410047220510f8021a20042005490d85012003200420056b3602002001200e20056a3602002004450d6320022d00a006210e02402009422088a72009a72204470d00200441016a22052004490d850120044101742215200520052015491b22054100480d8501024002402004450d00200510002215450d8901201520062005200420052004491b10f802210420061001200421060c010b200510002206450d88010b2009428080808070832005ad8421090b20062009422088a76a200e4101713a000020094280808080107c2109201441016a22142013490d000c620b0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d1e20022d00a006220541044b0d1e024020050e05001c1a1b13000b200241f0036a200110960120022802f003450d1e20024180046a290300210920022903f8032107200241a0066a200110a2014102210520022d00a00622044102460d1e200241bc066a2902002108200241b4066a290200210f20022f00a106210120022d00a306210620022902a40621102002200241ac066a2902003703f806200220103703f0062002200f37038007200120064110747221010c1d0b200241003a00a006200241a0066a20052006410047220410f8021a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d0820022d00a0062205450d0720054101470d08200241a0066a200341202003412049220e1b22056a41004100412020056b2005411f4b1b10f7021a200241a0066a2004200510f8021a41042106200141046a200320056b3602002001200420056a360200200e0d17200220022f00a1063b01f00620022d00a006210320022800a306210420022900af06210920022800b706210e20022800bb06211420022d00bf06211320022900a7062107200220022f01f00622053b01a006200220053b01cc05200241e0036a2001103a20022802e003450da90120022802e4032105200141046a22162802002106200241003a00a006200241a0066a200128020022172006410047221510f8021a20062015490d8e012016200620156b3602002001201720156a3602002006450d4e2007422088a721152007a7210120022d00a0062116200220022f01cc053b01ce05410321060caa010b200241e8036a2001103a20022802e803450dae0120022802ec032204417f4c0d7f2004450d4320041000220e450d8b01200e4100200410f7021a0c440b200241086a20011097012002290308a7450dae012002290310210920004100360200200041106a2009370300200041086a4202370300200241c0076a24000f0b200241a0066a20034120200341204922061b22056a41004100412020056b2005411f4b1b10f7021a200241a0066a2004200510f8021a4104210e200141046a200320056b3602002001200420056a36020020060d09200220022f00a1063b01f00620022d00a006210620022800a306210520022900a706211120022900af06211220022800b706210320022800bb06211420022d00bf062113200220022f01f00622043b01a006200220043b01cc05200241f0046a200110960120022802f004450d6020024180056a290300210f20022903f8042109200241e0046a200110970120022802e004450d6020022903e8042110200241d8046a2001103a20022802d804450d6020022802dc042204417f4c0d7d2004450d5e200410002217450d9e0120174100200410f7021a0c5f0b200241c0056a2001103a4100210420022802c005450d2520022802c4052205417f4c0d7c2005450d47200510002213450d890120134100200510f7021a0c480b200241a0066a200110a2014102210520022d00a00622044102460d0120022d00a306210e20022f00a1062114200241ac066a2902002109200241bc066a2902002107200241b8066a2802002106200241b4066a280200210320022902a4062108200241c8006a20011096012002280248450d012014200e411074722101200241c8006a41106a290300210f200229035021100b200020013b000d200041023602002000410f6a20014110763a0000200041c8006a2011370200200041c0006a2012370200200041386a200f370200200041306a2010370200200041186a2009370000200041106a2008370000200041286a2007370000200041246a2006360000200041206a20033600002000410c6a20043a0000200041086a2005360200200241c0076a24000f0b2000410d360200200241c0076a24000f0b200241d8036a2001103a20022802d803450d0020022802dc032104200241a0066a200110d50220022802a0062105200241f0066a200241a0066a41047241cc0010f8021a2005410d470d240b200220022f01ce053b01a0060ca5010b20024190016a2001109701200229039001a7450d212002290398012209422088a7210e2009a72114410321060c010b200241a0066a20034120200341204922061b22056a41004100412020056b2005411f4b1b10f7021a200241a0066a2004200510f8021a200141046a200320056b3602002001200420056a36020020060d1f200220022f00a1063b01f00620022d00a006210120022800a306211320022900af06210920022800b706210320022800bb06210520022d00bf06210420022900a7062107200220022f01f00622063b01a006200220063b01cc05200220063b01ce05200220022f01ce0522063b01d005200220063b01ca052007422088a7210e2007a72114410221060b200220022f01ca0522153b01a006200220153b01c805200020013a0009200041086a20063a000020004103360200200041286a20043a0000200041246a2005360200200041206a2003360200200041186a2009370200200041146a200e360200200041106a20143602002000410c6a2013360200200020022f01c8053b000a200241c0076a24000f0b200220022f01f0063b01a0060c630b200220022f01ce053b01a0060b0c9e010b200241c8036a200110970120022903c803a7450d0520022903d0032209422088a721012009a72106410621050c030b200241a0066a200341202003412049220e1b22066a41004100412020066b2006411f4b1b10f7021a200241a0066a2004200610f8021a41042105200141046a200320066b3602002001200420066a360200200e0d37200220022f00a1063b01f00620022d00a006210320022800a306210420022900af06210920022800b706210e20022800bb06211420022d00bf06211320022900a7062107200220022f01f00622013b01a006200220013b01cc05200220013b01ce052007422088a721012007a721060c480b200241d0046a2001103a20022802d004450d0b20022802d40422044108762101410621050c090b200241b8036a200110970120022903b803a7450d0220022903c0032209422088a721012009a72106410521050b0b200220022f01ce053b01a0060c460b200220022f01ce053b01a0060c96010b200241a0066a200341202003412049220e1b22056a41004100412020056b2005411f4b1b10f7021a200241a0066a2004200510f8021a200141046a200320056b22063602002001200420056a2205360200200e0d32200220022f00a1063b01f00620022d00a006210320022800a306210420022900a706210720022900af06210920022800b706210e20022800bb06211420022d00bf062113200220022f01f00622153b01a006200220153b01d005200241003a00a006200241a0066a20052006410047221510f8021a20062015490d7f200141046a200620156b3602002001200520156a3602002006450d4120022d00a0062101200220022f01d0053b01ce05200141017121152007422088a721012007a72106410321050c430b200220022f01f0063b01a0060c91010b200241003602a006200241a0066a200420034104200341044922061b220510f8021a200141046a200320056b3602002001200420056a36020020060d0420022802a0062104200241b0046a200110960120022802b004450d04200241c0046a290300210920022903b8042107200241a0046a200110970120022802a004450d0420022903a8042108200241003602a00641042105200241a0066a2001280200220e200141046a221428020022064104200641044922131b220310f8021a2014200620036b3602002001200e20036a36020020130d0420022802a006210120024180076a2009370300200220073703f806200220013602f006200441087621010c030b200241c8046a2001103a20022802c804450d0320022802cc0422044108762101410521050c010b20024188046a2001109601200229038804a7450d0220024198046a290300210920022002290390043703f006200220093703f806410321050b0b200241a0066a41106a200241f0066a41106a290300220f370300200241a0066a41086a200241f0066a41086a2903002210370300200241d0056a41086a22062010370300200241d0056a41106a2203200f370300200220022903f006220f3703d0052002200f3703a006200041386a2009370200200041306a20073702002000410c6a2001410874200441ff017172360200200041086a20053602002000410a360200200041286a2008370200200041106a20022903d005370200200041186a2006290300370200200041206a2003290300370200200241c0076a24000f0b200241a0066a41106a200241f0066a41106a290300370300200241a0066a41086a200241f0066a41086a290300370300200220022903f0063703a0062000410d360200200241c0076a24000f0b200241286a2001103a2002280228450d4c200228022c2205417f4c0d612005450d30200510002204450d7d20044100200510f7021a0c310b200241b0026a2001103a20022802b002450d274106210620022802b40221040c070b200241206a2001103a2002280220450d4a20022802242205417f4c0d5f2005450d30200510002204450d7c20044100200510f7021a0c310b200242003703a006200241a0066a200520034108200341084922061b220410f8021a200141046a200320046b3602002001200520046a36020020060d4920022903a00621094105210e0c350b200241a8026a2001103a20022802a802450d2420022802ac022104200141046a22032802002105200241003a00a006200241a0066a2001280200220e2005410047220610f8021a20052006490d6e2003200520066b3602002001200e20066a3602002005450d2420022d00a0062105410421060c050b200241a0066a200110d50220022802a0062105200241f0066a200241a0066a41047241cc0010f8021a2005410d460d23200241d0056a200241f0066a41cc0010f8021a41d00010002204450d7520042005360200200441046a200241d0056a41cc0010f8021a200141046a22032802002105200241003a00a006200241a0066a2001280200220e2005410047220610f8021a20052006490d762003200520066b22143602002001200e20066a22063602002005450d2220022d00a006220541034f0d2242002107200242003703a006200241a0066a2006201441082014410849220e1b220310f8021a200141046a201420036b3602002001200620036a360200200e0d2220022903a0062109410521060c040b200241c0006a2001103a2002280240450d4620022802442217ad220942187e2207422088a70d5b2007a72205417f4c0d5b2005450d302005100022040d31200541041019000b200241a0026a2001103a20022802a002450d214103210620022802a40221040c010b200242003703a006200241a0066a2004200341082003410849220e1b220510f8021a200141046a2214200320056b22063602002001200420056a2204360200200e0d2020022903a0062109200241003602a006200241a0066a20042006410420064104491b220510f8021a2014200620056b3602002001200420056a360200200641034d0d2020022802a006210442002107410721060b0b200220022f01ce0522013b01a006200220013b01cc05200041186a2007370200200041106a2009370200200020053a0009200041086a20063a0000200041053602002000410c6a2004360200200020022f01cc053b000a200241c0076a24000f0b0c230b200220022f01f0063b01a006200220022f01ce053b01d0050b200220022f01ca053b01a0062000410d360200200241c0076a24000f0b200241d0056a200241f0066a41cc0010f8021a41d00010002201450d6220012005360200200141046a200241d0056a41cc0010f8021a200220022f01ce053b01a006410221060c7e0b200241a0066a200110a20120022d00a00622064102460d7820022d00a306210420022f00a106210e200241ac066a290200210f200241bc066a2902002109200241b8066a2802002105200241b4066a280200210320022902a4062110200241f8026a200110960120022802f802450d78200241f8026a41106a29030021072002290380032108200241f0026a2001103a20022802f002450d78200e2004411074722101200f422088a72114200fa7211320022802f40221162010420888210f2010a72104410621150c7a0b200241e0026a2001103a20022802e002450d7720022802e40222064108762101410421150c040b200241e8026a2001103a20022802e802450d7620022802ec0222064108762101410521150c030b20024198036a2001109701200229039803a7450d7520022903a0032209420888210f2009a72104410921150c050b200241d8026a2001103a20022802d802450d7420022802dc022106200241a0066a200110a20120022d00a00622044102460d74200241ac066a2902002109200241bc066a2902002107200241b4066a2802002105200220022902a40622083700f306200241fb066a2009370000200220022d00a3063a00f206200220022f00a1063b01f0062002200241b8066a2802003602d005200220073702d405200241d0026a2001103a20022802d002450d7420022802d402210e200241c8026a2001103a20022802c802450d742007422088a721162008422088a721132009422088a721032009a721142006410876210120023502f00620023301f40620023100f6064210868442208684210f20022903d005210920022802cc02ad210842002107410321150c760b20024190036a2001103a200228029003450d7320022802940322064108762101410721150b0c730b200241a0066a200110a20120022d00a00622064102460d7120022902a4062207420888210f20022f00a10620022d00a306411074722101200241ac066a2902002208422088a72114200241b4066a2802002103200241b8066a2802002105200241bc066a29020021092007a721042008a72113410821150c730b200241a8036a200110970120022903a803a7450d7020022903b0032209420888210f2009a72104410a21150b0c700b200241d0016a2001103a20022802d001450d0b20022802d4012104200241c8016a2001103a20022802c801450d0b20022802cc012105200241b0016a200110960120022903b001a7450d0b200241c0016a29030021092004410876210d20022903b8012207a721174106210c0c020b20024180026a2001103a200228028002450d0a2002280284022204410876210d410b210c0c040b200241a0066a200110a20120022d00a00622044102460d09200241ac066a290200210920022f00a10620022d00a30641107472210d200241bc066a2902002207422088a721132007421088a721142007420888a72115200241b4066a2802002105200241b8066a28020021062007a7210e20022902a4062207a721174104210c0b2007422088a721160c070b200241a8016a2001103a20022802a801450d0720022802ac012204410876210d4105210c0c010b200241f8016a2001103a20022802f801450d0620022802fc012204410876210d4109210c0b0c040b200241d8016a200110970120022903d801a7450d0420022903e0012209422088a721162009a721174107210c0c010b200241e8016a200110970120022903e801a7450d0320022903f0012209422088a721162009a721174108210c0b0c010b200241003a00a006200241a0066a200a2003410047220410f8021a20032004490d4e200141046a200320046b3602002001200a20046a3602002003450d0120022d00a0064101712118410a210c0b200220022f01f00622013b01a006200220013b01d005200020183a0009200041086a200c3a0000200041043602002000412c6a2013360200200020143b012a200020153a0029200041286a200e3a0000200041246a2006360200200041206a2005360200200041186a2009370200200041146a2016360200200041106a20173602002000410c6a200d410874200441ff017172360200200020022f01d0053b000a200241c0076a24000f0b200220022f01f0063b01a0062000410d360200200241c0076a24000f0b4101210e0b200e2001280200200141046a22062802002203200420032004491b220510f802210e200628020022142005490d412006201420056b3602002001200128020020056a3602000240200320044f0d00200e10010c6a0b200e450d6920004289808080203703002000410c6a2004ad2209422086200984370200200041086a200e360200200241c0076a24000f0b200410a001200410010b200220022f01ce053b01a0062000410d360200200241c0076a24000f0b200220022f01f0063b01a0060c010b200220022f01f0063b01a0060b410721050c0f0b410121130b20132001280200200141046a220e2802002214200520142005491b220610f8022113200e28020022152006490d3b2005ad22094220862009842109200e201520066b3602002001200128020020066a3602000240201420054f0d00201310010c010b02402013450d0041022103201321040c610b201321040b0c5f0b410421060c5a0b410121040b20042001280200200141046a2203280200220e2005200e2005491b220610f8022113200328020022142006490d412003201420066b3602002001200128020020066a360200200e2005490d192013450d1a2005ad220942208620098421094106210e0c060b410121040b20042001280200200141046a2203280200220e2005200e2005491b220610f8022113200328020022142006490d402003201420066b3602002001200128020020066a360200200e2005490d172013450d182005ad220942208620098421094104210e0c040b410121040b20042001280200200141046a2203280200220e2005200e2005491b220610f8022113200328020022142006490d3f2003201420066b3602002001200128020020066a360200200e2005490d152013450d162005ad220942208620098421094102210e0c020b410421040b02402017450d00200141046a2106410021150340200241386a2001103a2002280238450d14200228023c2205417f4c0d2b024002402005450d00200510002214450d3620144100200510f7021a0c010b410121140b201420012802002006280200220e2005200e2005491b220310f8022114200628020022132003490d2f2006201320036b3602002001200128020020036a360200200e2005490d132014450d142005ad22074220862007842107200241306a2001103a2002280230450d1220022802342205417f4c0d2b024002402005450d00200510002213450d3720134100200510f7021a0c010b410121130b201320012802002006280200220e2005200e2005491b220310f8022113200628020022162003490d302006201620036b3602002001200128020020036a360200200e2005490d112013450d1202402009422088a722032009a7470d00200341016a220e2003490d2d20034101742216200e200e2016491bad220842187e220f422088a70d2d200fa7220e4100480d2d024002402003450d00200e10002216450d3920162004200e200341186c22032003200e4b1b10f802210320041001200321040c010b200e10002204450d380b20094280808080708320088421090b20042009422088a741186c6a2203201336020c2003200737020420032014360200200341106a2005ad220742208620078437020020094280808080107c2109201541016a22152017490d000b0b2004450d144107210e0b20004101360200200041106a20093702002000410c6a2004360200200041086a200e360200200241c0076a24000f0b410721050b0b200220022f01ce053b01a00620054107460d510b200220022f01a0063b01ca05200020033a0009200041086a20053a000020004107360200200020153a0029200041286a20133a0000200041246a2014360200200041206a200e360200200041186a2009370200200041146a2001360200200041106a20063602002000410c6a2004360200200020022f01ca053b000a200241c0076a24000f0b410121050b20052001280200200141046a2203280200220e2004200e2004491b220610f8022114200328020022132006490d392003201320066b3602002001200128020020066a360200200e2004490d112014450d122004ad220f422086200f84211120024188056a2001103a200228028805450d10200228028c052204417f4c0d222004450d0e200410002213450d4520134100200410f7021a0c0f0b42002109410121060b2006450d46200241b8026a2001103a20022802b802450d0520022802bc0221132009420888210f200641087621012009a72104410221150c470b2009a7450d450c440b410121170b20172001280200200141046a22152802002216200420162004491b220e10f802211720152802002218200e490d3c20152018200e6b36020020012001280200200e6a36020002400240201620044f0d00201710010c010b2017450d00200220022f01cc053b01d0052004ad2207422086200784220742088842088620074238862017ad4218868422084238888421072013ad42ff018320084208868421084102210e0c020b4104210e0b0b200220022f01d0053b01a006200e4104460d0c0c3f0b2009a70d3f0c400b201310010b2007a7450d010b201410010b02402009422088a72201450d00200141186c21052004210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141186a2101200541686a22050d000b0b2009a7450d010b200410010b2000410d360200200241c0076a24000f0b410121130b20132001280200200141046a2203280200220e2004200e2004491b220610f8022113200328020022152006490d342003201520066b3602002001200128020020066a3602000240200e20044f0d00201310010c010b2013450d00200220022f01d0053b01a0062004ad220f422086200f84220f4220862013ad842112200f422088a721034103210e0c360b2011a7450d010b201410010b200220022f01d0053b01a0060b2000410d360200200241c0076a24000f0b20052004107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b20042006107a000b102c000b1018000b20052004107a000b200541011019000b20032013107a000b20032016107a000b20052003107a000b20052014107a000b20062015107a000b200541011019000b200541011019000b200e41041019000b200441011019000b200541011019000b20152006107a000b41d00041081019000b20042003107a000b20062005107a000b20062014107a000b20062014107a000b20062014107a000b41d00041081019000b20152006107a000b20062013107a000b41d00041081019000b41d00041081019000b20062005107a000b200541011019000b200541011019000b200541011019000b200441011019000b200e2018107a000b201341011019000b200441011019000b20062015107a000b200441011019000b200220022f01a0063b01ce05200041c0006a200f370000200041386a2009370000200041306a2007370000200041286a2008370000200020063a0009200041086a200e3a00002000410b360200200041c8006a2010370000200041246a2014360000200041206a2003360000200041186a2012370000200041106a20113700002000410c6a2005360000200020022f01ce053b000a200241c0076a24000f0b200610010b2000410d360200200241c0076a24000f0b0b20004106360200200041c0006a2007370200200041386a2008370200200041346a200e360200200041306a2016360200200041286a2009370200200041246a2005360200200041206a20033602002000411c6a2014360200200041186a2013360200200041086a20153602002000410c6a2001410874200641ff017172360200200041106a200f4208862004ad42ff018384370200200241c0076a24000f0b0b200220022f01ce053b01a00620064104460d030b200220022f01a0063b01ca05200020033a0005200020063a000420004108360200200041286a2005360200200020163a0025200041246a20133a0000200041206a20143602002000411c6a200e360200200041146a2009370200200041106a20153602002000410c6a2001360200200041086a2004360200200020022f01ca053b0006200241c0076a24000f0b2000410d360200200241c0076a24000f0b200241a0066a41026a2214200241f0066a41026a2d00003a0000200220022f01ca053b01ce05200220022f00f0063b01a006024020034104470d002000410d360200200241c0076a24000f0b200241d0056a41026a221320142d00003a0000200220022f01ce053b01c805200220022f01a0063b01d005200020013a0005200020033a00042000410c360200200041246a200e3a0000200041206a20063600002000411c6a2005360000200041146a20073700002000410c6a2009370000200041086a2004360000200020022f01c8053b0006200020022f01d0053b0025200041276a20132d00003a0000200241c0076a24000f0b2000410d360200200241c0076a24000f0b2000410d360200200241c0076a24000f0b2000410d360200200241c0076a24000b851108067f017e017f027e087f017e037f037e230041d0006b22022400024002400240024002400240024002400240024002400240024002400240024002400240024020012d00002203450d0020034101470d01200041003a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a29000037000020030d024101450d120c110b200241336a2001410c6a280000360000200041013a00002002200141046a29000037002b20002002290028370001200041086a2002412f6a29000037000020030d0141000d100c110b20034103470d0520022001410c6a280200220436021c2002200141046a2802002205360218200241003a0028200241286a20052004410047220610f8021a20042006490d072002200420066b220736021c2002200520066a22063602182004450d050240024002400240024020022d00282204450d00024020044101460d0020044102470d0b200241003a0028200241286a20062007410047220410f8021a20072004490d0f2002200720046b220536021c2002200620046a22043602182007450d0b20022d00280d0b20024200370328200241286a200420054108200541084922061b220710f8021a2002200520076b36021c2002200420076a36021820060d0b20022903282108200241086a200241186a103a2002280208450d0b200228020c2209ad220a42287e220b422088a70d0e200ba72207417f4c0d0e2007450d0220071000220c450d1420090d030c040b200241003a0028200241286a20062007410047220410f8021a20072004490d0f2002200720046b36021c2002200620046a3602182007450d0a20022d00280d0a200241286a200241186a103920022802282207450d0a200229022c2108200241146a41026a200241286a41026a2d00003a0000200220022f00283b0114410121060c040b200241003a0028200241286a20062007410047220510f8021a20072005490d0f2002200720056b220436021c2002200620056a22053602182007450d1120022d00280d1141002106200241286a2004412020044120491b22076a41004100412020076b2007411f4b1b10f7021a200241286a2005200710f8021a2002200420076b36021c2002200520076a3602182004411f4d0d10200241cc006a41026a220d200241286a41026a22052d00003a0000200220022f00283b014c200228002b2107200229002f21082002280037210c200229003b210a200228004321042002310047210b2005200d2d0000220d3a0000200241246a41026a220e200d3a0000200220022f014c220d3b01242002200d3b0128200241c8006a41026a220d200e2d00003a0000200220022f01243b01482005200d2d0000220d3a0000200241146a41026a200d3a0000200220022f014822053b0114200220053b01280c030b4108210c2009450d010b20022802182105200228021c21042002412b6a210f200241376a21102002413b6a2111200241c3006a21124100210d0340200241286a2004412020044120491b22076a41004100412020076b2007411f4b1b10f7021a200241286a2005200710f8021a2002200420076b220636021c2002200520076a22073602182004411f4d0d06200241cc006a41026a2204200241286a41026a22052d00003a0000200220022f00283b014c200f280000210e200241286a41076a290000210b201028000021132011290000211420122800002115200241286a411f6a2d00002116200520042d000022043a0000200241246a41026a221720043a0000200220022f014c22043b0124200220043b012820024200370328200241286a20072006410820064108491b220510f8021a2002200620056b220436021c2002200720056a2205360218200641074d0d0720022903282118200220172d00003a004a200220022f01243b0148200220022d004a3a002a200220022f01483b01280240200a422088a7200aa72207470d00200741016a22062007490d0620074101742217200620062017491bad221942287e221a422088a70d06201aa722064100480d06024002402007450d00200610002217450d0c2017200c2006200741286c2207200720064b1b10f8022107200c10012007210c0c010b20061000220c450d0b0b200a42808080807083201984210a0b200c200a422088a741286c6a220720022f01283b010020022d002a210620072018370320200720163a001f2007201536001b200720143700132007201336000f2007200b3700072007200e360003200741026a20063a0000200a4280808080107c210a200d41016a220d2009490d000b0b200c450d0641022106200241146a41026a200241286a41026a2d00003a0000200220022f00283b01140b200241286a41026a2205200241146a41026a2d00003a0000200220022f01143b0128200020063a0000200041206a200b3700002000411c6a2004360000200041146a200a370000200041106a200c360000200041086a2008370000200041046a2007360000200020022f01283b0001200041036a20052d00003a00002003450d010b2003417f6a4102490d0f024020030d00200141086a280200450d10200141046a2802001001200241d0006a24000f0b200141086a280200450d0f200141046a2802001001200241d0006a24000f0b41010d0d0c0e0b1018000b200241286a41026a200241cc006a41026a2d00003a0000200220022f004c3b01280b200aa7450d00200c10010b41a79ec100411e1042000b200641081019000b20062004107a000b102c000b20042007107a000b20042007107a000b20052007107a000b200241286a41026a200241cc006a41026a2d00003a0000200220022f004c3b01280b200241286a41026a200241c8006a41026a2d00003a0000200220022f00483b012841a79ec100411e1042000b200741081019000b200141086a280200450d00200141046a2802001001200241d0006a24000f0b200241d0006a24000bd806010a7f230041106b22022400200241003602082002420137030020012802002103200128020822012002101b0240024002400240024002402001450d00200320014105746a210403402003280200200341086a2802002002108e012003410c6a280200200341146a2802002002108e01200241086a2205280200210120022802042106024002400240024002400240024002400240024002400240024002400240200341186a2802004101470d0020062001470d01200141016a22062001490d1120014101742207200620062007491b22064100480d112001450d0320022802002107200610002208450d122008200720062001200120064b1b10f8021a200710010c040b20062001470d01200141016a22062001490d1020014101742207200620062007491b22064100480d102001450d0520022802002107200610002208450d122008200720062001200120064b1b10f8021a200710010c060b200228020021080c030b200228020021080c050b200610002208450d0e0b20022006360204200220083602000b2005200141016a2207360200200820016a41023a00002003411c6a28020021090240200620076b41034b0d00200741046a220a2007490d0c2006410174220b200a200a200b491b220b4100480d0c200b1000210a2006450d04200a450d0f200a2008200b20062006200b4b1b10f8021a200810010c050b2008210a0c050b200610002208450d0c0b20022006360204200220083602000b2005200141016a2207360200200820016a41013a00002003411c6a28020021090240200620076b41044f0d00200741046a220a2007490d0920064101742201200a200a2001491b220b4100480d09200b100021012006450d042001450d0d20012008200b20062006200b4b1b10f8021a200810010c050b200141056a210a200821010c050b200a450d0a0b2002200b3602042002200a3602000b2005200141056a360200200a20076a2009360000200341206a22032004470d030c040b2001450d080b2002200b360204200220013602000b2005200a360200200120076a2009360000200341206a22032004470d000b0b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1018000b200641011019000b200641011019000b200b41011019000b200b41011019000bcb0401057f230041106b22022400200241003a0008200241086a2001280200220320012802042204410047220510f8021a024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002400240024002400240024002402004450d0020022d0008417f6a220441034b0d04024020040e0400030204000b20024100360208200241086a20052006410420064104491b220410f8021a200141046a200620046b3602002001200520046a360200200641034d0d052000200228020836020420004100360200200241106a24000f0b20004104360200200241106a24000f0b20024100360208200241086a20052006410420064104491b220410f8021a200141046a200620046b3602002001200520046a360200200641034d0d042000200228020836020420004102360200200241106a24000f0b20024200370308200241086a20052006410820064108491b220410f8021a200141046a200620046b3602002001200520046a360200200641074d0d04200041086a200229030837030020004101360200200241106a24000f0b20024200370308200241086a20052006410820064108491b220410f8021a200141046a200620046b3602002001200520046a360200200641074d0d04200041086a200229030837030020004103360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20052004107a000b6e01017f024002400240200028020022024101460d0020024102460d0120024103470d02200141041024200041086a290300200110230f0b200141021024200041086a290300200110230f0b200141031024200028020420011089010f0b200141011024200028020420011089010b3400200041efa3c10036020420004100360200200041146a4103360200200041106a41ecf6c200360200200041086a42093702000b4b00200041ddf5c10036020420004100360200200041206a41013602002000411c6a41b8f8c200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b340020004185a9c10036020420004100360200200041146a4108360200200041106a41c0f9c200360200200041086a420d3702000b4b00200041ddf5c10036020420004100360200200041206a41053602002000411c6a41a8fdc200360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b1300200041023602042000419080c3003602000b970302057f017e230041c0006b220224000240411c10002203450d002002421c37023420022003360230200241306a41a0a3c100411c1025200241086a220320022802383602002002200229033037030020012002101e200328020021042002280204210520022802002101200241306a41086a220642003703002002420037033020012004200241306a100220032006290300370300200220022903303703004100210302400240200241104188f0c100410041001004417f460d002002200236021020024110360214200242003703302002410020024110200241306a41084100100422032003417f461b2203410820034108491b360218200341074d0d0120022903302107200241306a200241106a103620022802302203450d0120022002290234370320200241306a41086a2204200241206a41086a28020036020020022002290320370330200020073703002000200229033037020c200041146a20042802003602000b2000200336020802402005450d00200110010b200241c0006a24000f0b41eac4c10041331042000b411c41011019000bae0603077f017e017f230041d0006b22012400200141286a41086a22024200370300200142003703284190f3c100410d200141286a1002200141086a41086a2002290300370300200120012903283703080240024002400240200141086a41104188f0c100410041001004417f460d002001421037021c2001200141086a360218200141286a200141186a10ea0220012802282203450d02200141306a2802002104200128022c21050c010b410021030b200141286a41206a2206200041206a290300370300200141286a41186a2207200041186a290300370300200141286a41106a200041106a2903003703002002200041086a290300370300200120002903003703282003410820031b210202400240024002402004410020031b22002005410020031b2205470d00200041016a22032000490d0320004101742204200320032004491b2205ad42287e2208422088a70d032008a722034100480d032000450d01200310002204450d05200420022003200041286c2209200920034b1b10f8021a200210010c020b200221040c010b200310002204450d030b2004200041286c6a22032001290328370300200341206a2006290300370300200341186a2007290300370300200341106a200141286a41106a290300370300200341086a200141286a41086a22032903003703002001200041016a22063602202001200536021c200120043602182001410036023020014201370328200141286a200141186a101f200128022c2107200128023021092001280228210220034200370300200142003703284190f3c100410d200141286a1002200141086a41086a200329030037030020012001290328370308200141086a411020022009100302402007450d00200210010b02402006450d00200041286c41286a2103200421000340024020002d00002202450d00024020024101470d00200041086a280200450d01200041046a2802001001200041286a2100200341586a22030d020c030b200041146a280200450d00200041106a28020010010b200041286a2100200341586a22030d000b0b02402005450d00200410010b200141d0006a24000f0b1018000b41eac4c10041331042000b200341081019000b930504057f017e017f047e230041206b22032400024002400240411810002204450d002003421837021420032004360210200341106a4193f1c10041181025200341086a220420032802183602002003200329031037030020002003101e20042802002105200328020421062003280200210742002108200341106a41086a220942003703002003420037031020072005200341106a1002200420092903003703002003200329031037030002400240200341104188f0c100410041001004417f460d00200342003703182003420037031020034110200341106a4110410010042204417f460d012004410f4d0d01200341186a290300210a200329031021082006450d040c030b4200210a20060d020c030b41eac4c10041331042000b411841011019000b200710010b0240411410002204450d002003421437021420032004360210200341106a41eeefc10041141025200341086a220420032802183602002003200329031037030020002003101e2004280200210520032802042106200328020021074200210b200341106a41086a220942003703002003420037031020072005200341106a10022004200929030037030020032003290310370300024002400240200341104188f0c100410041001004417f460d00200342003703182003420037031020034110200341106a4110410010042204417f460d022004410f4d0d02200341186a290300210c2003290310210b0c010b4200210c0b2002200a2008200156200a200256200a2002511b22041b210d2001200820041b210202402006450d00200710010b2000200b20027c2201200c200d7c2001200b54ad7c10aa012000200820027d200a200d7d2008200254ad7d10d302200341206a24000f0b41eac4c10041331042000b411441011019000bccaf0109027f027e057f017e0e7f017e027f027e147f230041f0026b2201240020014180016a41086a22024200370300200142003703800141b5c6c100411420014180016a100220014198026a41086a20022903003703002001200129038001370398020240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d0220012903800122034200510d044200210420002003824200520d1f0c010b42002104200042e807824200520d1e0b20014180016a41086a22022004370300200120043703800141c9c6c100411420014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460d1d200141003602800120014198026a411020014180016a41044100100441016a41044d0d012001280280012205450d1d20014180016a109e0220014180016a41086a22062802002107200128028401210820012802800121024200210320064200370300200142003703800141f2c6c100411420014180016a100220014198026a41086a220920062903003703002001200129038001370398022007410020021b2107024020014198026a41104188f0c100410041001004417f460d00200120014198026a3602c802200141103602cc0220014200370380012001410020014198026a411020014180016a41084100100422062006417f461b2206410820064108491b22093602d002200641074d0d0520012903800121032001410036028001200141d0026a410020014198026a411020014180016a41042009100422062006417f461b2206410420064104491b20096a360200200641034d0d05200128028001210620014180016a200141c8026a10362001280280012209450d052006200129028401220a422088a76b20076a210b0240200aa7450d00200910010b2002410820021b2109200b2005490d070c060b20064200370300200142003703800141f0f1c100410d20014180016a100220092006290300370300200120012903800137039802024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d0420012903800121030b410021062002410820021b2109200720054f0d050c060b41eac4c10041331042000b41eac4c10041331042000b41f08ac300104f000b41eac4c10041331042000b41eac4c10041331042000b0240200620054f0d002007200620056b6a220620074f0d052009200641286c6a29032021030c010b20014180016a41086a2206420037030020014200370380014186c7c100411420014180016a100220014198026a41086a2006290300370300200120012903800137039802024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d0220012903800120037c21030c010b420520037c21030b20014180016a41086a22064200370300200142003703800141b5c6c100411420014180016a100220014198026a41086a200629030037030020012001290380013703980202400240024002400240024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d02200129038001220a4200520d0141988bc300104f000b42e807210a0b2003200a7c427f7c22032003200a827d210302402002450d002008450d00200910010b20032000520d1a20014180016a109e0220014180016a41086a22022802002106200128028401210c200128028001210d4200210320024200370300200142003703800141c9c6c100411420014180016a100220014198026a41086a220520022903003703002001200129038001370398024100210e024020014198026a41104188f0c100410041001004417f460d00200141003602800120014198026a411020014180016a41044100100441016a41044d0d04200128028001210e0b20024200370300200142003703800141f0f1c100410d20014180016a100220052002290300370300200120012903800137039802024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d0220012903800121030b200d4108200d1b210f0240024020064100200d1b221041286c450d00200f41206a2903002003520d00200141f0016a41186a2206200f41186a290000370300200141f0016a41106a2205200f41106a290000370300200141f0016a41086a2207200f41086a2900003703002001200f2900003703f001412010002211450d0d200f41286a2102201120012903f001370000201141186a2006290300370000201141106a2005290300370000201141086a2007290300370000412021074101211241012105201041286c41586a2209450d010340200241206a2903002003520d02200141c8026a41186a200241186a2206290000370300200141c8026a41106a200241106a2208290000370300200141c8026a41086a200241086a220b290000370300200120022900003703c80220014180016a41186a2213200629000037030020014180016a41106a2214200829000037030020014180016a41086a2208200b2900003703002001200229000037038001024020052012470d00201241016a22062012490d162012410174220b20062006200b491b220bad420586220a422088a70d17200aa722064100480d1802402012450d00200610002215450d0b20152011200620124105742212201220064b1b10f80221062011100120062111200b21120c010b200b2112200610002211450d0a0b200241286a2102201120076a2206200129038001370000200641186a2013290300370000200641106a2014290300370000200641086a2008290300370000200741206a2107200541016a2105200941586a22090d000c020b0b4101211141002105410021120b024002400240201020056b200e4f0d0020014180016a41086a220242003703002001420037038001419ac7c100411c20014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460d01200142003703800120014198026a411020014180016a41084100100441016a41084d0d08200129038001210a0c020b2012450d1a20111001200d0d1b0c1c0b42e807210a0b20014100360288012001420137038001410810002202450d082001428880808080013702840120012002360280012002200a20037c370000411010002206450d09200620022900003700002002100120014290808080c001370284012006200520106b200e6a220e3600082001200636028001200520014180016a101b024002402005450d002005410574210b410020014180016a41086a221328020022066b210720012802840121052011210203400240024002400240200520076a41204f0d00200641206a22092006490d1c20054101742208200920092008491b22084100480d1d2005450d012001280280012114200810002209450d092009201420082005200520084b1b10f8021a201410010c020b20012802800121090c020b200810002209450d070b20012008360284012001200936028001200821050b2013200641206a2208360200200920066a220641086a200241086a290000370000200641106a200241106a290000370000200641186a200241186a29000037000020062002290000370000200741606a210720082106200241206a2102200b41606a220b0d000c020b0b20014188016a2802002108200128028401210520012802800121090b20014180016a41086a22024200370300200142003703800141f2c6c100411420014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a411020092008100302402005450d00200910010b02402012450d00201110010b4108211120014180016a41086a22024200370300200142003703800141b6c7c100410e20014180016a100220014198026a41086a2002290300370300200120012903800137039802410021140240024020014198026a41104188f0c100410041001004417f460d00200142103702cc02200120014198026a3602c80220014180016a200141c8026a10362001280280012213450d0e20014188016a280200210220012802840121100c010b410021130b200141106a2013410120131b221520152002410020131b4105746a102e024020012802142207200128021022066b4105762202450d002002410474220510002211450d0e200221140b02400240024020062007460d0041002105200141086a21092011210203402001200610b001200129030021032002200929030037030820022003370300200541016a2105200241106a21022007200641206a2206470d000b2005413f4d0d012005418080014f0d0241022102410210002209450d11200920054102744101723b00000c1a0b410021050b41012102410110002209450d0b200920054102743a00000c180b024020054180808080044f0d0041042102410410002209450d10200920054102744102723600000c180b410110002206450d10200641033a000041052102410510002209450d11200920062d00003a000020061001200920053600010c170b41eac4c10041331042000b41eac4c10041331042000b200841011019000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200641011019000b41888bc30020062007104e000b410841011019000b411041011019000b410141011019000b412041011019000b41eac4c10041331042000b200541081019000b410241011019000b410441011019000b410141011019000b410541011019000b410921220c160b410921220c150b410921220c140b410921220c130b410921220c120b024002402011201120054104746a220b460d00410020026b210720022105201121060340200641086a29030021032006290300210a0240200520076a410f4b0d00200241106a22082002490d0f20054101742212200820082012491b22084100480d10024002402005450d00200810002212450d092012200920082005200520084b1b10f802210520091001200521090c010b200810002209450d080b200821050b200920026a220820033700082008200a370000200741706a2107200241106a2102200b200641106a2206470d000c020b0b410121050b20014180016a41086a22064200370300200142003703800141c4c7c100411820014180016a100220014198026a41086a200629030037030020012001290380013703980220014198026a411020092002100302402005450d00200910010b02402014450d00201110010b20014180016a41086a22024200370300200142003703800141dcc7c100411220014180016a100220014198026a41086a220620022903003703002001200129038001370398020240024020014198026a41104188f0c100410041001004417f460d00200141003602800120014198026a411020014180016a41044100100441016a41044d0d0920012802800121020c010b410221020b200141c0026a4200370300200141b8026a4200370300200141b0026a420037030020014198026a41106a42003703002006420037030020014200370398022002200e6a2205ad42307e2203422088a70d0d2003a72202417f4c0d0e024002402002450d00200210002212450d0a201221020c010b41082112410821020b20014180016a41286a220720014198026a41286a29030037030020014180016a41206a220920014198026a41206a29030037030020014180016a41186a220820014198026a41186a29030037030020014180016a41106a220b20014198026a41106a29030037030020014180016a41086a20014198026a41086a29030037030020012001290398023703800102400240024020054102490d004101210603402002200129038001370300200241286a2007290300370300200241206a2009290300370300200241186a2008290300370300200241106a200b290300370300200241086a20014180016a41086a290300370300200241306a2102200641016a22062005490d000b2006417f6a21060c010b410021062005450d010b2002200129038001370300200241286a20014180016a41286a290300370300200241206a20014180016a41206a290300370300200241186a20014180016a41186a290300370300200241106a20014180016a41106a290300370300200241086a20014180016a41086a290300370300200641016a21060b20012006360288012001200536028401200120123602800120014180016a10a20202402005450d00201210010b20014188016a200e360200200141023a008401200141053a00800120014180016a10b4012013450d002010450d00201510010b200d450d010b200c450d00200f10010b20014180016a41086a22022004370300200120043703800141f2c6c100411420014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460d0d200120014198026a3602c802200141103602cc0220014200370380012001410020014198026a411020014180016a41084100100422022002417f461b2202410820024108491b22063602d0020240024002400240200241074d0d0020012903800121042001410036028001200141d0026a410020014198026a411020014180016a41042006100422022002417f461b22024104200241044922021b20066a36020020020d0020014180016a200141c8026a10362001280280012216450d00200128028401211720042000520d1020014180016a41086a22024200370300200142003703800141c4c7c100411820014180016a100220014198026a41086a2206200229030037030020012001290380013703980220014198026a4110100820064200370300200142003703980241f2c6c100411420014198026a10022002200629030037030020012001290398023703800102400240024020014180016a41104188f0c100410041001004417f460d00200120014180016a3602f001200141103602f40120014200370398022001410020014180016a411020014198026a41084100100422022002417f461b2202410820024108491b22063602f801200241074d0d0620012903980221042001410036029802200141f8016a410020014180016a411020014198026a41042006100422022002417f461b2202410420024104491b20066a360200200241034d0d06200128029802210220014198026a200141f0016a10362001280298022218450d06200120023602d002200120043703c802200129029c02211920012802d002211a4108211b4200211c20014198026a41086a22024200370300200142003703980241f2c6c100411420014198026a100220014180016a41086a2206200229030037030020012001290398023703800120014180016a4110100820024200370300200142003703980241eec7c100411320014198026a100220062002290300370300200120012903980237038001024020014180016a41104188f0c100410041001004417f460d00200142103702cc02200120014180016a3602c80220014198026a200141c8026a103e200128029802221b450d0a200129029c02211c20014198026a41086a22024200370300200142003703980241eec7c100411320014198026a100220014180016a41086a200229030037030020012001290398023703800120014180016a411010080b20014180016a41086a22024200370300200142003703800141f0f1c100410d20014180016a100220014198026a41086a2206200229030037030020012001290380013703980242002104024020014198026a41104188f0c100410041001004417f460d00200142003703800120014198026a411020014180016a41084100100441016a41084d0d0520012903800121040b2002420037030020014200370380014186c7c100411420014180016a10022006200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460d01200142003703800120014198026a411020014180016a41084100100441016a41084d0d0520012903800121000c020b02402017450d00201610010b419ac9c100410f100641e5c8c10041351006200141f0026a24000f0b420521000b2001200020047c3703184200210a20014180016a41086a22024200370300200142003703800141d0c8c100411520014180016a100220014198026a41086a20022903003703002001200129038001370398020240024020014198026a41104188f0c100410041001004417f460d002001420037038801200142003703800120014198026a411020014180016a4110410010042202417f460d072002410f4d0d0720014188016a290300210a200129038001211d0c010b4209211d0b201b201c422088a7221e41306c6a211102400240024002400240201a450d00201a417f6a210741002106201b2011460d01201b201e41306c6a220241506a2211290300200241586a29030084500d03200141b0026a200241786a290000370300200141a8026a200241706a290000370300200141a0026a200241686a2900003703002001200241606a29000037039802410121060c020b4100211341002107410021060c030b201b21110b410021130c010b410121130b20014189016a20014198026a41086a29030037000020014191016a20014198026a41106a29030037000020014199016a20014198026a41186a290300370000200120063a0080012001200129039802370081014101211f20014180016a410172210202402006450d002002201d200a10e102200141f0016a41186a200241186a290000370300200141f0016a41106a200241106a290000370300200141f0016a41086a200241086a290000370300200120022900003703f00141201000221f450d08201f20012903f001370000201f41186a200141f0016a41186a290300370000201f41106a200141f0016a41106a290300370000201f41086a200141f0016a41086a29030037000020014180016a410172210241202105410121204101212120070d0c0c0b0b200141f0016a41186a200241186a290000370300200141f0016a41106a200241106a290000370300200141f0016a41086a200241086a290000370300200120022900003703f0014100212141002120410f21220c120b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b41eac4c10041331042000b200841011019000b41eac4c10041331042000b41eac4c10041331042000b412041011019000b41eac4c10041331042000b200241081019000b410521220c070b410021220c060b410921220c050b410921220c040b412721220c030b412721220c020b41d60021220c010b41d80021220b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020220ead0209101100080f01020393020405069a02071213141517181d1e1f2021253738393a3ba701a801a901aa01ab01ad01ae01a002af01b001b301b701b801b901ba01bb01bc01bd01be01c201d401d501d601d701d801d901da01db01dc01dd01de01ec01ed01ee01ef01f401f501f601f701f8018002810283028402850286028702880289028b028c028d028e028f02900291029202a1028a02f901fa01fb01fc01fd01ff019b02fe018202e801e901ea01eb01f001df01e001f101e101e201f201e301e401f301e501e601e7019c02c301c501c601c701c801d301c901ca01cb01cc01cd01ab02ce01cf01d001d101d201bf01c001c101c401b401b501b601b101b201a902ac01262728292a3c3d3e3f404151525354555762636768696a608401a201a301a401a501a601850186018b018e018f0196029001970291019201930199019f01a001a1019a019b019c019d0194019e019501960197019801990298028c018d01870158880189018a017c7d7e7f800181018301a30282016b6c6d6e797b7a6f70777871729402737495027576a602a502a702616465665a5b5c5d5e5fa40259ac0256424344455046474e4f48499d024a4b9e024c4d9f022b2c362d2e2f3031323335a20234aa02191a1b1c242322a802160a0b0c0e0d0d0b20014180016a41186a2212200929030037030020014180016a41106a2209200829030037030020014180016a41086a2208200b290300370300200120012903c8023703800120212020470db502410621220c9d040b202041016a22062020490db502410721220c9c040b2020410174220b20062006200b491b220bad4205862204422088a70db502410821220c9b040b2004a722064100480db702410a21220c9a040b2020450dbe02410b21220c99040b200610002214450dbe02410c21220c98040b2014201f20062020410574220d200d20064b1b10f8022106201f10012006211f200b21200cad020b200b212020061000221f450dad02410421220c96040b201f20056a2206200129038001370000200641186a2012290300370000200641106a2009290300370000200641086a2008290300370000200541206a2105202141016a21212007450da402410021220c95040b2007417f6a2107201341ff01710da70241a80221220c94040b2011201b460d910441a90221220c93040b201141506a2209290300201141586a290300844200510d910441aa0221220c92040b201141606a2900002104201141686a2900002100201141706a290000210320014198026a41186a2206201141786a29000037030020014198026a41106a2208200337030020014198026a41086a220b200037030020012004370398022002200129039802370000200241086a200b290300370000200241106a2008290300370000200241186a200629030037000041012106200141013a0080012002201d200a10e10241002113200921110ca3020b41002113201b21110ca0020b41012113200921110ca0020b41002107410121220c8e040b2002200129039802370000200241086a20014198026a41086a290300370000200241106a20014198026a41106a290300370000200241186a20014198026a41186a29030037000041002106200141003a008001410221220c8d040b200141c8026a41186a2209200241186a290000370300200141c8026a41106a2208200241106a290000370300200141c8026a41086a220b200241086a290000370300200120022900003703c80220060da1020ca0020b20014180016a109e024100212320012802840121062019422088a7221220014180016a41086a280200410020012802800122021b221341286c220541286e2207200720124b1b2224450db202411021220c8b040b202441057422074100480da802411121220c8a040b200710002225450db102411221220c89040b2006410020021b21142002410820021b221120056a210b20120db2020cb1020b41012125410021242006410020021b21142002410820021b221120056a210b2012450db202411321220c87040b41002123201121022012210520252106411421220c86040b200b20026b419f014d0db302419f0221220c85040b20014180016a41186a200241186a220729000037030020014180016a41106a200241106a220929000037030020014180016a41086a200241086a22082900003703002001200229000037038001200829000021042009290000210020022900002103200641186a2007290000370000200641106a2000370000200641086a20043700002006200337000020054101460dff0341a00221220c84040b200241306a2900002104200241386a290000210020022900282103200641386a200241c0006a290000370000200641306a2000370000200641286a20043700002006200337002020054102460dff0341a10221220c83040b200241d8006a2900002104200241e0006a290000210020022900502103200641d8006a200241e8006a290000370000200641d0006a2000370000200641c8006a20043700002006200337004020054103460dff0341a20221220c82040b20024180016a290000210420024188016a290000210020022900782103200641f8006a20024190016a290000370000200641f0006a2000370000200641e8006a200437000020062003370060202341046a212320064180016a2106200241a0016a21022005417c6a22050dae020cad020b200b2002460daf02411621220c80040b2011201341286c6a210d41012107411721220cff030b20014180016a41186a200241186a220929000037030020014180016a41106a200241106a220829000037030020014180016a41086a200241086a22132900003703002001200229000037038001201329000021042008290000210020022900002103200641186a2009290000370000200641106a2000370000200641086a200437000020062003370000200520072209460daf02411821220cfe030b200941016a2107200641206a2106200d200241286a2202470dad02411921220cfd030b202320096a21230cae020b202341017221230caf020b202341027221230cad020b20234103722123411a21220cf9030b2001201f3602840220014188026a2202201f20214105746a360200200141003a00900220012012360280022001200b3602fc01200120113602f801200120143602f401200120113602f0012001418c026a200141186a36020020014180016a200141f0016a10472001290380014201520dad0241920121220cf8030b417f417f4100200141fc016a280200200141f0016a41086a2802006b41286d220620014180026a2802006b2205200520064b1b220620022802002001280284026b4105766a220220022006491b220241016a220620062002491b2226ad42287e2204422088a70db90241930121220cf7030b2004a72202417f4c0db90241940121220cf6030b410821272002450d900341950121220cf5030b200210002227450d900341960121220cf4030b202720014180016a41086a2202290300370300202741206a200241206a290300370300202741186a200241186a290300370300202741106a200241106a290300370300202741086a200241086a290300370300200141c8026a41206a200141f0016a41206a280200360200200141c8026a41186a2211200141f0016a41186a290300370300200141c8026a41106a2213200141f0016a41106a290300370300200141c8026a41086a200141f0016a41086a290300370300200120012903f0013703c80220014180016a200141c8026a10472001290380014201520d900341910221220cf3030b20014180016a41086a2102200141d4026a2114200141dc026a210d412821054101212841920221220cf2030b20014198026a41206a2207200241206a29030037030020014198026a41186a2209200241186a29030037030020014198026a41106a2208200241106a29030037030020014198026a41086a220b200241086a290300370300200120022903003703980220282026470de60341940221220cf1030b417f417f41002014280200200141c8026a41086a2802006b41286d220620132802006b2212201220064b1b22062011280200200d2802006b4105766a221220122006491b220641016a221220122006491b2206450de60341950221220cf0030b202620066a22062026490d8e0241960221220cef030b20264101742212200620062012491b2212ad42287e2204422088a70d8e0241970221220cee030b2004a722064100480d8e0241980221220ced030b2026450de30341990221220cec030b20061000220f450de303419a0221220ceb030b200f20272006202641286c220e200e20064b1b10f802210620271001200621270ce3030b200610002227450de303419b0221220ce9030b2012212641930221220ce8030b202720056a2206200129039802370300200641206a2007290300370300200641186a2009290300370300200641106a2008290300370300200641086a200b290300370300200541286a2105202841016a212820014180016a200141c8026a10472001290380014201510d85030c86030b200141f8016a22062802002202200141fc016a2802002205460d9c02411c21220ce6030b20062002200520026b41586a41286e41286c6a41286a360200411d21220ce5030b20012802f401450d9b02411e21220ce4030b20012802f0011001411f21220ce3030b4100212641082127410021280c9a020b4101212841980121220ce1030b200141d0026a22062802002202200141d4026a2802002205460d800341990121220ce0030b20062002200520026b41586a41286e41286c6a41286a360200419a0121220cdf030b20012802cc02450dff02419b0121220cde030b20012802c8021001419c0121220cdd030b202841144b0dfe0241ff0121220cdc030b202841014d0d940241800221220cdb030b2028417f6a210941810221220cda030b202820092202417f6a2209490dc40341820221220cd9030b202820096b22074102490dc40341840221220cd8030b2027200241286c6a220b41206a22022903002027200941286c6a220841206a220629030022045a0dc40341850221220cd7030b20014180016a41186a2211200841186a220529030037030020014180016a41106a2213200841106a221229030037030020014180016a41086a2214200841086a220d29030037030020012008290300370380012008200b290300370300200d200b41086a2903003703002012200b41106a2903003703002005200b41186a2903003703002006200229030037030020074103490dc50341880221220cd6030b410321054102210641890221220cd5030b200620074f0dc703418b0221220cd4030b2008200641286c6a220241206a221229030020045a0dc103418c0221220cd3030b2006417f6a220620074f0dc603418e0221220cd2030b2008200641286c6a22062002290300370300200641206a2012290300370300200641186a200241186a290300370300200641106a200241106a290300370300200641086a200241086a290300370300200520074f0dc303418f0221220cd1030b20052106200541016a220b2005492112200b21052002210b2012450dc1030cc0030b200b210241870221220ccf030b2002200129038001370300200241186a2011290300370300200241106a2013290300370300200241086a20142903003703002002200437032041830221220cce030b20090d88020c87020b20284101762229ad42287e2204422088a70d9002419e0121220ccc030b2004a72202417f4c0d9002419f0121220ccb030b2002450ded0241a00121220cca030b20021000222a450ded0241a10121220cc9030b202a210b0ced020b4108212a4108210b41a20121220cc7030b202741586a212b202741a87f6a212c4104210d4100212d4100210c202821100cec020b2013210c20100dee020ced020b4100210741f50121220cc4030b20112007490dab0341f60121220cc3030b201120284b0da60341f70121220cc2030b201120076b22054101762209450daa0341f80121220cc1030b202b20086a21022027200741286c6a210641f90121220cc0030b20014180016a41206a2208200641206a221229030037030020014180016a41186a2213200641186a221429030037030020014180016a41106a220f200641106a220e29030037030020014180016a41086a2215200641086a22102903003703002001200629030037038001200241086a222e2903002104200241106a222f2903002100200241186a223029030021032002290300210a2012200241206a223129030037030020142003370300200e2000370300201020043703002006200a3703002031200829030037030020302013290300370300202f200f290300370300202e20152903003703002002200129038001370300200241586a2102200641286a21062009417f6a22090da90341fa0121220cbf030b20070dec0241a90121220cbe030b20072110200c202d460df1020cf2020b20112105200c202d460dee020cef020b2010211141002110410121052011417f6a2207450de50241a40121220cbb030b2027200741286c6a41206a2903002027201141286c22026a41506a29030022045a0de50241f20121220cba030b202c201141056c41037422086a210241f30121220cb9030b20074101460d9f0341f40121220cb8030b2007417f6a2107200420022903002200542106200241586a21022000210420060d9c030c9d030b2011417e6a2107202c20026a2106410021104100210241a60121220cb6030b20072002460de20241a70121220cb5030b200241016a21022004200629030022005a2105200641586a21062000210420050de00241a80121220cb4030b200241016a2105201120026b417f6a2207450de20241db0121220cb3030b200541094b0de20241dc0121220cb2030b201120284b0d880341dd0121220cb1030b20112007417f6a2210490d880341de0121220cb0030b201120106b22054102490d880341e20121220caf030b2027200741286c6a220841206a22022903002027201041286c6a220941206a220629030022045a0d880341e30121220cae030b20014180016a41186a2213200941186a220729030037030020014180016a41106a2214200941106a221229030037030020014180016a41086a220f200941086a220e290300370300200120092903003703800120092008290300370300200e200841086a2903003703002012200841106a2903003703002007200841186a2903003703002006200229030037030020054103490d8a0341e60121220cad030b410321074102210641e70121220cac030b200620054f0d8c0341e90121220cab030b2009200641286c6a220241206a221229030020045a0d860341ea0121220caa030b2006417f6a220620054f0d8b0341ec0121220ca9030b2009200641286c6a22062002290300370300200641206a2012290300370300200641186a200241186a290300370300200641106a200241106a290300370300200641086a200241086a290300370300200720054f0d880341ed0121220ca8030b20072106200741016a2208200749211220082107200221082012450d86030c85030b2008210241e50121220ca6030b2002200129038001370300200241186a2013290300370300200241106a2014290300370300200241086a200f2903003703002002200437032041df0121220ca5030b2010450dff0241e10121220ca4030b201021072005410a490df90241e00121220ca3030b200c202d470dd30241d20121220ca2030b202d41016a2202202d490dc50141d30121220ca1030b202d4101742206200220022006491b2206ad4203862204422088a70dc30141d40121220ca0030b2004a722024100480dc10141d50121220c9f030b202d450df00241d60121220c9e030b200210002207450df00241d70121220c9d030b2007200d2002202d4103742209200920024b1b10f8022102200d10012002210d0cf0020b20021000220d450df00241d80121220c9b030b2006212d41aa0121220c9a030b200d200c4103746a2202200536020420022010360200200c41016a220c4102490dcf0241b00121220c99030b200d200c2213417f6a220c4103746a2202280200450dd10241b10121220c98030b200d20134103746a220941746a2802002207200228020422064d0dd10241cd0121220c97030b201341024d0de60241cf0121220c96030b200d2013417d6a22024103746a2802042205200620076a4d0de40241d00121220c95030b201341034d0de50241d10121220c94030b200941646a280200200520076a4d0de1020ce0020b20134103490dcd0241cb0121220c92030b20022802042106200d2013417d6a22024103746a280204210541cc0121220c91030b20052006490dcc0241b30121220c90030b2013417e6a210241b40121220c8f030b2013200241016a222e4d0dcb0241b60121220c8e030b201320024d0dcb0241b80121220c8d030b200d20024103746a220f280204222f200f2802006a2202200d202e4103746a220e2802002215490dcb0241b90121220c8c030b200220284b0dcb0241ba0121220c8b030b200f41046a21302027201541286c6a2211200e280204221441286c22066a2109200241286c2105200220156b220820146b220220144f0dcb0241c30121220c8a030b202a2009200241286c220610f8021a200b20066a210720144101480dd40241c50121220c89030b20024101480dd40241c60121220c88030b202b20056a21052009210241c70121220c87030b2005200241586a2208200741586a2212200741786a290300200241786a2903005422091b2206290300370300200541206a200641206a290300370300200541186a200641186a290300370300200541106a200641106a290300370300200541086a200641086a2903003703002007201220091b210720112008200220091b22024f0dca0241c80121220c86030b200541586a2105200b2106200b2007490dcd020cce020b202a2011200610f8021a200b20066a210720144101480dc60241bf0121220c84030b200820144c0dc60241c00121220c83030b202720056a2112200b21062011210241c10121220c82030b200220092006200941206a290300200641206a2903005422081b2205290300370300200241206a200541206a290300370300200241186a200541186a290300370300200241106a200541106a290300370300200241086a200541086a2903003703002006200641286a20081b2106200241286a2102200941286a200920081b220920124f0dcb0241c20121220c81030b200720064b0dc6020cc7020b200921020cc4020b2011210241bd0121220cfe020b200b210641be0121220cfd020b20022006200720066b220520054128706b10f8021a2030202f20146a360200200f2015360200200e200e41086a2013202e417f736a41037410f9021a200c41014b0db30241ab0121220cfc020b20100da20241ac0121220cfb020b202d450db20241ad0121220cfa020b200d100141ae0121220cf9020b2029450db40141af0121220cf8020b202a1001412021220cf7020b20012028360288012001202636028401200120273602800120014180016a10a1022026450db301412121220cf6020b20271001412221220cf5020b20014180016a41086a2202420037030020014200370380014197c8c100411220014180016a100220014198026a41086a2206200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460db201412321220cf4020b200142103702cc02200120014198026a3602c80220014180016a200141c8026a1036200128028001220e450db201412421220cf3020b20014188016a280200210220012802840121300cb2010b4100210e412521220cf1020b200141b0026a420037030020014198026a41106a420037030020064200370300200142003703980220024100200e1b2212ad2204421b88a70db101412621220cf0020b2004420586a72202417f4c0db501412821220cef020b2002450db501412921220cee020b2002100022130db501418e0121220ced020b200241011019000b41012113412a21220ceb020b20014180016a41186a220520014198026a41186a29030037030020014180016a41106a220720014198026a41106a29030037030020014180016a41086a220920014198026a41086a29030037030020012001290398023703800120124102490db301418b0121220cea020b2013210241012106418c0121220ce9020b2002200129038001370000200241186a2005290300370000200241106a2007290300370000200241086a2009290300370000200241206a2102200641016a22062012490d8202418d0121220ce8020b2006417f6a210d0cb2010b4100210d201321022012450db001412c21220ce6020b2002200129038001370000200241186a20014180016a41186a290300370000200241106a20014180016a41106a290300370000200241086a20014180016a41086a290300370000200d41016a210d412d21220ce5020b201b201e41306c6a2102201a450db001412e21220ce4020b2002201b460db001412f21220ce3020b201e41306c2106201a417f732108200141f0016a41186a2105200141f0016a41106a2107200141f0016a41086a2109413021220ce2020b201b20066a220241586a2903002104200241506a29030021002005200241786a2903003703002007200241706a2903003703002009200241686a2903003703002001200241606a2903003703f00120002004844200510db101413121220ce1020b20014198026a41186a220b200529030037030020014198026a41106a2211200729030037030020014198026a41086a22142009290300370300200120012903f00137039802200141c8026a41186a220f200b290300370300200141c8026a41106a220b2011290300370300200141c8026a41086a2211201429030037030020012001290398023703c80220014180016a41186a200f29030037030020014180016a41106a200b29030037030020014180016a41086a2011290300370300200120012903c80237038001200841016a2208450db101413221220ce0020b200641506a22060dae010cad010b2002201b460db00141880121220cde020b20014198026a41086a2206200241686a220529030037030020014198026a41106a2209200241706a220829030037030020014198026a41186a220b200241786a22112903003703002001200241606a221429030037039802200241586a2903002104200241506a2207290300210020014180016a41186a201129030037030020014180016a41106a200829030037030020014180016a41086a20052903003703002001201429030037038001200141f0016a41186a2202200b290300370300200141f0016a41106a22052009290300370300200141f0016a41086a2209200629030037030020012001290398023703f0012000200484500df60141890121220cdd020b200141e0006a41186a2002290300370300200141e0006a41106a2005290300370300200141e0006a41086a2009290300370300200120012903f0013703604100212f41002127420150450de4010ce5010b4100212741012102201ca70db0010caf010b200141e0006a41186a20014180016a41186a290300370300200141e0006a41106a20014180016a41106a290300370300200141e0006a41086a20014180016a41086a2903003703002001200129038001370360200241506a21074100212f0ce0010b4101212f410021274200500de00141f70021220cd9020b4100212741f80021220cd8020b20072102202f211441f90021220cd7020b200141c0006a41186a2206200141e0006a41186a2210290300370300200141c0006a41106a2205200141e0006a41106a220c290300370300200141c0006a41086a2207200141e0006a41086a222e2903003703002001200129036037034020014198026a41186a2209200629030037030020014198026a41106a2208200529030037030020014198026a41086a220b20072903003703002001200129034037039802200141f0016a20014198026a10eb0220014180016a41186a2211200629030037030020014180016a41106a2206200529030037030020014180016a41086a22052007290300370300200120012903403703800120012802f0014101460de70141fa0021220cd6020b201441ff01710de70141fc0021220cd5020b201b2002460de70141fd0021220cd4020b200241586a2903002104200241506a220729030021002009200241786a22142903003703002008200241706a220f290300370300200b200241686a22152903003703002001200241606a220229030037039802201120142903003703002006200f290300370300200520152903003703002001200229030037038001200141f0016a41186a22022009290300370300200141f0016a41106a22062008290300370300200141f0016a41086a2205200b29030037030020012001290398023703f0012000200484500de90141fe0021220cd3020b20102002290300370300200c2006290300370300202e2005290300370300200120012903f001370360410021142007210242014200520de1010ce2010b4101212f410121142007210242004200520dde010cdf010b200141c8026a41086a220f2005290300370300200141c8026a41106a22152006290300370300200141c8026a41186a2228201129030037030020012001290380013703c802200141f0016a41086a22142802002107200141206a41186a22312028290300370300200141206a41106a22282015290300370300200141206a41086a2215200f290300370300200120012903c8023703202011203129030037030020062028290300370300200520152903003703002001200129032037038001200d20074d0de70141820121220cd0020b201320074105746a2207200129038001370000200741186a2011290300370000200741106a2006290300370000200741086a2005290300370000202741016a2127202f41ff01710de30141830121220ccf020b201b2002460de30141840121220cce020b200241586a2903002104200241506a220729030021002009200241786a220f2903003703002008200241706a2215290300370300200b200241686a222f2903003703002001200241606a2202290300370398022011200f290300370300200620152903003703002005202f2903003703002001200229030037038001200141f0016a41186a22022009290300370300200141f0016a41106a220620082903003703002014200b29030037030020012001290398023703f0012000200484500de50141850121220ccd020b20102002290300370300200c2006290300370300202e2014290300370300200120012903f0013703604100212f42014200520dd6010cd7010b4101212f42004200520dd70141fb0021220ccb020b41012102201ca7450d9d01413421220cca020b201b1001413521220cc9020b200e2002200e1b210f200d20122012200d4b1b2208450d9e01413621220cc8020b41002105200f210220132106413721220cc7020b20022006460d9e01413821220cc6020b20022006412010fa02450d9e01413921220cc5020b411610002207450d9e01413a21220cc4020b2001421637028401200120073602800120014180016a4181c8c1004116102520014198026a41086a220720014180016a41086a2209280200360200200120012903800137039802200220014198026a101e20072802002111200128029c022114200128029802210b200942003703002001420037038001200b201120014180016a10022007200929030037030020012001290380013703980220014198026a411010082014450d9e01413b21220cc3020b200b1001413c21220cc2020b200241206a2102200641206a2106200541016a22052008490d9801413d21220cc1020b20014198016a210620014190016a210520014188016a21072013200d4105746a22112102200d2109413e21220cc0020b200220136b41ff004d0d9d0141e90021220cbf020b2006420037030020054200370300200742003703002001420037038001200241606a220820014180016a460dbe0141ea0021220cbe020b200820014180016a412010fa020dbe0141ec0021220cbd020b2006420037030020054200370300200742003703002001420037038001200241406a220820014180016a460dbe0141ed0021220cbc020b200820014180016a412010fa020dbe0141ef0021220cbb020b2006420037030020054200370300200742003703002001420037038001200241a07f6a220820014180016a460dbe0141f00021220cba020b200820014180016a412010fa020dbe0141f20021220cb9020b20064200370300200542003703002007420037030020014200370380012009417c6a2109200241807f6a220220014180016a460d950141f30021220cb8020b200220014180016a412010fa02450d930141f40021220cb7020b41012107200941016a2202200d4f0d9a0141e40021220cb6020b200d210541e50021220cb5020b200220076a22062002490db30141e60021220cb4020b2005417f6a2105200621022006200d490db10141e70021220cb3020b201320054105746a21110c9e010b20132002460d900141c00021220cb1020b20014180016a41206a210520014198016a210720014190016a210820014188016a210b4101210641c10021220cb0020b2007420037030020084200370300200b4200370300200142003703800120052002460d910141c20021220caf020b200241606a20014180016a412010fa020d910141e80021220cae020b200641016a21062013200241606a2202470d8e010c8d010b410121072009417f6a41016a2202200d490d92010c93010b410121072009417e6a41016a2202200d490d93010c94010b410121072009417d6a41016a2202200d490d94010c95010b41012107200920066b41016a2202200d490d8e0141c40021220ca9020b200d210541c50021220ca8020b2001419c016a202336020020014180016a41186a202436020020014194016a202536020020014180016a41106a20213602002001418c016a202036020020014180016a41086a2202201f360200200141033a008401200141053a00800120014180016a10b40120014100360288012001420137038001200520014180016a101b2005450d940141c60021220ca7020b4100200228020022066b2109200128028001210820012802840121072013210241c70021220ca6020b20022102200720096a411f4b0d940141db0021220ca5020b200641206a22052006490d3f41dc0021220ca4020b2007410174220b20052005200b491b22054100480d3f41dd0021220ca3020b20051000210b2007450d9c0141de0021220ca2020b200b450d9c0141df0021220ca1020b200b200820052007200720054b1b10f8021a200810010c9d010b200b450d9b0141e00021220c9f020b200b21082005210741c80021220c9e020b200820066a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200941606a2109200641206a21062011200241206a2202470d8b0141c90021220c9d020b20014188016a2006360200200120073602840120012008360280010c8c010b200228020021062001280284012107200128028001210841ca0021220c9b020b20014180016a41086a2202420037030020014200370380014197c8c100411220014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a41102008200610032007450d8b0141cb0021220c9a020b2008100141cc0021220c99020b2012450d8a0141cd0021220c98020b2013100141ce0021220c97020b200120273602c80220014180016a41086a22024200370300200142003703800141a9c8c100411620014180016a100220014198026a41086a2206200229030037030020012001290380013703980220014198026a4110200141c8026a4104100320024200370300200142003703800141bfc8c100411120014180016a10022006200229030037030020012001290380013703980220014198026a41104188f0c100410041001004417f460d890141cf0021220c96020b200141003602800120014198026a411020014180016a41044100100441016a41044d0d890141d00021220c95020b20012802800141016a21020c89010b4101210241d10021220c93020b200120023602c80220014180016a41086a22024200370300200142003703800141bfc8c100411120014180016a100220014198026a41086a200229030037030020012001290380013703980220014198026a4110200141c8026a41041003200e450d880141d20021220c92020b2030450d880141d30021220c91020b200f100141d40021220c90020b2019a7450d870141d50021220c8f020b2018100141d60021220c8e020b2017450d860141d70021220c8d020b2016100141d80021220c8c020b200141f0026a24000f0b1018000b41d08ac30020062005104e000b41e08ac30020062005104e000b41c08ac300202e2013104e000b41c08ac30020022013104e000b20152002107a000b200220281076000b200641011019000b200541011019000b411641011019000b41d08ac30020062007104e000b41e08ac30020062007104e000b20092028107a000b102c000b41eac4c10041331042000b200641081019000b200241041019000b20072011107a000b20112007417f6a22104f0ddb0141ee0121220cf8010b20102011107a000b201120281076000b200741011019000b41eac4c10041331042000b200241081019000b41b08bc3002007200d104e000b200241081019000b410521220cf0010b410121220cef010b410121220cee010b410221220ced010b410121220cec010b410f21220ceb010b410321220cea010b410421220ce9010b410d21220ce8010b410421220ce7010b410921220ce6010b410921220ce5010b410921220ce4010b410921220ce3010b410921220ce2010b410921220ce1010b410921220ce0010b410921220cdf010b410921220cde010b410921220cdd010b410921220cdc010b410921220cdb010b410e21220cda010b410d21220cd9010b41a70221220cd8010b41a60221220cd7010b411a21220cd6010b411321220cd5010b411a21220cd4010b411a21220cd3010b411421220cd2010b411521220cd1010b411a21220cd0010b411721220ccf010b411921220cce010b411a21220ccd010b411a21220ccc010b411a21220ccb010b411b21220cca010b411d21220cc9010b411f21220cc8010b412021220cc7010b412021220cc6010b412021220cc5010b41810221220cc4010b412021220cc3010b412221220cc2010b41910121220cc1010b41900121220cc0010b412521220cbf010b412721220cbe010b412721220cbd010b412721220cbc010b412721220cbb010b412721220cba010b412721220cb9010b418f0121220cb8010b412a21220cb7010b412b21220cb6010b412d21220cb5010b412c21220cb4010b41870121220cb3010b413321220cb2010b413321220cb1010b413021220cb0010b413321220caf010b41f60021220cae010b413321220cad010b413521220cac010b413521220cab010b413421220caa010b413d21220ca9010b413721220ca8010b413c21220ca7010b413c21220ca6010b41f50021220ca5010b413c21220ca4010b413e21220ca3010b413e21220ca2010b413f21220ca1010b41c40021220ca0010b41c40021220c9f010b41c10021220c9e010b41e80021220c9d010b41c30021220c9c010b41c40021220c9b010b41e40021220c9a010b41e40021220c99010b41c40021220c98010b41e40021220c97010b41c40021220c96010b41e40021220c95010b41c40021220c94010b41c50021220c93010b41e30021220c92010b41c70021220c91010b41c80021220c90010b41ca0021220c8f010b41cc0021220c8e010b41ce0021220c8d010b41da0021220c8c010b41d90021220c8b010b41d10021220c8a010b41d40021220c89010b41d40021220c88010b41d60021220c87010b41d80021220c86010b41e20021220c85010b41e10021220c84010b41e10021220c83010b41e00021220c82010b41e50021220c81010b41e70021220c80010b41ec0021220c7f0b41eb0021220c7e0b41ef0021220c7d0b41ee0021220c7c0b41f20021220c7b0b41f10021220c7a0b41f70021220c790b41fb0021220c780b41f70021220c770b41fb0021220c760b41f80021220c750b41fb0021220c740b41f80021220c730b41f90021220c720b41fb0021220c710b41f90021220c700b41fb0021220c6f0b41800121220c6e0b41fb0021220c6d0b41fb0021220c6c0b41fb0021220c6b0b41fb0021220c6a0b41ff0021220c690b41810121220c680b41860121220c670b418a0121220c660b418c0121220c650b41960121220c640b419e0221220c630b41970121220c620b41920221220c610b41980121220c600b419a0121220c5f0b419c0121220c5e0b419d0121220c5d0b41fe0121220c5c0b41fd0121220c5b0b41a20121220c5a0b41a30121220c590b41a30121220c580b41ac0121220c570b41a30121220c560b41e00121220c550b41a50121220c540b41a60121220c530b41f10121220c520b41db0121220c510b41a90121220c500b41a90121220c4f0b41aa0121220c4e0b41d20121220c4d0b41aa0121220c4c0b41d20121220c4b0b41aa0121220c4a0b41ab0121220c490b41b00121220c480b41ae0121220c470b41b20121220c460b41b20121220c450b41b30121220c440b41b40121220c430b41b50121220c420b41b70121220c410b41ca0121220c400b41c90121220c3f0b41bb0121220c3e0b41bc0121220c3d0b41bc0121220c3c0b41bd0121220c3b0b41bd0121220c3a0b41c10121220c390b41be0121220c380b41c70121220c370b41be0121220c360b41be0121220c350b41c40121220c340b41c40121220c330b41ce0121220c320b41cc0121220c310b41cc0121220c300b41ce0121220c2f0b41ce0121220c2e0b41da0121220c2d0b41d90121220c2c0b41d80121220c2b0b41d90121220c2a0b41dd0121220c290b41ef0121220c280b41ee0121220c270b41df0121220c260b41df0121220c250b41e00121220c240b41e40121220c230b41e40121220c220b41e50121220c210b41e70121220c200b41e50121220c1f0b41e80121220c1e0b41eb0121220c1d0b41f00121220c1c0b41f00121220c1b0b41f30121220c1a0b41f50121220c190b41fc0121220c180b41fb0121220c170b41fa0121220c160b41f90121220c150b41900221220c140b41830221220c130b41830221220c120b41860221220c110b41860221220c100b41870221220c0f0b41890221220c0e0b41870221220c0d0b418a0221220c0c0b418d0221220c0b0b41930221220c0a0b41930221220c090b419d0221220c080b419c0221220c070b419b0221220c060b419c0221220c050b41a50221220c040b41a40221220c030b41a30221220c020b41ac0221220c010b41ab0221220c000b0b821103037f067e067f230041e0016b2208240002400240024002400240200728020022094100480d00200941ffffffff07460d002007200941016a36020002400240200741046a220a200410de012209450d002009280200450d00200941106a290300210b200941086a290300210c0c010b200841306a20072802102004200741146a280200280214110400200841386a290300210b2008290330210c0b20072007280200417f6a36020020072802282109024002402002450d00200941c0006a21090c010b0240200c200b84500d00200941e0006a21090c010b200941d0006a21090b2001290310220d200141186a290300220e844200510d01200841206a2009290300200941086a290300200d200e10fb02200142002001290308220e20082903207d220d200d200e56200d507222091b370308024002402009450d0041a3b9c1002101412221070c010b200728020022014100480d01200141ffffffff07460d012007200141016a36020002400240200a200310de012201450d002001280200450d00200141106a290300210d200141086a290300210e0c010b200841106a20072802102003200741146a280200280214110400200841186a290300210d2008290310210e0b20072007280200417f6a3602000240200e20057d220f200e56200d20067d200e200554ad7d220e200d56200e200d511b4101470d00419d8cc2002101411d21070c010b0240200c200b8450450d00200741286a2802002201290330200556200141386a290300220d200656200d2006511b450d0041ba8cc2002101411f21070c010b200841086a200310ca01024020082802082201450d00200828020c21070c010b0240200c20057c2210200c542201200b20067c2001ad7c220d200b54200d200b511b450d0041d98cc2002101412d21070c010b41002101024020032004460d0020032004412010fa02450d0020072802000d042007417f360200200841f8006a41186a2201200341186a290000370300200841f8006a41106a2209200341106a290000370300200841f8006a41086a2202200341086a29000037030020082003290000370378200841c0006a200a200841f8006a10df010240024020082802404101470d00200841c0006a41086a2802002101200841c0006a41106a2802002109200842003702b401200841e8bdc0003602b0012001200941306c6a41e8026a2101200841f8006a200841b0016a10cb01200841f8006a10cc010c010b200841a8016a200841f4006a280200360200200841f8006a41286a200841ec006a29020037030020084198016a200841e4006a2902003703002001200841dc006a2902003703002009200841d4006a2902003703002002200841cc006a29020037030020082008290244370378200841b0016a41186a4100360200200841b0016a41106a4200370300200841b0016a41086a4200370300200841b0016a41286a4200370300200842003703b001200841e8bdc0003602d401200841f8006a200841b0016a10e20121010b2001200f37030820014201370300200141106a200e3703002007200728020041016a220136020020010d042007417f360200200841f8006a41186a2201200441186a290000370300200841f8006a41106a200441106a290000370300200841f8006a41086a2209200441086a29000037030020082004290000370378200841c0006a200a200841f8006a10df010240024020082802404101470d00200841c0006a41086a2802002101200841d0006a2802002109200842003702b401200841e8bdc0003602b0012001200941306c6a41e8026a2101200841f8006a200841b0016a10cb01200841f8006a10cc010c010b200841a8016a200841f4006a280200360200200841f8006a41286a200841ec006a29020037030020084198016a200841e4006a2902003703002001200841dc006a290200370300200841f8006a41106a200841d4006a2902003703002009200841cc006a29020037030020082008290244370378200841b0016a41186a4100360200200841b0016a41106a4200370300200841b0016a41086a4200370300200841b0016a41286a4200370300200842003703b001200841e8bdc0003602d401200841f8006a200841b0016a10e20121010b2001201037030820014201370300200141106a200d3703002007200728020041016a360200200841c0006a41186a2202200341186a290000370300200841c0006a41106a220a200341106a290000370300200841c0006a41086a2211200341086a290000370300200841f8006a41086a2212200441086a290000370300200841f8006a41106a2213200441106a290000370300200841f8006a41186a2214200441186a29000037030020082003290000370340200820042900003703780240200741246a22092802002201200741206a280200470d00200141016a22042001490d0620014101742203200420042003491b2215ad42d8007e220d422088a70d06200da722044100480d06024002402001450d002007411c6a2802002116200410002203450d09200320162004200141d8006c2201200120044b1b10f8021a201610010c010b200410002203450d080b200741206a20153602002007411c6a2003360200200741246a28020021010b2007411c6a280200200141d8006c6a2207200829034037000141002101200741003a000020072008290378370021200741096a2011290300370000200741116a200a290300370000200741196a2002290300370000200741296a2012290300370000200741316a2013290300370000200741396a2014290300370000200741d0006a200637030020072005370348200741c7006a200841b6016a2d00003a0000200741c5006a200841b4016a2f00003b0000200720082800b0013600412009200928020041016a3602000b0b2000200736020420002001360200200841e0016a24000f0b10c602000b41b8c7c200104f000b108402000b1018000b200441081019000ba46704097f017e167f017e230041c0036b2208240020084200370254200841e8bdc00036025002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240410310002209450d00200941026a41002d008680413a0000200941002f008480413b000020084283808080303702940320082009360290030240410110002209450d00200941003a0000200841f0026a41e0083b0100200841e8026a428180808010370300200841f2026a20082f01c8023b0100200820093602e402200841113602e002200841e0006a200841d0006a20084190036a200841e0026a10e101024020082d00714105460d002008280268450d00200828026410010b0240410f10002209450d00200941076a410029008e80413700002009410029008780413700002008428f808080f0013702940320082009360290030240410410002209450d0020094100360000200841f0026a41e0083b0100200841e8026a4284808080c000370300200841f2026a20082f01c8023b0100200820093602e402200841123602e002200841f8006a200841d0006a20084190036a200841e0026a10e101024020082d0089014105460d00200828028001450d00200828027c10010b0240410f10002209450d00200941076a410029009d80413700002009410029009680413700002008428f808080f0013702940320082009360290030240410110002209450d00200941003a0000200841f0026a41e0003b0100200841e0026a41086a428180808010370300200841f2026a20082f01c8023b0100200820093602e402200841133602e00220084190016a200841d0006a20084190036a200841e0026a10e101024020082d00a1014105460d00200828029801450d0020082802940110010b0240410810002209450d00200942e5f0d1fbb5ac98b6ec003700002008428880808080013702940320082009360290030240410710002209450d0020094100360003200941013a0002200941003b0000200841f0026a41e0003b0100200841e8026a4287808080f000370300200841f2026a20082f01c8023b0100200820093602e402200841143602e002200841a8016a200841d0006a20084190036a200841e0026a10e101024020082d00b9014105460d0020082802b001450d0020082802ac0110010b0240410a10002209450d00200941086a41002f00ad80413b0000200941002900a580413700002008428a808080a0013702940320082009360290030240410710002209450d0020094100360003200941013a0002200941003b0000200841f0026a41e0003b0100200841e0026a41086a4287808080f000370300200841f2026a20082f01c8023b0100200820093602e402200841153602e002200841c0016a200841d0006a20084190036a200841e0026a10e101024020082d00d1014105460d0020082802c801450d0020082802c40110010b0240410a10002209450d00200941086a41002f00b780413b0000200941002900af80413700002008428a808080a0013702940320082009360290030240410210002209450d00200941003b0000200841f0026a41e0083b0100200841e0026a41086a428280808020370300200841f2026a20082f01c8023b0100200820093602e402200841163602e002200841d8016a200841d0006a20084190036a200841e0026a10e101024020082d00e9014105460d0020082802e001450d0020082802dc0110010b0240410a10002209450d00200941086a41002f00c180413b0000200941002900b980413700002008428a808080a001370294032008200936029003200841f0026a41e0083b0100200841ec026a4100360200200842013702e402200841173602e002200841f0016a200841d0006a20084190036a200841e0026a10e101024020082d0081024105460d0020082802f801450d0020082802f40110010b0240410e10002209450d00200941066a41002900c98041370000200941002900c380413700002008428e808080e001370294032008200936029003200841f0026a41e0003b0100200841ec026a4100360200200842013702e402200841183602e00220084188026a200841d0006a20084190036a200841e0026a10e101024020082d0099024105460d00200828029002450d00200828028c0210010b0240410e10002209450d00200941066a41002900d78041370000200941002900d180413700002008428e808080e0013702940320082009360290030240410310002209450d00200941003a0002200941003b0000200841e0026a41106a41e0083b0100200841e8026a428380808030370300200841f2026a20082f01c8023b0100200820093602e402200841193602e002200841a0026a200841d0006a20084190036a200841e0026a10e101024020082d00b1024105460d0020082802a802450d0020082802a40210010b0240411010002209450d00200941086a41002900e78041370000200941002900df8041370000200842908080808002370294032008200936029003200841e0026a41106a41e0003b0100200841ec026a4100360200200842013702e4022008411a3602e002200841c8026a200841d0006a20084190036a200841e0026a10e101024020082d00d9024105460d0020082802d002450d0020082802cc0210010b0240411010002209450d00200941086a41002900f78041370000200941002900ef80413700002008429080808080023702bc02200820093602b8020240410310002209450d00200941003a0002200941003b0000200841f0026a41e0083b0100200841e0026a41086a428380808030370300200841f2026a20082f0190033b0100200820093602e4022008411b3602e00220084190036a200841d0006a200841b8026a200841e0026a10e101024020082d00a1034105460d00200828029803450d0020082802940310010b200841c0006a41086a200841d0006a41086a280200360200200820082903503703404100210a200841003602d002200820003602c802200820013602cc020240200141044f0d00200841013a008802200841f4026a4101360200200841ec026a41013602002008410f3602a402200841e0c3c1003602e802200841013602e402200841b08fc2003602e002200820084188026a3602a0022008200841a0026a3602f00220084190036a200841e0026a104d200828029403210b200828029003210c0c2b0b200841c8026a41086a41043602000240024020002800004180c2cdeb06470d002001417c714104470d01200841013a008802200841f4026a4101360200200841ec026a41013602002008410f3602a402200841e0c3c1003602e802200841013602e402200841b08fc2003602e002200820084188026a3602a0022008200841a0026a3602f00220084190036a200841e0026a104d200828029403210b200828029003210c4100210a0c2c0b410121010c290b0240200141074d0d00200841c8026a41086a41083602000240024002400240024002402000280004220c4101470d00200841e0026a200841c8026a10ba0220082802e002220e4101470d01410021004104210f4100211020082d00e4020d020c1a0b410221010c2f0b200841e0026a410572210b4104210f200841e0026a412c6a211220084184036a211320084180036a2114200841fc026a2115200841f8026a2116200841f4026a2117200841f0026a2118200841ec026a2119200841e8026a211a4128210d41002100410021104100210a0340200841a0026a41026a221b200b41026a2d00003a00002008200b2f00003b01a0022012280200211c20084188036a280200211d2013280200211e2014280200211f2015280200212020162802002121201728020021222018280200212320192802002124201a2802002125024020082d00e402220c417e6a220941ff0171410b4f0d0002400240024002400240024002400240024002400240024002400240024002400240024002402009410a4b22260d00024020090e0b00070405020809060b030a000b200a41ff0171222741014d0d0c0c0b0b200a41ff0171222741004b0d0a0c0b0b200a41ff0171222741054d0d0a0c090b200a41ff01712227410a4d0d090c080b200a41ff0171222741034d0d080c070b200a41ff0171222741044d0d070c060b200a41ff0171222741084d0d060c050b200a41ff0171222741024d0d050c040b200a41ff0171222741064d0d040c030b200a41ff0171222741074d0d030c020b200a41ff01712227410b4d0d020c010b200a41ff0171222741094d0d010b41132101200c410d4b0d010c020b02400240024002400240024002400240024002400240024020260d00024020090e0b00070405020809060b030a000b20274101470d110c0b0b20274100460d0a0c100b20274105470d0f0c090b2027410a470d0e0c080b20274103470d0d0c070b20274104470d0c0c060b20274108470d0b0c050b20274102470d0a0c040b20274106470d090c030b20274107470d080c020b2027410b470d070c010b20274109470d060b41142101200c410d4d0d010b02402024450d00202510010b02402021450d002020450d00202110010b201d450d01201e1001200c4105460d020c030b02400240024002400240024002400240024002400240024002400240200c0e0e0d0405010d0d0d08030e070002060d0b2023450d0c2025202341186c6a21232025210b03400240200b41046a280200450d00200b28020010010b0240200b41146a280200220d450d00200b28020c2109200d410474210d0340024020092d00004109470d00200941086a28020041ffffffff0371450d00200941046a28020010010b200941106a2109200d41706a220d0d000b0b200b41186a21090240200b41106a280200450d00200b410c6a28020010010b2009210b20092023470d000c0d0b0b2023450d0b202341286c210d2025210903400240200941046a280200450d00200928020010010b0240200941106a280200450d002009410c6a28020010010b200941286a2109200d41586a220d0d000c0c0b0b2023450d0a20252023411c6c6a21232025210b03400240200b410c6a280200220d450d00200b2802042109200d410474210d0340024020092d00004109470d00200941086a28020041ffffffff0371450d00200941046a28020010010b200941106a2109200d41706a220d0d000b0b0240200b41086a280200450d00200b41046a28020010010b200b411c6a21090240200b41146a280200450d00200b28021010010b2009210b20092023470d000c0b0b0b2023450d09202341146c210d2025210903400240200941046a280200450d00200928020010010b200941146a2109200d416c6a220d0d000c0a0b0b02402024450d00202510010b2021450d0920221001200c4105460d0a0c0b0b2023450d072023410474210d2025210903400240200941046a280200450d00200928020010010b200941106a2109200d41706a220d0d000c080b0b202541ff017122094102460d0320094101460d0220090d052023450d0720241001200c4105460d080c090b2023450d0520252023411c6c6a21232025210b03400240200b410c6a280200220d450d00200b2802042109200d410474210d0340024020092d00004109470d00200941086a28020041ffffffff0371450d00200941046a28020010010b200941106a2109200d41706a220d0d000b0b0240200b41086a280200450d00200b41046a28020010010b200b411c6a21090240200b41146a280200450d00200b28021010010b2009210b20092023470d000c060b0b2023450d04202520234104746a21232025210b03400240200b280208220d450d00200b2802002109200d410474210d0340024020092d00004109470d00200941086a28020041ffffffff0371450d00200941046a28020010010b200941106a2109200d41706a220d0d000b0b200b41106a21090240200b41046a280200450d00200b28020010010b2009210b20092023470d000c050b0b2021450d012021410c6c210d20232109034002402009280200220b450d00200941046a280200450d00200b10010b2009410c6a2109200d41746a220d0d000c020b0b2021450d00202320214104746a21202023211d0340201d222141106a211d024020212802042209450d0002402021410c6a280200220d450d00200d410c6c210d034002402009280200220b450d00200941046a280200450d00200b10010b2009410c6a2109200d41746a220d0d000b0b202141086a280200450d00202141046a28020010010b201d2020470d000b0b2022450d0220231001200c4105460d030c040b2023450d01202410010c010b2024450d0020251001200c4105460d010c020b200c4105470d010b200e450d002024450d00202510010b200f21092010450d050c040b0240024002400240024002400240024002400240024020260d00024020090e0b00070405020809060b030a000b4101210a0c0b0b4100210a0c0a0b4105210a0c090b410a210a0c080b4103210a0c070b4104210a0c060b4108210a0c050b4102210a0c040b4106210a0c030b4107210a0c020b410b210a0c010b4109210a0b20084190036a41026a2226201b2d00003a0000200820082f01a0023b019003024020102000470d00200041016a22092000490d1b2000410174221b20092009201b491b221bad422c7e2211422088a70d1b2011a722094100480d1b024002402000450d0020091000220e450d07200e200f20092000412c6c2200200020094b1b10f8022109200f10012009210f0c010b20091000220f450d060b201b21000b200f200d6a220941586a200c3a00002009201c3602002009417c6a201d360200200941786a201e360200200941746a201f360200200941706a20203602002009416c6a2021360200200941686a2022360200200941646a2023360200200941606a20243602002009415c6a20253602002009415b6a20262d00003a0000200941596a20082f0190033b0000200d412c6a210d201041016a2110200841e0026a200841c8026a10ba0220082802e002220e4101470d000b20082d00e402450d180b20082902e4022211422088a7210c2011421088a7210d2011420888a7210a200841ec026a280200210b2011a72101200f21092010450d010b2010412c6c211003402009102a2009412c6a2109201041546a22100d000b0b2000450d2d200f10010c2d0b200941041019000b410820011076000b410341011019000b411041011019000b411041011019000b410341011019000b410e41011019000b410e41011019000b410a41011019000b410241011019000b410a41011019000b410741011019000b410a41011019000b410741011019000b410841011019000b410141011019000b410f41011019000b410441011019000b410f41011019000b410141011019000b410341011019000b2010412c6c2109200f41606a210a2010ad4220862000ad8421110240024003402009450d01200941546a2109200a41206a210d200a412c6a220b210a200d2d0000410b470d000b200b280200210c0c010b4100210c0b2010412c6c2109200f41586a210a0240024003402009450d01200941546a2109200a41286a210d200a412c6a220b210a200d2d00004104470d000b200841386a200b1049200c200828023c460d010c150b200c4100470d140b02400240024002400240024002400240024002400240200841d0026a2802002001470d00200f450d022011a72110200f2011422088a7220d412c6c6a210a200f21090340200a2009460d0220092d000021012009412c6a2200210920014106470d000b200841306a200041586a10492008280234450d01410221090c1c0b200841003a008802200841f4026a4101360200200841ec026a41013602002008410f3602a402200841e0c3c1003602e802200841013602e402200841b08fc2003602e002200820084188026a3602a0022008200841a0026a3602f00220084190036a200841e0026a104d200828029403210b200828029003210c02402011422088a72209450d002009412c6c2101200f210903402009102a2009412c6a2109200141546a22010d000b0b410521012011a7450d22200f10010c220b200841e0026a41086a22014200370300200841e8bdc0003602e402200820062903003e02f002200820062903083e02e002200841e0026a4104722209410d10602009410c10602009410710602009410f1060200841d8026a20082802f002360200200841c8026a41086a2001290300370300200820082903e0023703c802200f450d0120084190036a410c6a20113702002008200f3602980320084280c2cdeb1637039003200841e0026a20084190036a200841c8026a105a024020082802e0024101470d00200841f0026a2802002100200841ec026a280200210a0240200841f4026a2802002209450d002009412c6c2101200a210903402009102a2009412c6a2109200141546a22010d000b0b02402000450d00200a10010b200841c8026a41047210ce01410321090c230b200841f0026a2903002111200841e0026a410c6a280200210920082902e4022128200841c8026a41047210ce012009450d0220084190036a410c6a201137020020082009360298032008202837039003200841e0026a20084190036a20062802281048024020082802e0024101470d000240200841e8026a280200450d0020082802e40210010b410421090c230b200841ec026a280200220f450d0320082902e4022128200841f0026a2903002211a72110200f2011422088a7220d412c6c6a210a200f2109024002400340200a2009460d0120092d000021012009412c6a2200210920014102470d000b200841286a200041586a104920082802282109200828022c21010c010b410021090b2001410020091b211d20094188f0c10020091b2120200f200d412c6c6a210a200f2109024002400340200a2009460d0120092d000021012009412c6a2200210920014103470d000b200841206a200041586a104920082802202109200828022421010c010b410021090b20094188f0c10020091b22212001410020091b41286c6a21004100210c0240034020212000460d0120212101034041062109200141086a2802004103470d1d02402001280200220a4196b9c100460d00200a4196b9c100410310fa020d1e0b024002400240200141186a2d0000220a4102460d00200a0d010c020b2001411c6a210c0b200141286a22012000470d010c030b0b20202001411c6a280200220a4104746a4100201d200a4b1b221c450d1c201c200b201c1b211e200141286a2121200141146a280200210a2001410c6a280200211b200828024021012008280244210b200841c0006a21240340200841e0026a41086a221f2024360200200820013602e4022008200b3602e002200841186a200841e0026a10a10120082802182201200828021c410c6c6a2123417f2125418901210b024002400240034020012023460d012001450d0102400240201b2001280200200141086a2802002224200a200a20244b1b10fa022222450d00200b41146a210b417f410120224100481b22240d010c050b200b41146a210b4100417f4101200a2024491b200a2024461b2224450d040b2001410c6a2101202541016a212520244101460d000b20082802e00222010d010c200b200841106a200841e0026a10a1012008280214212520082802e0022201450d1f0b201f28020021242001417f6a210b20082802e40220254102746a41e8026a28020021010c010b0b20082802e402200b6a22224111460d1c2022417f6a2d0000201e2d000c470d1c2022417b6a2802002224201e280208470d1c202241736a2802002125201e28020021234100210102400340200120244f0d01202320016a210a202520016a210b200141016a2101200b2d0000200a2d0000460d000c1e0b0b20222d0000220a4104462224201e410d6a2d00002201410447460d1c201c210b200a2001460d00201c210b20240d00201c210b20014104460d000c1c0b0b024002400240024002400240200c450d0041072109200c280204220a450d20200c2802002200200c28020822014b0d202001200628022c4b0d2020002001417f200a1b10102201417f460d20410c1000221c450d0d201c2001360208201c428180808010370200200f0d010c1f0b4100410010102209417f460d01410c1000221c450d0a201c2009360208201c428180808010370200200f450d1e0b200841003602a802200842013703a002410410002209450d08200841043602a402200841a8026a22012001280200220a41046a360200200820093602a0022009200a6a20283e0000024020082802a402220a200128020022096b41044f0d00200941046a22012009490d0e200a4101742209200120012009491b22094100480d0e200a450d0220082802a0022100200910002201450d0b200120002009200a200a20094b1b10f8021a200010010c030b20082802a00221010c030b41072109200f0d1e0c250b200910002201450d080b200820093602a402200820013602a002200841a8026a28020021090b200841a0026a41086a200941046a360200200120096a2028422088a7360000200f2011422088a72209412c6c22016a21002011a7211f024002400240024002402009450d00200141546a2123200841e0026a4101722101200841e0026a412a6a210d200841e0026a41286a2110200841e0026a41206a210b200841e0026a41186a210c200841e0026a41106a2124200841e0026a41086a2125200f2109034020092d0000210a200d2009412b6a2d00003a00002010200941296a2f00003b0100200b200941216a290000370300200c200941196a2900003703002024200941116a2900003703002025200941096a2900003703002008200941016a2900003703e002200a410f460d0220084190036a412a6a2221200d2d00003a000020084190036a41286a222220102f01003b010020084190036a41206a221d200b29030037030020084190036a41186a2220200c29030037030020084190036a41106a221e202429030037030020084190036a41086a221b2025290300370300200820082903e002370390032001200829039003370000200141086a201b290300370000200141106a201e290300370000200141186a2020290300370000200141206a201d290300370000200141286a20222f01003b00002001412a6a20212d00003a00002008200a3a00e002200841c8026a200841e0026a200841a0026a10b30220082d00c802220a411a470d05202341546a21232009412c6a22092000470d000b200022092000470d020c030b200f22092000470d010c020b2009412c6a22092000460d010b200841e0026a4101722101200841e0026a412a6a210d200841e0026a41286a2110200841e0026a41206a210b200841e0026a41186a210c200841e0026a41106a2124200841e0026a41086a2125034020092d0000210a200d2009412b6a2d00003a00002010200941296a2f00003b0100200b200941216a290000370300200c200941196a2900003703002024200941116a2900003703002025200941096a2900003703002008200941016a2900003703e002200a410f460d0120084190036a412a6a2223200d2d00003a000020084190036a41286a222120102f01003b010020084190036a41206a2222200b29030037030020084190036a41186a221d200c29030037030020084190036a41106a2220202429030037030020084190036a41086a221e2025290300370300200820082903e002370390032001200829039003370000200141086a201e290300370000200141106a2020290300370000200141186a201d290300370000200141206a2022290300370000200141286a20212f01003b00002001412a6a20232d00003a00002008200a3a00e002200841e0026a102a2009412c6a22092000470d000b0b201f450d09200f10010c090b20082d00cb02212620082f00c902210e200841c8026a41086a280200211220082802cc02211302402023450d002009412c6a2109200841e0026a4101722101200841e0026a412a6a2110200841e0026a41286a210b200841e0026a41206a210c200841e0026a41186a2124200841e0026a41106a2125200841e0026a41086a2123034020092d0000210d20102009412b6a2d00003a0000200b200941296a2f00003b0100200c200941216a2900003703002024200941196a2900003703002025200941116a2900003703002023200941096a2900003703002008200941016a2900003703e002200d410f460d0120084190036a412a6a222120102d00003a000020084190036a41286a2222200b2f01003b010020084190036a41206a221d200c29030037030020084190036a41186a2220202429030037030020084190036a41106a221e202529030037030020084190036a41086a221b2023290300370300200820082903e002370390032001200829039003370000200141086a201b290300370000200141106a201e290300370000200141186a2020290300370000200141206a201d290300370000200141286a20222f01003b00002001412a6a20212d00003a00002008200d3a00e002200841e0026a102a2009412c6a22092000470d000b0b0240201f450d00200f10010b200a411a460d08200e202641107472410874200a722109024020082802a402450d0020082802a00210010b0240200941ff01714105470d002012450d00201310010b201c201c280200417f6a22013602004100210920010d22201c2802081011201c201c280204417f6a220136020420010d22201c10010c220b4188a1c10041341042000b41bca1c10041361042000b41bca1c10041361042000b41bca1c10041361042000b410441011019000b410c41041019000b200941011019000b410c41041019000b200841a0026a41086a280200212120082802a402212220082802a0022123200841a0036a420037030020084280808080c00037039803200842043703900320082802442110200841e0026a41086a220020082802402201360200200841e0026a410c6a220d200841c0006a360200200820103602e40220082010410047220c3602e002024002402010450d002010417f6a2109200841e0026a410472210b2001210a03402000200a2802e802220a360200200d200841c0006a360200200820093602e402200820094100473602e0022009417f6a2209417f470d000c020b0b200841e0026a410472210b0b200841a0026a41086a200b41086a2802003602002008200b2902003703a002200841e0026a41086a220a2001360200200841ec026a2200200841c0006a360200200820103602e4022008200c3602e00202402010450d002010417f6a21090340200a200120012f01064102746a41e8026a28020022013602002000200841c0006a360200200820093602e402200820094100473602e0022009417f6a2209417f470d000b0b200841ec026a2802002109200841e0026a41086a2201280200220a2f0106210020082802e402210d200841c8026a41086a2210200841a0026a41086a280200360200200820082903a0023703c8022008280248210b200841e0026a411c6a2000360200200841f8026a2009360200200841e0026a41146a200a360200200120102802003602002008200b360280032008200d3602f002200841003602ec02200820082903c8023703e002200841086a200841e0026a10d301024020082802082209450d00200828020c210120084190036a41086a210003402001280200210d200928020821012009280200211041031000220a450d03200a41026a41002d0098b9413a0000200a41002f0096b9413b00002001417f4c0d04024002402001450d002001100022090d010c070b410121090b20092010200110f8022110024020002802002209200828029403470d00200941016a220b2009490d032009410174220c200b200b200c491b220fad4205862211422088a70d032011a7220b4100480d03024002402009450d002008280290032124200b1000220c450d09200c2024200b200941057422252025200b4b1b10f8021a202410010c010b200b1000220c450d080b2008200f360294032008200c360290030b20082802900320094105746a220941003602182009201036020c20094283808080303702042009200a3602002009411c6a200d360200200941146a2001360200200941106a20013602002000200028020041016a3602002008200841e0026a10d30120082802042101200828020022090d000b0b201c280200220941016a220141014d0d05201c20013602002009417e460d05201c200941026a3602000240200841a4036a22012802002209200841a0036a280200470d00200941016a220a2009490d0120094101742200200a200a2000491b220dad4202862211422088a70d012011a7220a4100480d01024002402009450d002008419c036a2802002110200a10002200450d0b20002010200a2009410274220b200b200a4b1b10f8021a201010010c010b200a10002200450d0a0b200841a0036a200d3602002008419c036a20003602000b2008419c036a28020020094102746a201c3602002001200128020041016a360200201c280208210d410310002201450d06200141026a41002d0098b9413a0000200141002f0096b9413b000041061000220a450d07200a41046a41002f009db9413b0000200a4100280099b941360000024020084198036a22002802002209200828029403470d00200941016a22102009490d012009410174220b20102010200b491b220cad4205862211422088a70d012011a722104100480d01024002402009450d00200828029003210f20101000220b450d0c200b200f201020094105742224202420104b1b10f8021a200f10010c010b20101000220b450d0b0b2008200c360294032008200b360290030b20082802900320094105746a220941013602182009200a36020c2009428380808030370204200920013602002009411c6a200d360200200941106a4286808080e0003702002000200028020041016a360200201c201c280200417f6a2209360200024020090d00201c41086a2802001011201c201c280204417f6a220936020420090d00201c10010b41002109200841f8026a4100360200200841e8026a2003360200200841003a00880320082007360284032008201c36028003200820063602fc02200842013703f002200820043602ec02200820023602e402200820053602e002200841a0026a20084190036a10d70202400240411c2023202120082802a002220120082802a802200841e0026a1012220d417f460d00200d417d470d01410221090b024020082802a402450d00200110010b024020094102470d0020084188036a2d0000210120084180036a28020021090240200841f4026a280200450d00200841f0026a28020010010b20092009280200417f6a220a3602000240200a0d002009280208101120092009280204417f6a220a360204200a0d00200910010b4108410520011b210941002124410121250c110b0240200841f4026a280200450d00200841f0026a28020010010b20084180036a220928020022012001280200417f6a3602000240200928020022012802000d0020012802081011200928020022012001280204417f6a360204200928020022092802040d00200910010b024020084198036a2802002201450d0020082802900321092001410574210103400240200941046a280200450d00200928020010010b0240200941106a280200450d002009410c6a28020010010b200941206a2109200141606a22010d000b0b0240200828029403450d0020082802900310010b0240200841a4036a2802002201450d002008419c036a28020021092001410274210103402009280200220a200a280200417f6a36020002402009280200220a2802000d00200a28020810112009280200220a200a280204417f6a3602042009280200220a2802040d00200a10010b200941046a21092001417c6a22010d000b0b0240200841a0036a280200450d002008419c036a28020010010b02402022450d00202310010b200841c0006a10d201200841c0036a240041060f0b200841c8026a20084190036a410c6a102d20082802d002211020082802cc02210c20082802c802210b024020082802a402450d00200110010b200841ac026a2010360200200841a0026a41086a200c3602002008200b3602a4022008200d3602a002200841003602d002200842083703c802200841c8026a4188f0c1004100102620082802cc02210020082802c802210a20082802d0022109200841003602d002200842013703c8022009200841c8026a101b02402009450d0020094104742101200a210903402009200841c8026a10d902200941106a2109200141706a22010d000b0b200841c8026a41086a280200210f20082802cc02212420082802c802210102402000450d00200a10010b410a10002209450d0a20094200370000200941086a41003b000041012100200d419fb9c10041042001200f2009410a200841e0026a1013220a417d460d0c200a0d0b2008410936028c022008200941016a360288020240024020092d0000220a4101460d00200a0d01410021000c0e0b200841c8026a20084188026a10d80220082802c802220a4104460d0041002100200a4105470d0d0b2009100102402024450d00200110010b20084180036a2802002101200841f4026a280200210a200841f0026a280200210f20084188036a2d00004521090c0d0b1018000b410341011019000b102c000b200141011019000b200b41041019000b00000b410341011019000b410641011019000b200a41041019000b201041041019000b410a41011019000b41d889c300104f000b2009100102402024450d00200110010b20084180036a2802002101200841f4026a280200210a200841f0026a280200210f20084188036a2d0000212402402000450d0020244521090c010b410821092024450d0141acd6c200104f000b4105410820091b21090b0240200a450d00200f10010b20012001280200417f6a220a3602000240200a0d002001280208101120012001280204417f6a220a360204200a0d00200110010b200d101402402010450d002010410274210a200b21010340200128020022002000280200417f6a3602000240200128020022002802000d0020002802081011200128020022002000280204417f6a360204200128020022002802040d00200010010b200141046a2101200a417c6a220a0d000b0b4101212441002125200c450d00200b10010b2008280290032100024020084198036a2802002201450d002001410574210a2000210103400240200141046a280200450d00200128020010010b0240200141106a280200450d002001410c6a28020010010b200141206a2101200a41606a220a0d000b0b0240200828029403450d00200010010b2008419c036a280200210f0240200841a4036a2802002201450d002001410274210a200f21010340200128020022002000280200417f6a3602000240200128020022002802000d0020002802081011200128020022002000280204417f6a360204200128020022002802040d00200010010b200141046a2101200a417c6a220a0d000b0b0240200841a0036a280200450d00200f10010b02402022450d00202310010b200841c0006a10d20120242025410047720d0a200d101402402010450d002010410274210a200b21010340200128020022002000280200417f6a3602000240200128020022002802000d0020002802081011200128020022002000280204417f6a360204200128020022002802040d00200010010b200141046a2101200a417c6a220a0d000b0b200c450d0a200b1001200841c0036a240020090f0b41bca1c10041361042000b200f450d070b0240200d450d00200d412c6c210a200f210103402001102a2001412c6a2101200a41546a220a0d000b0b2010450d06200f10010c060b02402010450d002010412c6c2101200f210903402009102a2009412c6a2109200141546a22010d000b0b411921012000450d00200f10010b0b0c010b410521014100210d0b200d411074200a41ff017141087472200141ff01717221010b41012109200141ff01714105470d00200b450d00200c10010b200841c0006a10d2010b200841c0036a240020090bf70604027f017e067f027e230041d0006b220424002004200136021c200420004188f0c10020011b360218200441106a200441186a103a024002400240024002400240024002402004280210450d0020042802142205ad2206421c88a70d022006420486a72201417f4c0d02024002400240024002402001450d00200110002200450d0820050d010c020b410821002005450d010b200441306a4104722107410021080340200441306a200441186a10d802200441c0006a41086a2201200741086a28020036020020042007290200370340200428023022094104460d03200441206a41086a220a20012802003602002004200429034037032002402006422088a722012006a7470d00200141016a220b2001490d032001410174220c200b200b200c491bad220d420486220e422088a70d03200ea7220b4100480d03024002402001450d00200b1000220c450d08200c2000200b20014104742201200b2001491b10f802210120001001200121000c010b200b10002200450d070b200642808080807083200d8421060b20002006422088a74104746a220120093602002001410c6a200a2802003602002001200429032037020420064280808080107c2106200841016a22082005490d000b0b2000450d022004200637022420042000360220200441086a200441206a1049200441306a20022004280208200428020c20031105002004410036024820044201370340200428023021004101100021010240024020004105470d002001450d08200141013a000020044281808080103702442004200136024042012106200121000c010b2001450d08200141003a0000200442818080801037024420042001360240024020004104470d00410210002200450d0a200020012d00003a000020011001200041003a0001200442828080802037024420042000360240420221060c010b410210002200450d0a200020012d00003a000020011001200041013a0001200442828080802037024420042000360240200441306a200441c0006a10d902200441c8006a3502002106200428024021000b2000ad422086200684210602402004280224450d00200428022010010b200441d0006a240020060f0b1018000b2006a7450d00200010010b41dec1c10041f0001042000b200b41081019000b102c000b200141081019000b410141011019000b410141011019000b410241011019000b410241011019000b4501017f230041c0006b22012400200141386a2000410c6a28020036020020012000290204370330200141086a200141306a10cf01200141086a10d001200141c0006a24000b4b00200041ddf5c10036020420004100360200200041206a41003602002000411c6a4188f0c100360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b3400200041f9bdc10036020420004100360200200041146a4101360200200041106a41bc85c300360200200041086a42093702000b4b00200041ddf5c10036020420004100360200200041206a41063602002000411c6a41f885c300360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b871a0a027f027e107f027e017f027e047f017e077f017e230041d0026b22022400200241086a200110350240024002400240024002402002280208450d00200228020c2203ad220442287e2205422088a70d032005a72206417f4c0d03024002400240024002402006450d00200610002207450d0920030d010c020b410821072003450d010b200241c7016a2108200241f8006a41116a2109200241b8016a41106a2106200241b8016a410172210a200241106a410172210b200141046a210c200141086a210d200241f0016a210e20024180026a210f410021100340200241003a00b8012001280200200c280200200241b8016a4101200d28020010042111200d200d280200201141016a221141014b6a221236020002400240024002400240024002400240024002400240024020114102490d004104211320022d00b801221141034b0d0b024020110e0400040203000b2002200110352002280200450d0b20022802042211417f4c0d132011450d08201110002212450d1520124100201110f7021a0c090b410421130c0a0b200241b8016a41186a2214420037030020064200370300200241b8016a41086a22114200370300200242003703b801200d41002001280200200c280200200241b8016a41202012100422122012417f461b2212412020124120491b200d2802006a3602002012411f4d0d04200241c0026a41026a20022d00ba013a000020024188026a41086a200841086a29000037030020024188026a41106a200841106a2d00003a0000200220022f01b8013b01c002200220082900003703880220022800bb01211520022900bf012116410121120c050b200242003703b801200d41002001280200200c280200200241b8016a41082012100422112011417f461b2211410820114108491b200d2802006a2212360200201141074d0d0120022903b8012117200e4200370300200241b8016a41306a4200370300200241b8016a41286a4200370300200241b8016a41206a4200370300200241b8016a41186a420037030020064200370300200241b8016a41086a4200370300200242003703b801200d41002001280200200c280200200241b8016a41c0002012100422112011417f461b221141c000201141c000491b200d2802006a3602002011413f4d0d0120024188026a41086a200841086a29000037030020024188026a41106a200841106a29000037030020024188026a41186a200841186a29000037030020024188026a41206a200841206a29000037030020024188026a41286a200841286a29000037030020024188026a41306a200841306a2d00003a0000200220022d00ba013a00c202200220022f01b8013b01c002200220082900003703880220022800bb01211820022900bf012119410121112017211a0c020b200241b8016a2001103420022802b8012211450d0720022902bc012105200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2006290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a290300370300200220024188026a41026a2d00003a00b201200220022f0088023b01b001200220022903b801370378410021132011211b0c060b410021110b200241b8016a41086a221220024188026a41086a290300370300200620024188026a41106a290300370300200241b8016a41186a221420024188026a41186a290300370300200241b8016a41206a221c20024188026a41206a290300370300200241b8016a41286a221d20024188026a41286a290300370300200241b8016a41306a221e20024188026a41306a2d00003a0000200220022d00c2023a00ca02200220022f01c0023b01c80220022002290388023703b8012011450d05200241f8006a41086a2012290300370300200241f8006a41106a2006290300370300200241f8006a41186a2014290300370300200241f8006a41206a201c290300370300200241f8006a41286a201d290300370300200241f8006a41306a201e2d00003a0000200220022d00ca023a00b201200220022f01c8023b01b001200220022903b801370378410221132018211b20192105201a211f0c050b410021120b200241c8026a41026a221c200241c0026a41026a2d00003a0000201120024188026a41086a290300370300200620024188026a41106a2d00003a0000200220022f01c0023b01c80220022002290388023703b8012012450d03200241f8006a41086a2011290300370300200241f8006a41106a20062d00003a0000200220022f01c8023b01b001200220022903b8013703782002201c2d00003a00b2012009411f6a200241b8016a411f6a290000370000200941186a2014290000370000200941106a2006290000370000200941086a2011290000370000200920022900b801370000410121132015211b201621050c020b410121120b200d201141002001280200200c28020020122011200d280200100422142014417f461b2214201420114b1b200d2802006a3602000240201120144d0d00201210010c020b2012450d012011ad22054220862005842105200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2006290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a290300370300200220022f0088023b01b001200220022903b801370378200220024188026a41026a2d00003a00b201410321132012211b0b0b20024188026a41026a221e20022d00b2013a0000200241b8016a41086a2211200241f8006a41086a22142903003703002006200241f8006a41106a221c290300370300200241b8016a41186a2212200241f8006a41186a221d290300370300200241b8016a41206a2220200241f8006a41206a290300370300200241b8016a41286a2221200241f8006a41286a290300370300200241b8016a41306a2222200241f8006a41306a290300370300200220022f01b0013b018802200220022903783703b80120134104460d02200241f4006a41026a2223201e2d00003a0000200241386a41086a221e2011290300370300200241386a41106a22242006290300370300200241386a41186a22252012290300370300200241386a41206a22262020290300370300200241386a41286a22202021290300370300200241386a41306a22212022290300370300200220022f0188023b0174200220022903b80137033820112005370300200a20022f01743b0000200a41026a20232d00003a000020062002290338370000200641086a201e290300370000200641106a2024290300370000200641186a2025290300370000200641206a2026290300370000200641286a2020290300370000200641306a2021290300370000200220133a00b8012002201b3602bc01200f201f370300200241106a200241b8016a10d60220022d00102113200241b8016a411f6a221e200b411f6a2900003700002012200b41186a2900003703002006200b41106a2900003703002011200b41086a2900003703002002200b2900003703b80120134103460d03200241f8006a411f6a2220201e290000370000201d2012290300370300201c200629030037030020142011290300370300200220022903b80137037802402004422088a722112004a7470d00201141016a22122011490d062011410174221e20122012201e491bad221742287e2227422088a70d062027a722124100480d06024002402011450d0020121000221e450d09201e20072012201141286c2211201120124b1b10f802211120071001201121070c010b201210002207450d080b20044280808080708320178421040b20072004422088a741286c6a221120133a0000201141206a2020290000370000201141196a201d290300370000201141116a201c290300370000201141096a20142903003700002011200229037837000120044280808080107c2104201041016a22102003490d000b0b2007450d022000200437020420002007360200200241d0026a24000f0b200241033a0010200241b8016a411f6a200b411f6a290000370000200241b8016a41186a200b41186a290000370300200241b8016a41106a200b41106a290000370300200241b8016a41086a200b41086a2900003703002002200b2900003703b8010b02402004422088a72206450d00200641286c2111200721060340024020062d0000220b450d000240200b4101470d00200641086a280200450d01200641046a2802001001200641286a2106201141586a22110d020c030b200641146a280200450d00200641106a28020010010b200641286a2106201141586a22110d000b0b2004a7450d00200710010b20004100360200200241d0026a24000f0b1018000b201241081019000b102c000b200641081019000b201141011019000bcc0201057f230041206b22022400024002400240411610002203450d002002421637021420022003360210200241106a4181c8c10041161025200241086a220320022802183602002002200229031037030020012002101e200328020021042002280204210520022802002101200241106a41086a220642003703002002420037031020012004200241106a1002200320062903003703002002200229031037030002400240200241104188f0c100410041001004417f460d002002410036021020024110200241106a41044100100441016a41044d0d01200228021021032002410036021020024110200241106a41044104100441016a41044d0d01200041086a200228021036020020002003360204200041013602002005450d040c030b2000410036020020050d020c030b41eac4c10041331042000b411641011019000b200110010b200241206a24000b3400200041a9cbc10036020420004100360200200041146a4114360200200041106a41c08bc300360200200041086a42073702000b4b00200041ddf5c10036020420004100360200200041206a41093602002000411c6a419896c300360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b130020004104360204200041d89dc3003602000ba80703057f037e047f230041206b220324000240024002402002280208220420014d0d00200241086a2004417f6a22053602002002280200220620054105746a22072900002108200729000821092007290010210a200620014105746a220141186a200741186a2900003700002001200a37001020012009370008200120083700002002280204210b20034100360218200342013703102005200341106a101b02400240024002402005450d00200441057441606a210c200341106a41086a280200210120032802102104200328021421072006210d0340200d210202400240024002402007200122056b41204f0d00200541206a22012005490d072007410174220d20012001200d491b220d4100480d07200d1000210e2007450d01200e450d08200e2004200d20072007200d4b1b10f8021a200410010c020b200541206a21010c020b200e450d060b200e2104200d21070b200241206a210d200420056a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200c41606a220c0d000b200341186a200136020020032007360214200320043602100c010b200341106a41086a280200210120032802142107200328021021040b200341106a41086a220242003703002003420037031041b6c7c100410e200341106a1002200341086a2002290300370300200320032903103703002003411020042001100302402007450d00200410010b0240200b450d00200610010b411310002202450d032003421337021420032002360210200341106a41eee8c10041131025200341086a220220032802183602002003200329031037030020002003101e200228020021072003280204210120032802002105200341106a41086a220442003703002003420037031020052007200341106a1002200220042903003703002003200329031037030020034110100802402001450d00200510010b411410002202450d042003421437021420032002360210200341106a41c8e8c10041141025200341086a220220032802183602002003200329031037030020002003101e200228020021072003280204210120032802002105200341106a41086a220442003703002003420037031020052007200341106a1002200220042903003703002003200329031037030020034110100802402001450d00200510010b200341206a24000f0b1018000b200d41011019000b41b08bc30020012004104e000b411341011019000b411441011019000baa0201057f230041306b220224000240024002400240411310002203450d002002421337022420022003360220200241206a41eee8c10041131025200241086a220320022802283602002002200229032037030020012002101e200328020021042002280204210520022802002101200241206a41086a220642003703002002420037032020012004200241206a100220032006290300370300200220022903203703000240200241104188f0c100410041001004417f460d002002421037021420022002360210200241206a200241106a103d20022802202203450d0220002002290224370204200020033602002005450d040c030b200041003602082000420137020020050d020c030b411341011019000b41eac4c10041331042000b200110010b200241306a24000b940201067f23004180016b220124000240411310002202450d002001421337020420012002360200200141abf1c10041131025200141f0006a41086a22022001280208360200200120012903003703702000200141f0006a101e200228020021032001280274210420012802702105200141086a220642003703002001420037030020052003200110022002200629030037030020012001290300370370200141f0006a4110100802402004450d00200510010b200641013a0000200141096a2000290000370000200141116a200041086a290000370000200141196a200041106a290000370000200141216a200041186a290000370000200141013a0000200110b40120014180016a24000f0b411341011019000b3400200041b1f3c10036020420004100360200200041146a410a360200200041106a4198a0c300360200200041086a42063702000b34002000418ff6c10036020420004100360200200041146a410b360200200041106a41f8a4c300360200200041086a42083702000baf05010c7f230041206b2202240002400240411010002203450d002002421037021420022003360210200241106a41c785c20041101025200228021021040240024002400240024020022802142205200228021822036b41044f0d00200341046a22062003490d0320054101742207200620062007491b22084100480d032005450d01200810002207450d062007200420082005200520084b1b10f802210520041001200521040c020b200341046a2106200521080c010b200810002204450d040b200420036a200036000020024100360218200242013703102001280200210920012802082203200241106a101b024002402003450d002003410574210a200241106a41086a28020021072002280210210b200228021421002009210c0340200c210302400240024002402000200722056b41204f0d00200541206a22072005490d072000410174220c20072007200c491b220c4100480d07200c1000210d2000450d01200d450d08200d200b200c20002000200c4b1b10f8021a200b10010c020b200541206a21070c020b200d450d060b200d210b200c21000b200341206a210c200b20056a22052003290000370000200541186a200341186a290000370000200541106a200341106a290000370000200541086a200341086a290000370000200a41606a220a0d000b200241186a2007360200200220003602142002200b3602100c010b200241186a2802002107200228021421002002280210210b0b200241106a41086a220342003703002002420037031020042006200241106a1002200241086a20032903003703002002200229031037030020024110200b2007100302402000450d00200b10010b02402008450d00200410010b0240200141046a280200450d00200910010b200241206a24000f0b1018000b200c41011019000b411041011019000b200841011019000b4b00200041ddf5c10036020420004100360200200041206a41023602002000411c6a41bcacc300360200200041146a4204370200200041106a41e3f5c100360200200041086a42063702000b130020004103360204200041dcaec3003602000b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f02400240200120004f0d002002450d012001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000c020b0b2002450d00200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000b0b20000b4401037f024002402002450d00410021030340200020036a2d00002204200120036a2d00002205470d02200341016a22032002490d000b41000f0b41000f0b200420056b0b3e01017f230041106b22052400200520012002200320044100108003200529030021012000200541086a29030037030820002001370300200541106a24000b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a108003200529031021012000200529031837030820002001370300200541206a24000b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080bd80502037f067e230041306b220624000240024002400240024002400240024002400240024002400240024002400240024020024200510d002003500d012004500d03200479a7200279a76b2207413f4b0d0241ff0020076b2108200741016a21070c0c0b200450450d012005450d0520034200510d0c20054200370308200520012003823703000c060b2004500d0b20014200510d032004427f7c2209200483500d07200479a7200279a76b2207413e4d0d090b2005450d012005200137030020052002370308420021010c070b2003427f7c2209200383500d044100200379a741c1006a200279a76b22076b21080c080b420021010c050b02402005450d0020054200370300200520022004823703080b200220048021010c040b20034200510d060b200120038021010c020b02402005450d0020054200370308200520092001833703000b20034201510d07200641206a2001200220037aa710ff02200641286a2903002102200629032021010c070b02402005450d0020052001370300200520092002833703080b200220047a423f838821010b420021020c050b41ff0020076b2108200741016a21070b200620012002200841ff007110fe02200641106a20012002200741ff007110ff02200641086a2903002102200641106a41086a290300210a200629030021012006290310210902402007450d004200210b4200210c0340200a4201862009423f8884220d200d427f8520047c20094201862002423f88842209427f85220d20037c200d54ad7c423f87220d2004837d2009200d200383220e54ad7d210a2009200e7d2109420020024201862001423f8884842102200c2001420186842101200d420183220d210c2007417f6a22070d000b2005450d030c020b4200210d4200210b20050d010c020b00000b200520093703002005200a3703080b200b20024201862001423f8884842102200d20014201868421010b2000200137030020002002370308200641306a24000b0bdeb0030200418080c0000ba98d022f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962616c6c6f632f7665632e727366756e635f737461636b5f636f7374732069736e27742079657420636f6d70757465643b0a0909090944696420796f752063616c6c2060636f6d707574655f737461636b5f636f737473603f546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647343616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a200000000000002f686f6d652f6261737469616e2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e332e312f7372632f737461636b5f6865696768742f6d6f642e727366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a090909097165645369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e656446756e6374696f6e20617420696e64657820206973206e6f7420646566696e65640000000000000000000000002f686f6d652f6261737469616e2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e332e312f7372632f6761732e72737372632f6c6962616c6c6f632f7665632e7273617373657274696f6e206661696c65643a20656e64203c3d206c656e617373657274696f6e206661696c65643a20696e646578203c3d206c656e4e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e46756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64737461636b206d757374206265206e6f6e2d656d707479737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e6400002f686f6d652f6261737469616e2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e332e312f7372632f737461636b5f6865696768742f6d61785f6865696768742e7273747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e6473000000000000000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72736066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e64547261696c696e6744617461556e6578706563746564456f66496e76616c696444617461492f4f204572726f723a204578706c69636974207265706f7274696e67206e6f7420616c6c6f77656445787472696e7369635375636365737345787472696e7369634661696c656420416e2065787472696e736963206661696c65642e20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e48617368206e6f7420657175616c00617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f67656e657269632f6572612e727352756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e676361706163697479206f766572666c6f776120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72000000000000000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f666d742f6d6f642e727301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202020202020202020202020202020202020202020202020202020202020303030303030303030303030303030304040404040000000000000000000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e67746820736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d000100000000000000200000000000000003000000000000000300000000000000030000000100000001000000200000000000000003000000000000000300000000000000030000000100000002000000200000000000000003000000000000000300000000000000030000000100000003000000200000000000000003000000000000000300000000000000030000000100000000000000200000000000000003000000000000000300000000000000030000000100000001000000200000000000000003000000000000000300000000000000030000000100000002000000200000000000000003000000000000000300000000000000030000000100000003000000200000000000000003000000000000000300000000000000030000000100000004000000200000000000000003000000000000000300000000000000030000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f6620600000007372632f6c6962636f72652f666d742f6d6f642e72732e2e00000000000000007372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21b003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000d0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c813000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d000000000000001e1f20000000000021002200232425000000002600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027280000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000002b2c00002d0000000000000000000000000000000000000000000000000000000000002e2f300000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000000000320033000000000000000000000000000000000000000000000000000034350000353535360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff06fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db07000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff000000010305050606030706080809110a1c0b190c140d120e160f0410031212130916011705180219031a071c021d011f1620032b062c022d0b2e01300331023202a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f1838586898b8c98a0a4a6a8a9acbabebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f74759697c9ff2f5f262e2fa7afb7bfc7cfd7df9a409798308f1fffceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100856070207150d500443032d03010411060f0c3a041d250d064c206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082a0682ff1118082f112d032010210f808c048297190b158894052f053b07020e180980af31740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880ba3d35040a06380846080c06740b1e035a0459098083181c0a1609460a808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b0210011104120513111402150217021a021c051d0824016a036b02bc02d102d40cd509d602d702da01e005e802ee20f004f9040c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1c848509379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a2225c5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d03f71727b5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a80a64e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b5f2148080a80a65e22450b0a060d1338080a362c041080c03c64530c0181004808531d398107460a1d03474937030e080a0639070a8136198107839a66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b65450b2f101140021e97f20e82f3a50d811f51818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b87d580d7294b050a0402831144814b3c06010455051b3402810e2c04640c560a0d035c043d391d0d2c040907020e06809a83d50b0d030a06740c59270c0438080a0628081e520c046703290d0a06030d30600e859263616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75657372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f662060426f72726f774572726f72426f72726f774d75744572726f724572726f72547269656420746f20736872696e6b20746f2061206c61726765722063617061636974797372632f6c6962616c6c6f632f7261775f7665632e7273626164206f726967696e3a20657870656374656420746f2062652061207468726573686f6c64206e756d626572206f6620636f756e63696c206d656d62657273436f6e747261637420436f64654f66436f6e7472616374204761735370656e74436f6e747261637420426c6f636b4761734c696d6974637265617465204372656174652061206e657720636f6e74726163742c206f7074696f6e616c6c79207472616e73666572696e6720736f6d652062616c616e636520746f207468652063726561746564206163636f756e742e204372656174696f6e20697320657865637574656420617320666f6c6c6f77733a202d207468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20746865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792063726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e79206d6573736167652072656365697665642062792074686973206163636f756e742e656e646f776d656e746761735f6c696d69743c543a3a47617320617320486173436f6d706163743e3a3a5479706563746f725f636f646564617461204d616b6520612063616c6c20746f206120737065636966696564206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e436f6e7472616374204761735072696365566563203c2054203a3a2048617368203e3c2054206173205472616974203e203a3a2050726f706f73616c566f74696e67282050726f706f73616c496e646578202c20753332202c20566563203c2054203a3a204163636f756e744964203e202c20566563203c2054203a3a204163636f756e744964203e20292050726f706f73616c7320736f206661722e20566f74657320666f72206120676976656e2070726f706f73616c3a202872657175697265645f7965735f766f7465732c207965735f766f746572732c206e6f5f766f74657273292e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e205468652028686173686573206f662920746865206163746976652070726f706f73616c732e426f783c3c542061732054726169743e3a3a50726f706f73616c3e4372656174656420436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d60202d3e2060746f60207769746820676976656e206076616c7565602061732070617274206f66206120606d6573736167652d63616c6c60206f722060637265617465602e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f6e74726163742f7372632f6c69622e7273566f746564417070726f766564446973617070726f7665642041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e206173207533327320726573706563746976656c79292e2041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20753332292e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f756e63696c2f7372632f6d6f74696f6e732e72730000000000000000000000000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656450726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b20716564000000000000000000000000000000000000000000436f6e74726163742043757272656e745363686564756c65436f6e7472616374204d61784465707468436f6e747261637420436f6e7472616374466565436f6e74726163742043616c6c42617365466565436f6e74726163742043726561746542617365466565436f756e63696c4d6f74696f6e732050726f706f73616c4f6670726f706f736572206e6f74206f6e20636f756e63696c436f756e63696c4d6f74696f6e732050726f706f73616c436f756e74436f756e63696c4d6f74696f6e732050726f706f73616c73436f756e63696c4d6f74696f6e7320566f74696e67766f746572206e6f74206f6e20636f756e63696c70726f706f73616c206d7573742065786973746d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f72656400000000000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e7273626c6f636b20676173206c696d697420697320726561636865646f766572666c6f77206d756c7469706c79696e6720676173206c696d69742062792070726963655472656173757279205370656e64506572696f64547265617375727920506f74547265617375727920417070726f76616c735472656173757279204275726e0000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f6f70732f61726974682e727356616c696461746f72436f756e744d696e696d756d56616c696461746f72436f756e7453657373696f6e7350657245726153657373696f6e52657761726450657262696c6c4f66666c696e65536c6173684f66666c696e65536c6173684772616365426f6e64696e674475726174696f6e43757272656e7445726156616c696461746f72507265666572656e63657356616c696461746f725072656673203c2054203a3a2042616c616e6365203e496e74656e74696f6e734e6f6d696e6174696e674e6f6d696e61746f7273466f7243757272656e744e6f6d696e61746f7273466f7243757272656e7453657373696f6e52657761726443757272656e744f66666c696e65536c6173684e65787453657373696f6e735065724572614c6173744572614c656e6774684368616e67655374616b6552616e6765506169724f66203c2054203a3a2042616c616e6365203e536c617368436f756e74466f7263696e674e6577457261282020292057652061726520666f7263696e672061206e6577206572612e20546865206e756d626572206f662074696d6573206120676976656e2076616c696461746f7220686173206265656e207265706f72746564206f66666c696e652e205468697320676574732064656372656d656e746564206279206f6e652065616368206572612074686174207061737365732e2054686520626c6f636b20617420776869636820746865206077686f6027732066756e6473206265636f6d6520656e746972656c79206c69717569642e20546865206869676865737420616e64206c6f77657374207374616b65642076616c696461746f7220736c61736861626c652062616c616e6365732e205468652073657373696f6e20696e6465782061742077686963682074686520657261206c656e677468206c617374206368616e6765642e20546865206e6578742076616c7565206f662073657373696f6e7320706572206572612e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e742e20416c6c206e6f6d696e61746f72202d3e206e6f6d696e65652072656c6174696f6e73686970732e20416c6c20746865206163636f756e7473207769746820612064657369726520746f207374616b652e20507265666572656e636573207468617420612076616c696461746f72206861732e205468652063757272656e742065726120696e6465782e20546865206c656e677468206f662074686520626f6e64696e67206475726174696f6e20696e20626c6f636b732e204e756d626572206f6620696e7374616e636573206f66206f66666c696e65207265706f727473206265666f726520736c617368696e6720626567696e7320666f722076616c696461746f72732e20536c6173682c207065722076616c696461746f7220746861742069732074616b656e20666f72207468652066697273742074696d6520746865792061726520666f756e6420746f206265206f66666c696e652e204d6178696d756d207265776172642c207065722076616c696461746f722c20746861742069732070726f7669646564207065722061636365707461626c652073657373696f6e2e20546865206c656e677468206f662061207374616b696e672065726120696e2073657373696f6e732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e5374616b696e6720536c617368436f756e745374616b696e67204f66666c696e65536c61736847726163655374616b696e672043757272656e744f66666c696e65536c617368736c61736820636f756e74206e6f206c6f6e67657220696e6372656d656e746564206166746572206f766572666c6f773b207072696f7220636865636b206f6e6c79206661696c73207769746820696e7374616e636573203e3d20313b207468757320696e7374616e636573202d203120616c7761797320776f726b7320616e6420697320612076616c696420616d6f756e74206f6620626974733b207165645374616b696e6720496e74656e74696f6e735374616b696e67204d696e696d756d56616c696461746f72436f756e745374616b696e672056616c696461746f72507265666572656e636573706f73206465726976656420636f72726563746c792066726f6d2053656c663a3a696e74656e74696f6e7328293b206170706c795f756e7374616b652063616e206f6e6c79206661696c20696620706f732077726f6e673b2053656c663a3a696e74656e74696f6e73282920646f65736e2774206368616e67653b207165645374616b696e6720466f7263696e674e65774572615374616b696e6720426f6e64696e674475726174696f6e5374616b696e6720426f6e64616765496e76616c696420696e646578000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72735374616b696e67204e6f6d696e61746f7273466f725374616b696e672043757272656e744e6f6d696e61746f7273466f727374616b65756e7374616b656e6f6d696e617465756e6e6f6d696e61746572656769737465725f707265666572656e6365737365745f73657373696f6e735f7065725f6572617365745f626f6e64696e675f6475726174696f6e7365745f76616c696461746f725f636f756e74666f7263655f6e65775f6572617365745f6f66666c696e655f736c6173685f67726163652053657420746865206f66666c696e6520736c61736820677261636520706572696f642e20466f72636520746865726520746f2062652061206e6577206572612e205468697320616c736f20666f726365732061206e65772073657373696f6e20696d6d6564696174656c792061667465722e20606170706c795f72657761726473602073686f756c64206265207472756520666f722076616c696461746f727320746f20676574207468652073657373696f6e207265776172642e2054686520696465616c206e756d626572206f662076616c696461746f72732e20546865206c656e677468206f662074686520626f6e64696e67206475726174696f6e20696e20657261732e2053657420746865206e756d626572206f662073657373696f6e7320696e20616e206572612e205365742074686520676976656e206163636f756e74277320707265666572656e636520666f7220736c617368696e67206265686176696f75722073686f756c64207468657920626520612076616c696461746f722e20416e206572726f7220286e6f2d6f7029206966206053656c663a3a696e74656e74696f6e7328295b696e74656e74696f6e735f696e6465785d20213d206f726967696e602e696e74656e74696f6e735f696e646578707265667356616c696461746f7250726566733c543a3a42616c616e63653e2057696c6c2070616e69632069662063616c6c6564207768656e20736f757263652069736e27742063757272656e746c79206e6f6d696e6174696e67207461726765742e2055706461746573204e6f6d696e6174696e672c204e6f6d696e61746f7273466f7220616e64204e6f6d696e6174696f6e42616c616e63652e7461726765745f696e6465787461726765742052657472616374207468652064657369726520746f207374616b6520666f7220746865207472616e736163746f722e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e204465636c617265207468652064657369726520746f207374616b6520666f7220746865207472616e736163746f722e50726f706f73616c426f6e645065726d696c6c50726f706f73616c426f6e644d696e696d756d5370656e64506572696f644275726e506f7450726f706f73616c436f756e7450726f706f73616c496e64657850726f706f73616c203c2054203a3a204163636f756e744964202c2054203a3a2042616c616e6365203e417070726f76616c73566563203c2050726f706f73616c496e646578203e2050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e20546f74616c2066756e647320617661696c61626c6520746f2074686973206d6f64756c6520666f72207370656e64696e672e2050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e2050726f706f7274696f6e206f662066756e647320746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c61636520612070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f65736e27742e70726f706f73655f7370656e647365745f706f74636f6e66696775726572656a6563745f70726f706f73616c617070726f76655f70726f706f73616c20417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f6964436f6d706163743c50726f706f73616c496e6465783e202852652d29636f6e6669677572652074686973206d6f64756c652e70726f706f73616c5f626f6e6470726f706f73616c5f626f6e645f6d696e696d756d7370656e645f706572696f646275726e20536574207468652062616c616e6365206f662066756e647320617661696c61626c6520746f207370656e642e6e65775f706f742050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e62656e656669636961727954726561737572792050726f706f73616c734b657975706772616465543a3a4163636f756e74496400617474656d707420746f20646976696465206279207a65726f55706772616465644b65794368616e67656420416e2075706772616465206a7573742068617070656e65643b206f6c64206b657920697320737570706c69656420617320616e20617267756d656e742e20416e2075706772616465206a7573742068617070656e65642e5265776172644f66666c696e655761726e696e67204f6e652076616c696461746f722028616e64207468656972206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e204f6e652076616c696461746f722028616e64207468656972206e6f6d696e61746f72732920686173206265656e20676976656e2061206f66666c696e652d7761726e696e67202874686579277265207374696c6c2077697468696e207468656972206772616365292e205468652061636372756564206e756d626572206f6620736c6173686573206973207265636f726465642c20746f6f2e20416c6c2076616c696461746f72732068617665206265656e2072657761726465642062792074686520676976656e2062616c616e63652e50726f706f7365645370656e64696e67417761726465644275726e74526f6c6c6f766572205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f7374616b696e672f7372632f6c69622e72732f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f74726561737572792f7372632f6c69622e72732f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f757067726164652d6b65792f7372632f6c69622e72735374616b696e672043757272656e7453657373696f6e5265776172645374616b696e67205374616b6552616e67655374616b696e67204c6173744572614c656e6774684368616e67655374616b696e672053657373696f6e735065724572615374616b696e672043757272656e744572615374616b696e67204e65787453657373696f6e735065724572615374616b696e672056616c696461746f72436f756e745374616b696e67204f66666c696e65536c6173685374616b696e672053657373696f6e52657761726443616e6e6f74207374616b6520696620616c7265616479207374616b65642e43616e6e6f74207374616b6520696620616c7265616479206e6f6d696e6174696e672e43616e6e6f74206e6f6d696e61746520696620616c7265616479206e6f6d696e6174696e672e43616e6e6f74206e6f6d696e61746520696620616c7265616479207374616b65642e5374616b696e67204e6f6d696e6174696e674163636f756e74206d757374206265206e6f6d696e6174696e67496e76616c69642074617267657420696e64657863616e6e6f7420756e7374616b65207768656e2074686572652061726520746f6f20666577207374616b6564207061727469636970616e747354726561737572792050726f706f73616c426f6e644d696e696d756d54726561737572792050726f706f73616c426f6e6454726561737572792050726f706f73616c436f756e7450726f706f73657227732062616c616e636520746f6f206c6f774e6f2070726f706f73616c206174207468617420696e646578557067726164654b6579204b65796f6e6c79207468652063757272656e742075706772616465206b65792063616e207573652074686520757067726164655f6b6579206d6f64756c6553657373696f6e204c6173744c656e6774684368616e676553657373696f6e2053657373696f6e4c656e67746853657373696f6e20466f7263696e674e657753657373696f6e53657373696f6e2043757272656e74537461727453657373696f6e2043757272656e74496e64657853657373696f6e204e65787453657373696f6e4c656e67746853657373696f6e2056616c696461746f727353657373696f6e204e6578744b6579466f7200000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f6f70732f61726974682e727356616c696461746f727353657373696f6e4c656e67746843757272656e74496e64657843757272656e745374617274466f7263696e674e657753657373696f6e4c6173744c656e6774684368616e67654e6578744b6579466f7254203a3a2053657373696f6e4b65794e65787453657373696f6e4c656e67746820546865206e6578742073657373696f6e206c656e6774682e20546865206e657874206b657920666f72206120676976656e2076616c696461746f722e20426c6f636b206174207768696368207468652073657373696f6e206c656e677468206c617374206368616e6765642e204e65772073657373696f6e206973206265696e6720666f72636564206973207468697320656e747279206578697374733b20696e20776869636820636173652c2074686520626f6f6c65616e2076616c7565206973207768657468657220746865206e65772073657373696f6e2073686f756c6420626520636f6e736964657265642061206e6f726d616c20726f746174696f6e202872657761726461626c6529206f7220657863657074696f6e616c2028736c61736861626c65292e2054696d657374616d70207768656e2063757272656e742073657373696f6e20737461727465642e2043757272656e7420696e646578206f66207468652073657373696f6e2e2043757272656e74206c656e677468206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e7365745f6b65797365745f6c656e677468666f7263655f6e65775f73657373696f6e20466f726365732061206e65772073657373696f6e2e6170706c795f72657761726473205365742061206e65772073657373696f6e206c656e6774682e20576f6e2774206b69636b20696e20756e74696c20746865206e6578742073657373696f6e206368616e6765202861742063757272656e74206c656e677468292e2053657473207468652073657373696f6e206b6579206f6620605f76616c696461746f726020746f20605f6b6579602e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e6b6579543a3a53657373696f6e4b657900000000000000000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e00000000000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72734e657753657373696f6e204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e426c6f636b4e756d6265722f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f73657373696f6e2f7372632f6c69622e72737372632f6c69622e727342616420696e70757420646174612070726f766964656420746f20657865637574655f626c6f636b696e697469616c6973655f626c6f636b6170706c795f65787472696e736963696e686572656e745f65787472696e73696373636865636b5f696e686572656e747376616c69646174655f7472616e73616374696f6e6772616e6470615f70656e64696e675f6368616e67652f686f6d652f6261737469616e2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d636f6465632d322e312e352f7372632f636f6465632e72732f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f6e74726163742f7372632f766d2f72756e74696d652e72736761736578745f7365745f73746f726167656578745f6765745f73746f726167656578745f6372656174656578745f72657475726e6578745f63616c6c65726578745f696e7075745f73697a656578745f696e7075745f636f70796578745f736372617463685f73697a656578745f736372617463685f636f7079707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090944656d6f637261637920426f6e6461676563616e6e6f74207472616e7366657220696c6c69717569642066756e647344656d6f6372616379204c61756e6368506572696f6444656d6f6372616379205075626c696350726f707344656d6f6372616379204465706f7369744f6644656d6f637261637920566f74696e67506572696f6444656d6f6372616379205075626c696344656c617944656d6f6372616379204e65787454616c6c7944656d6f6372616379205265666572656e64756d436f756e7444656d6f6372616379204469737061746368517565756544656d6f6372616379205265666572656e64756d496e666f4f6644656d6f637261637920566f74657273466f7244656d6f637261637920566f74654f660000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f6f70732f61726974682e727343616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f5075626c696350726f70436f756e7450726f70496e6465785075626c696350726f7073566563203c20282050726f70496e646578202c2054203a3a2050726f706f73616c202c2054203a3a204163636f756e7449642029203e4465706f7369744f66282054203a3a2042616c616e6365202c20566563203c2054203a3a204163636f756e744964203e20294c61756e6368506572696f644d696e696d756d4465706f7369745075626c696344656c61794d61784c6f636b506572696f64734c6f636b506572696f64735265666572656e64756d436f756e745265666572656e64756d496e6465784e65787454616c6c795265666572656e64756d496e666f4f6628205265666572656e64756d496e666f203c2054203a3a20426c6f636b4e756d626572202c2054203a3a2050726f706f73616c203e202944697370617463685175657565566563203c204f7074696f6e203c20282054203a3a2050726f706f73616c202c205265666572656e64756d496e6465782029203e203e426f6e64616765566f74657273466f72566f74654f6628205265666572656e64756d496e646578202c2054203a3a204163636f756e7449642029566f7465204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e2054686520626c6f636b20617420776869636820746865206077686f6027732066756e6473206265636f6d65206c69717569642e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206e657874207265666572656e64756d20696e64657820746861742073686f756c642062652074616c6c6965642e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e64756d73207374617274656420736f206661722e20546865206d6178696d756d206e756d626572206f66206164646974696f6e616c206c6f636b20706572696f6473206120766f746572206d6179206f6666657220746f20737472656e677468656e20746865697220766f74652e204d756c7469706c6573206f6620605075626c696344656c6179602e205468652064656c6179206265666f726520656e6163746d656e7420666f7220616c6c207075626c6963207265666572656e64612e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e7365636f6e6473746172745f7265666572656e64756d63616e63656c5f7265666572656e64756d63616e63656c5f7175657565642043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e7768656e543a3a426c6f636b4e756d62657277686963682052656d6f76652061207265666572656e64756d2e7265665f696e646578436f6d706163743c5265666572656e64756d496e6465783e2053746172742061207265666572656e64756d2e7468726573686f6c64566f74655468726573686f6c6464656c617920566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e436f6d706163743c50726f70496e6465783e2050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e5461626c6564537461727465645061737365644e6f7450617373656443616e63656c6c656445786563757465642f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f64656d6f63726163792f7372632f6c69622e727344656d6f6372616379204d696e696d756d4465706f73697476616c756520746f6f206c6f7744656d6f6372616379205075626c696350726f70436f756e7470726f706f73657227732062616c616e636520746f6f206c6f7763616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f7744656d6f6372616379204d61784c6f636b506572696f6473766f74652068617320746f6f206772656174206120737472656e677468766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e7472616e736163746f72206d75737420686176652062616c616e636520746f207369676e616c20617070726f76616c2e746f6f206d616e7920696e737472756374696f6e733a6772616e6470613a617574683a4772616e64706146696e616c6974792050656e64696e674368616e67654772616e64706146696e616c69747950656e64696e674368616e676553746f72656450656e64696e674368616e6765203c2054203a3a20426c6f636b4e756d626572202c2054203a3a2053657373696f6e4b6579203e4e6577417574686f726974696573204e657720617574686f726974792073657420686173206265656e206170706c6965642e5665633c2853657373696f6e4b65792c20753634293e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f6772616e6470612f7372632f6c69622e72736e616d65616c7265616479206d757461626c7920626f72726f776564616c726561647920626f72726f776564636f6e3a73746f3a4469676573744974656d206e6f7420657175616c6e6f7420616c6c6f77656420746f206661696c20696e2072756e74696d656e6f64657375627374726174652d6e6f646500df6acb689907609b0100000037e397fc7c91f5e40100000040fe3ad401f8959a01000000d2bc9897eed08f1501000000ed99c5acb25eedf501000000dd718d5cc53262d4010000004576656e7474696d657374616d70636f6e73656e73757362616c616e63657353657373696f6e73657373696f6e5374616b696e677374616b696e6744656d6f637261637964656d6f6372616379636f756e63696c636f756e63696c5f766f74696e67436f756e63696c4d6f74696f6e73636f756e63696c5f6d6f74696f6e734772616e6470616772616e64706154726561737572797472656173757279436f6e7472616374636f6e7472616374557067726164654b6579757067726164655f6b657973797374656d617572614e6f2076616c69642074696d657374616d7020696e20626c6f636b2e4f6e20656e74727920746f207468652066756e6374696f6e20606d6f64756c65602063616e2774206265204e6f6e653b207165644f6e20656e74727920746f207468652066756e6374696f6e20606d6f64756c65602063616e277420626520604e6f6e65603b2071656454696d657374616d702044696455706461746554696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f74696d657374616d702f7372632f6c69622e7273436f756e63696c566f74696e672050726f706f73616c73436f756e63696c566f74696e672050726f706f73616c4f66436f756e63696c566f74696e67205665746f656450726f706f73616c436f756e63696c566f74696e6720456e61637444656c6179506572696f6454696d657374616d7020426c6f636b506572696f6454696d657374616d704e6f7754203a3a204d6f6d656e74426c6f636b506572696f64446964557064617465626f6f6c20446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f20546865206d696e696d756d2028616e6420616476697365642920706572696f64206265747765656e20626c6f636b732e2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e54696d657374616d70204e6f7773657420536574207468652063757272656e742074696d652e2045787472696e736963207769746820746869732063616c6c2073686f756c6420626520706c616365642061742074686520737065636966696320706f736974696f6e20696e20746865206561636820626c6f636b2028737065636966696564206279207468652054726169743a3a54494d455354414d505f5345545f504f534954494f4e29207479706963616c6c7920617420746865207374617274206f6620746865206561636820626c6f636b2e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e74207370656369666965642062792060626c6f636b5f706572696f64602e6e6f773c543a3a4d6f6d656e7420617320486173436f6d706163743e3a3a54797065436f756e63696c566f74696e67436f6f6c6f6666506572696f64456e61637444656c6179506572696f6450726f706f73616c73566563203c20282054203a3a20426c6f636b4e756d626572202c2054203a3a20486173682029203e50726f706f73616c4f6654203a3a2050726f706f73616c50726f706f73616c566f74657273436f756e63696c566f74654f66282054203a3a2048617368202c2054203a3a204163636f756e74496420295665746f656450726f706f73616c282054203a3a20426c6f636b4e756d626572202c20566563203c2054203a3a204163636f756e744964203e2029204e756d626572206f6620626c6f636b7320627920776869636820746f2064656c617920656e6163746d656e74206f66207375636365737366756c2c206e6f6e2d756e616e696d6f75732d636f756e63696c2d696e7374696761746564207265666572656e64756d2070726f706f73616c732e70726f706f7365766f74657665746f7365745f636f6f6c6f66665f706572696f647365745f766f74696e675f706572696f64626c6f636b7370726f706f73616c5f68617368543a3a4861736870726f706f73616c617070726f7665426f783c543a3a50726f706f73616c3e7372632f6c6962636f72652f736c6963652f6d6f642e727354616c6c7943616e63656c6174696f6e54616c6c795265666572656e64756d204120766f74696e672074616c6c79206861732068617070656e656420666f722061207265666572656e64756d20766f74652e204c61737420746872656520617265207965732c206e6f2c206162737461696e20636f756e74732e204120766f74696e672074616c6c79206861732068617070656e656420666f722061207265666572656e64756d2063616e63656c6c6174696f6e20766f74652e48617368436f756e63696c566f74696e6720436f756e63696c566f74654f662f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f756e63696c2f7372632f766f74696e672e727354696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c426c6f636b506572696f643e206265747765656e2073657175656e7469616c20626c6f636b7354696d657374616d702065787472696e736963206d75737420626520617420706f736974696f6e2054696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b4e6f2076616c69642074696d657374616d7020696e686572656e7420696e20626c6f636b54696d657374616d7020746f6f2066617220696e2066757475726520746f20616363657074436f756e63696c566f74696e6720566f74696e67506572696f6470726f706f73657220776f756c64206e6f74206265206f6e20636f756e63696c6475706c69636174652070726f706f73616c73206e6f7420616c6c6f77656470726f706f73616c206973207665746f6564436f756e63696c566f74696e672050726f706f73616c566f746572736f6e6c7920636f756e63696c6c6f7273206d617920766f7465206f6e20636f756e63696c2070726f706f73616c736f6e6c7920636f756e63696c6c6f7273206d6179207665746f20636f756e63696c2070726f706f73616c7370726f706f73616c206d75737420657869737420746f206265207665746f6564436f756e63696c566f74696e6720436f6f6c6f6666506572696f646120636f756e63696c6c6f72206d6179206e6f74207665746f20612070726f706f73616c207477696365000001000000000000002000000000000000030000000000000003000000000000000300000001000000010000002000000000000000030000000000000003000000000000000300000001000000020000002000000000000000030000000000000003000000000000000300000053746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f6578656375746976652f7372632f6c69622e7273446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a204e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e436f6e73656e737573204f726967696e616c417574686f7269746965736c656e3a617574683a416c6c2065787472696e736963732073686f756c642062652070726f7065726c79207369676e6564416c6c2065787472696e736963732073686f756c6420686176652073656e6465722061626c6520746f207061792074686569722066656573416c6c2065787472696e736963732073686f756c6420686176652074686520636f7272656374206e6f6e6365626164207369676e617475726520696e2065787472696e7369635472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e72656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565766d20657865637574652072657475726e6564206572726f72207768696c652063616c6c656e766d656d6f727963616c6c6e6f7420656e6f7567682067617320746f20706179207472616e736665722066656572656163686564206d6178696d756d2064657074682c2063616e6e6f74206372656174656e6f7420656e6f7567682067617320746f2070617920626173652063726561746520666565636f6e747261637420616c726561647920657869737473766d20657865637574652072657475726e6564206572726f72207768696c652063726561746541757261204c61737454696d657374616d70000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f617572612f7372632f6c69622e7273000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72734f6e6c79206f6e6520626c6f636b206d617920626520617574686f7265642070657220736c6f742e2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f617572612f7372632f6c69622e72734175726120736c6f74206475726174696f6e2063616e6e6f74206265207a65726f2e74696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c00617474656d707420746f20646976696465206279207a65726f436f6e73656e7375734f726967696e616c417574686f726974696573566563203c2054203a3a2053657373696f6e4b6579203e7265706f72745f6d69736265686176696f726e6f74655f6f66666c696e6572656d61726b7365745f686561705f70616765737365745f636f64657365745f73746f726167652053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e6e65775665633c75383e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573753634204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b204e6f7465207468652070726576696f757320626c6f636b27732076616c696461746f72206d6973736564207468656972206f70706f7274756e69747920746f2070726f706f7365206120626c6f636b2e6f66666c696e653c543a3a496e686572656e744f66666c696e655265706f727420617320496e686572656e744f66666c696e655265706f72743e3a3a496e686572656e74205265706f727420736f6d65206d69736265686176696f75722e5f7265706f72743a636f646573657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a0909097165642f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f636f72652f73722d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e72732f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f6e73656e7375732f7372632f6c69622e7273010000000100000000000000200000000000000003000000000000000300000000000000030000003a6865617070616765736e6f74655f6f66666c696e652065787472696e736963206d75737420626520617420706f736974696f6e2020696e2074686520626c6f636b52657475726e207479706573206c656e6774682073686f756c642062652030206f72203173746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c696420747970650000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962616c6c6f632f736c6963652e7273436f756e63696c20566f74696e67506572696f64436f756e63696c20446573697265645365617473436f756e63696c20416374697665436f756e63696c436f756e63696c204e65787446696e616c697365436f756e63696c205465726d4475726174696f6e436f756e63696c2050726573656e746174696f6e4475726174696f6e436f756e63696c20566f74657273436f756e63696c20536e617073686f7465645374616b6573436f756e63696c204361727279436f756e74436f756e63696c204c6561646572626f617264436f756e63696c205265676973746572496e666f4f66436f756e63696c2043616e64696461746573436f756e63696c2043616e646964617465436f756e74436f756e63696c20566f7465436f756e74436f756e63696c2043616e646964616379426f6e6466696e616c6973652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e47757275206d656469746174696f6e000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f436f756e63696c43616e646964616379426f6e64566f74696e67426f6e6450726573656e74536c617368506572566f7465724361727279436f756e7450726573656e746174696f6e4475726174696f6e496e6163746976654772616365506572696f64566f7465496e646578566f74696e67506572696f645465726d4475726174696f6e446573697265645365617473416374697665436f756e63696c566563203c20282054203a3a204163636f756e744964202c2054203a3a20426c6f636b4e756d6265722029203e566f7465436f756e74417070726f76616c734f66566563203c20626f6f6c203e5265676973746572496e666f4f662820566f7465496e646578202c2075333220294c6173744163746976654f66566f7465727343616e6469646174657343616e646964617465436f756e744e65787446696e616c697365282054203a3a20426c6f636b4e756d626572202c20753332202c20566563203c2054203a3a204163636f756e744964203e2029536e617073686f7465645374616b6573566563203c2054203a3a2042616c616e6365203e4c6561646572626f617264566563203c20282054203a3a2042616c616e6365202c2054203a3a204163636f756e7449642029203e2047657420746865206c6561646572626f6172642069662077653b726520696e207468652070726573656e746174696f6e2070686173652e20546865207374616b6573206173207468657920776572652061742074686520706f696e7420746861742074686520766f746520656e6465642e20546865206163636f756e747320686f6c64696e672074686520736561747320746861742077696c6c206265636f6d652066726565206f6e20746865206e6578742074616c6c792e205468652070726573656e742063616e646964617465206c6973742e205468652070726573656e7420766f746572206c6973742e2054686520766f746520696e64657820616e64206c69737420736c6f742074686174207468652063616e646964617465206077686f60207761732072656769737465726564206f7220604e6f6e6560206966207468657920617265206e6f742063757272656e746c7920726567697374657265642e20546865206c61737420636c656172656420766f746520696e6465782074686174207468697320766f74657220776173206c617374206163746976652061742e2054686520746f74616c206e756d626572206f6620766f746573207468617420686176652068617070656e6564206f722061726520696e2070726f67726573732e205468652063757272656e7420636f756e63696c2e205768656e2074686572652773206120766f746520676f696e67206f6e2c20746869732073686f756c64207374696c6c206265207573656420666f7220657865637574697665206d6174746572732e204e756d626572206f66206163636f756e747320746861742073686f756c642062652073697474696e67206f6e2074686520636f756e63696c2e20486f77206c6f6e67206561636820706f736974696f6e2069732061637469766520666f722e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206d616e7920766f746573206e65656420746f20676f206279206166746572206120766f7465722773206c61737420766f7465206265666f726520746865792063616e2062652072656170656420696620746865697220617070726f76616c7320617265206d6f6f742e20486f77206c6f6e6720746f2067697665206561636820746f702063616e64696461746520746f2070726573656e74207468656d73656c7665732061667465722074686520766f746520656e64732e20486f77206d616e792072756e6e6572732d75702073686f756c64206861766520746865697220617070726f76616c73207065727369737420756e74696c20746865206e65787420766f74652e205468652070756e6973686d656e742c2070657220766f7465722c20696620796f752070726f7669646520616e20696e76616c69642070726573656e746174696f6e2e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f2062652061626c6520746f207375626d697420766f7465732e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f207375626d6974206f6e6527732063616e6469646163792e7365745f617070726f76616c73726561705f696e6163746976655f766f746572726574726163745f766f7465727375626d69745f63616e64696461637970726573656e745f77696e6e65727365745f646573697265645f736561747372656d6f76655f6d656d6265727365745f70726573656e746174696f6e5f6475726174696f6e7365745f7465726d5f6475726174696f6e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e74206120766f7465206265696e672070726573656e74656420666f722c2077696c6c20696e766f6b65206066696e616c6973655f766f7465602e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e746c79206120766f7465206265696e672070726573656e74656420666f722c2077696c6c636f756e743c543a3a426c6f636b4e756d62657220617320486173436f6d706163743e3a3a547970652052656d6f7665206120706172746963756c6172206d656d6265722e20412074616c6c792077696c6c2068617070656e20696e7374616e746c7920286966206e6f7420616c726561647920696e20612070726573656e746174696f6e20706572696f642920746f2066696c6c2074686520736561742069662072656d6f76616c206d65616e732074686174207468652064657369726564206d656d6265727320617265206e6f74206d65742e20546869732069732065666665637469766520696d6d6564696174656c792e416464726573733c543a3a4163636f756e7449642c20543a3a4163636f756e74496e6465783e20536574207468652064657369726564206d656d62657220636f756e743b206966206c6f776572207468616e207468652063757272656e7420636f756e742c207468656e2073656174732077696c6c206e6f7420626520757020656c656374696f6e207768656e2074686579206578706972652e204966206d6f72652c207468656e2061206e657720766f74652077696c6c2062652073746172746564206966206f6e65206973206e6f7420616c726561647920696e2070726f67726573732e436f6d706163743c7533323e20436c61696d207468617420607369676e656460206973206f6e65206f662074686520746f702053656c663a3a63617272795f636f756e742829202b2063757272656e745f766f746528292e312063616e646964617465732e204f6e6c7920776f726b73206966207468652060626c6f636b5f6e756d626572203e3d2063757272656e745f766f746528292e306020616e6420603c2063757272656e745f766f746528292e30202b2070726573656e746174696f6e5f6475726174696f6e2829606020607369676e6564602073686f756c642068617665206174206c6561737463616e646964617465746f74616c696e646578436f6d706163743c566f7465496e6465783e205375626d6974206f6e6573656c6620666f722063616e6469646163792e204163636f756e74206d757374206861766520656e6f756768207472616e736665727261626c652066756e647320696e20697420746f207061792074686520626f6e642e736c6f742052656d6f7665206120766f7465722e20416c6c20766f746573206172652063616e63656c6c656420616e642074686520766f746572206465706f7369742069732072657475726e65642e2052656d6f7665206120766f7465722e20466f72206974206e6f7420746f206265206120626f6e642d636f6e73756d696e67206e6f2d6f702c20616c6c20617070726f7665642063616e64696461746520696e6469636573206d757374206e6f772062652065697468657220756e72656769737465726564206f72207265676973746572656420746f20612063616e646964617465207468617420726567697374657265642074686520736c6f742061667465722074686520766f7465722067617665207468656972206c61737420617070726f76616c207365742e204d61792062652063616c6c656420627920616e796f6e652e2052657475726e732074686520766f746572206465706f73697420746f20607369676e6564602e7265706f727465725f696e64657877686f5f696e646578617373756d65645f766f74655f696e646578205365742063616e64696461746520617070726f76616c732e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e766f7465735665633c626f6f6c3e566f746572526561706564426164526561706572536c617368656454616c6c795374617274656454616c6c7946696e616c6973656420412074616c6c792028666f7220617070726f76616c20766f746573206f6620636f756e63696c2073656174287329292068617320656e646564202877697468206f6e65206f72206d6f7265206e6577206d656d62657273292e5665633c4163636f756e7449643e20412074616c6c792028666f7220617070726f76616c20766f746573206f6620636f756e63696c2073656174287329292068617320737461727465642e20736c6173686564207265617065722072656170656420766f7465722c207265617065722f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f636f756e63696c2f7372632f73656174732e72736e6f20617070726f76616c206368616e67657320647572696e672070726573656e746174696f6e20706572696f64696e636f727265637420766f746520696e646578436f756e63696c204c6173744163746976654f66436f756e63696c20566f74696e67426f6e64436f756e63696c20417070726f76616c734f6663616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f647265706f72746572206d757374206265206120766f746572766f746520696e646578206e6f742063757272656e7463616e6e6f74207265617020647572696e6720677261636520706572696474617267657420666f7220696e616374697669747920636c65616e7570206d75737420626520616374697665436f756e63696c20496e6163746976654772616365506572696f646261642074617267657420696e646578626164207265706f7274657220696e64657863616e6e6f742072657472616374207768656e2070726573656e74696e6763616e6e6f742072657472616374206e6f6e2d766f74657272657472616374696f6e20696e64657820696e76616c696472657472616374696f6e20696e646578206d69736d617463686475706c69636174652063616e646964617465207375626d697373696f6e696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e6473696e646578206e6f742063757272656e7463616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f6470726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e64736c6561646572626f617264206d757374206578697374207768696c652070726573656e742070686173652061637469766563616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c656374656463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726470726573656e7465642063616e646964617465206d7573742062652063757272656e74436f756e63696c2050726573656e74536c617368506572566f7465726475706c69636174652070726573656e746174696f6e696e636f727265637420746f74616c626164206f726967696e3a20657870656374656420746f206265206120726f6f74206f726967696e626164206f726967696e3a20657870656374656420746f2062652061207369676e6564206f726967696e626164206f726967696e3a20657870656374656420746f20626520616e20696e686572656e74206f726967696e42616c616e636573204672656542616c616e636500000000000042616c616e636573205472616e73616374696f6e4261736546656542616c616e636573205472616e73616374696f6e4279746546656542616c616e636573204578697374656e7469616c4465706f73697442616c616e63657320546f74616c49737375616e63656e6f7420656e6f7567682066756e647320666f72207472616e73616374696f6e2066656542616c616e63657320526573657276656442616c616e636553797374656d204163636f756e744e6f6e63653a65787472696e7369635f696e64657853797374656d204576656e747353797374656d20426c6f636b48617368000000000053797374656d204e756d62657253797374656d20506172656e744861736853797374656d2045787472696e73696373526f6f7453797374656d2052616e646f6d53656564426c6f636b206e756d626572206d6179206e65766572206265207a65726f2f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f73797374656d2f7372632f6c69622e727353797374656d2044696765737453797374656d2045787472696e7369634461746153797374656d4163636f756e744e6f6e636554203a3a204163636f756e74496454203a3a20496e64657845787472696e736963436f756e74753332426c6f636b4861736854203a3a20426c6f636b4e756d62657254203a3a204861736845787472696e73696344617461566563203c207538203e52616e646f6d536565644e756d626572506172656e744861736845787472696e73696373526f6f7444696765737454203a3a204469676573744576656e7473566563203c204576656e745265636f7264203c2054203a3a204576656e74203e203e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e53797374656d2045787472696e736963436f756e744d6f64756c6543616c6c42616c616e636573204372656174696f6e46656542616c616e636573205472616e7366657246656542616c616e636573546f74616c49737375616e636554203a3a2042616c616e63654578697374656e7469616c4465706f7369745265636c61696d5265626174655472616e736665724665654372656174696f6e4665654e657874456e756d53657454203a3a204163636f756e74496e646578456e756d536574566563203c2054203a3a204163636f756e744964203e4672656542616c616e6365526573657276656442616c616e63655472616e73616374696f6e426173654665655472616e73616374696f6e42797465466565205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e2054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e20285468697320697320646966666572656e7420616e642077686f6c6c7920756e72656c6174656420746f207468652060426f6e64616765602073797374656d207573656420696e20746865207374616b696e67206d6f64756c652e29205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420697320616c6f6e65207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865726d6f72652c20604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e75702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f20676574732054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e204174206c6561737420617320626967206173205265636c61696d5265626174652e205468652066656520726571756972656420746f206d616b652061207472616e736665722e2054686520616d6f756e7420637265646974656420746f20612064657374696e6174696f6e2773206163636f756e742077686f736520696e64657820776173207265636c61696d65642e20546865206d696e696d756d20616d6f756e7420616c6c6f77656420746f206b65657020616e206163636f756e74206f70656e2e2054686520746f74616c20616d6f756e74206f66207374616b65206f6e207468652073797374656d2e62656e6566696369617279206163636f756e74206d757374207072652d657869737442616c616e636573204e657874456e756d53657442616c616e636573205265636c61696d52656261746542616c616e63657320456e756d536574000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f72757374632f313439393764353661353530663461613939666537333735393363643237353832323761666335362f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000617474656d707420746f20646976696465206279207a65726f696e76616c6964206163636f756e7420696e6465786e6f7420656e6f75676820667265652066756e64737472616e736665727365745f62616c616e636520536574207468652062616c616e636573206f66206120676976656e206163636f756e742e77686f526177416464726573733c543a3a4163636f756e7449642c20543a3a4163636f756e74496e6465783e667265653c543a3a42616c616e636520617320486173436f6d706163743e3a3a547970657265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572207374616b65722e6465737476616c75650000000100000000000000200000000000000003000000000000000300000000000000030000000100000001000000200000000000000003000000000000000300000000000000030000007372632f6c6962636f72652f726573756c742e72733a20696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f686f6d652f6261737469616e2f70726f6a656374732f7061726974792f7375627374726174652f73726d6c2f62616c616e6365732f7372632f6c69622e72734e65774163636f756e745265617065644163636f756e745472616e73666572205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e4163636f756e74496442616c616e636520416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e4163636f756e74496e6465784e65774163636f756e744f7574636f6d65676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c756562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c75655f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e0041b08dc2000ba0a30100001000430000005e0a0000250000000000100043000000640a00002c000000e3841000280000004e6110004d0000008700000009000000e3841000280000004e6110004d00000090000000090000003001100067000000220100001700000005011000250000006302100012000000750210000f000000360210000a0000004002100014000000540210000f000000900210005a0000008800000016000000fd0210001c000000ea021000130000005f04000009000000190310001e000000ea021000130000005603000009000000100410006e000000c800000011000000f0041000480000009f0900000a000000ed05100012000000ff0510000c0000002f0610000b000000000000005806100010000000000000000878100000000000000000000000000010881000010000000000000000000000680610000f00000000000000087810000000000000000000000000001888100001000000000000008c061000250000007706100015000000c006100019000000e00610004d00000052000000220000004f07100011000000ea17100017000000f502000005000000a00710004600000081010000130000001d00000004000000040000001e0000001f00000020000000e608100020000000060910001200000021000000000000000100000022000000e009100006000000e60910002200000049561000180000002d09000005000000080a1000160000001e0a10000d000000495610001800000033090000050000008e0b10000b00000092171000160000002b0a100001000000780b1000160000002c08000009000000701710000e0000007e1710000400000082171000100000002b0a100001000000780b1000160000003008000005000000301710002b0000005b1710001500000063010000150000008e0b10000b000000990b100026000000bf0b100008000000c70b1000060000002b0a100001000000780b1000160000003d080000050000000878100000000000e60b100002000000d00b1000160000005604000011000000d00b1000160000004a04000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20100c10004a000000600e100000020000601010003700000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b0200010202020203020202020402050602020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202070202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202f00b1000200000003100000019000000f00b1000200000003200000020000000f00b1000200000003400000019000000f00b1000200000003500000018000000f00b100020000000360000002000000008781000000000005b17100015000000f003000005000000c617100024000000ea171000170000004b02000009000000000000009f5c1000040000000000000088901000040000000000000000000000e890100002000000000000000000000000000000771810000600000000000000f89010000400000000000000000000005891100009000000000000000100000000000000788410000400000000000000b33210000c000000000000007c84100005000000000000001b8410002000000000000000571a10000900000000000000601a10001c00000000000000851a10000400000000000000b35f100007000000891a10004a000000891a10004a000000000000004e1a100009000000000000001b8410002000000000000000571a10000900000000000000601a10001c000000000000007c1a10000900000000000000b35f10000700000000000000851a10000400000000000000b35f1000070000007d181000530000000878100000000000d0181000210000000878100000000000f118100050000000411910002e0000006f1910005b000000ca19100057000000211a10002d00000000000000af541000090000000000000000000000e41a100011000000000000000000000000000000000000009092100001000000000000000100000000000000e05410000a0000000100000000000000057a10000900000000000000f51a10001a0000000000000098921000010000000000000000000000000000000f1b1000060000000100000000000000057a10000900000000000000151b10004900000000000000a092100001000000000000000000000000000000e12d10000d0000000000000000000000e97910000300000000000000000000000000000000000000a8921000010000000000000001000000ec1b100026000000b91b100033000000701b1000490000005e1b10001200000000000000de5510000700000000000000109310000200000000000000000000000878100000000000000000000000000000000000e55510000400000000000000409310000300000000000000000000000878100000000000000000000100000000000000664b100009000000000000004a6f10000c000000000000002a5610000800000000000000121c10001b000000000000002a56100008000000000000002356100007000000000000004470100005000000000000004731100016000000000000003256100007000000000000001a5210000400000000000000628510000800000000000000e0931000030000000000000000000000f89310000100000000000000000000002d1c1000070000000000000088cf1000020000000000000000000000009410000100000000000000968510000900000096851000090000009f851000070000006b1c10005d000000341c100037000000e384100028000000c81c100040000000930000000100000000000000743410000800000000000000fc9410000400000000000000000000001c951000010000000000000000000000081d10000500000000000000249510000500000000000000000000004c9510000200000000000000000000000d1d100008000000000000005c95100001000000000000000000000064951000010000000000000000000000151d10000b000000000000005c9510000100000000000000000000006c9510000100000000000000000000005c4c10000800000000000000749510000200000000000000000000008495100001000000000000009685100009000000ee2d10000d0000001b57100004000000e979100003000000461e10005900000096851000090000001b571000040000001a52100004000000e979100003000000e979100003000000c71d100042000000091e10003d0000001b57100004000000961d100031000000611d1000350000001b571000040000001a52100004000000201d100041000000e3841000280000009f1e10004300000044000000010000002d1f100036000000603f10005d000000fb00000005000000f01e10003d000000603f10005d00000002010000050000002d1f100036000000603f10005d0000001001000005000000603f10005d00000017010000050000008686100023000000c81c10004000000093000000010000002100000000000000010000002300000024000000250000002600000086861000230000009f1e1000430000004400000001000000b020100048000000a50900000e0000008021100039000000c0211000480000001a0200002d00000000000000082210000e0000000000000000000000e979100003000000000000000000000000000000000000005c9b10000100000000000000010000000000000016221000150000000000000000000000e97910000300000000000000000000000000000000000000649b1000010000000000000001000000000000002b2210000e0000000000000000000000f579100010000000000000000000000000000000000000006c9b100001000000000000000100000000000000392210000d0000000000000000000000462210000700000000000000000000000000000000000000749b1000010000000000000001000000000000004d2210000c00000000000000000000004622100007000000000000000000000000000000000000007c9b10000100000000000000010000000000000059221000110000000000000000000000e97910000300000000000000000000000000000000000000849b1000010000000000000001000000000000006a2210000f0000000000000000000000f579100010000000000000000000000000000000000000008c9b100001000000000000000100000000000000792210000a0000000000000000000000f57910001000000000000000000000000000000000000000949b10000100000000000000010000000000000083221000140000000100000000000000c37910000e00000000000000972210001f000000000000009c9b100001000000000000000100000000000000b62210000a0000000000000000000000887b10001600000000000000000000000000000000000000a49b100001000000000000000100000000000000c02210000a0000000100000000000000c37910000e00000000000000c37910000e00000000000000ac9b100001000000000000000000000000000000ca2210000d0000000100000000000000c37910000e00000000000000887b10001600000000000000b49b100001000000000000000100000000000000d7221000140000000100000000000000c37910000e00000000000000887b10001600000000000000bc9b100001000000000000000100000000000000eb221000140000000000000000000000247b10000c00000000000000000000000000000000000000749b100001000000000000000100000000000000ff221000130000000000000000000000247b10000c000000000000000000000000000000000000007c9b10000100000000000000010000000000000012231000120000000000000000000000f57910001000000000000000000000000000000000000000c49b10000100000000000000000000000000000024231000130000000000000000000000f57910001000000000000000000000000000000000000000cc9b100001000000000000000100000000000000372310000a0000000000000000000000412310001700000000000000000000000000000000000000d49b10000100000000000000010000000000000043461000070000000100000000000000c37910000e00000000000000f57910001000000000000000dc9b100001000000000000000100000000000000582310000a0000000100000000000000c37910000e00000000000000e97910000300000000000000e49b100001000000000000000100000000000000622310000d00000000000000000000006f2310000400000000000000000000000000000000000000ec9b1000010000000000000000000000572710002a0000000727100050000000de2610002900000096261000480000004226100054000000f42510004e000000c62510002e000000af251000170000008d2510002200000064251000290000003c251000280000001725100025000000d624100041000000b2241000240000007a241000380000003e2410003c000000012410003d0000008d23100074000000732310001a00000000000000f9291000050000000000000008781000000000000000000000000000d49d100003000000000000000000000000000000fe2910000700000000000000ec9d1000010000000000000000000000049e100003000000000000000100000000000000052a100008000000000000001c9e100001000000000000000000000008781000000000000000000002000000000000000d2a10000a00000000000000349e10000100000000000000000000004c9e100002000000000000000300000000000000172a100014000000000000005c9e10000200000000000000000000008c9e1000030000000000000004000000000000002b2a10001400000000000000c0a91000010000000000000000000000a49e1000010000000000000005000000000000003f2a10001400000000000000c0a91000010000000000000000000000ac9e100001000000000000000600000000000000532a10001300000000000000b49e1000010000000000000000000000cc9e100001000000000000000700000000000000662a10000d00000000000000e0a91000010000000000000000000000d49e100002000000000000000800000000000000732a10001700000000000000b49e1000010000000000000000000000e49e1000010000000000000009000000792d1000300000000878100000000000422d10003700000000000000542c100010000000000000004a6f10000c000000122d1000300000000878100000000000422d100037000000000000000c2d10000600000000000000646e10002600000000000000002d10000c000000000000004a6f10000c000000832c100044000000c72c10003900000000000000542c100010000000000000004a6f10000c00000000000000642c10000500000000000000692c10001a000000b82b10005600000008781000000000000e2c100046000000922b100026000000662b10002c00000000000000b05f100003000000000000004a6f10000c000000462b100020000000ae2a10004f000000fd2a1000490000008a2a10002400000000000000a92d10000c0000000000000000000000b52d10000700000000000000000000000000000000000000cca0100002000000000000000100000000000000bc2d1000130000000000000000000000247b10000c00000000000000000000000000000000000000dca0100001000000000000000100000000000000cf2d10000b0000000000000000000000f57910001000000000000000000000000000000000000000e4a0100001000000000000000100000000000000da2d1000040000000000000000000000b52d10000700000000000000000000000000000000000000eca0100001000000000000000100000000000000de2d1000030000000000000000000000247b10000c00000000000000000000000000000000000000f4a0100001000000000000000100000000000000e12d10000d0000000000000000000000ee2d10000d00000000000000000000000000000000000000fca0100001000000000000000100000000000000af541000090000000100000000000000ee2d10000d00000000000000fb2d10002a0000000000000004a1100001000000000000000000000000000000252e10000900000000000000000000002e2e100015000000000000000000000000000000000000000ca11000010000000000000001000000b42f1000540000000830100037000000622f100052000000402f100022000000fc2e100044000000c92e100033000000a02e100029000000812e10001f000000432e10003e000000000000003f3010000d0000000000000004a2100002000000000000000000000034a21000030000000000000000000000000000004c30100007000000000000004ca2100001000000000000000000000064a21000010000000000000001000000000000005330100009000000000000006ca21000040000000000000000000000cca21000010000000000000002000000000000005c3010000f00000000000000d4a21000010000000000000000000000eca21000010000000000000003000000000000006b3010001000000000000000d4a21000010000000000000000000000f4a21000020000000000000004000000000000007c84100005000000000000001b84100020000000000000008c3210000b00000000000000646e100026000000df3110004b0000002a3210004d000000773210001500000000000000d831100007000000000000001b84100020000000ab3110002d00000000000000793110000d00000000000000b52d100007000000000000008631100015000000000000001b84100020000000000000009b3110000c00000000000000756d10002400000000000000a73110000400000000000000b52d1000070000005d3110001c000000000000003c3110000b000000000000004731100016000000fd3010003f0000007b30100057000000d23010002b00000000000000a9321000030000000000000000000000c37910000e000000000000000000000000000000000000000878100000000000000000000100000000000000ac321000070000000000000098c410000100000000000000000000000878100000000000000000000000000000000000213c10000700000000000000a0a310000100000000000000000000000878100000000000000000000100000000000000b05f10000300000000000000b33210000c000000c032100019000000c021100048000000c50100002d00000000000000d932100008000000000000000878100000000000000000000000000028a41000010000000000000000000000e13210000a0000000000000000d8100001000000000000000000000030a410000100000000000000293310001a000000eb3210003e00000000000000433310000600000000000000bca41000010000000000000000000000c4a41000010000000000000000000000493310000e00000000000000cca41000020000000000000000000000dca410000200000000000000000000004d2210000c00000000000000eca41000020000000000000000000000fca4100001000000000000009f851000070000003c341000380000009685100009000000e979100003000000a233100055000000f73310004500000096851000090000009f85100007000000573310004b00000000000000743410000800000000000000e0a51000010000000000000000000000e8a510000100000000000000000000007c3410000800000000000000bca41000010000000000000000000000f0a51000010000000000000000000000843410000700000000000000f8a5100003000000000000000000000010a610000100000000000000000000008b3410000500000000000000bca4100001000000000000000000000018a61000010000000000000000000000903410000800000000000000bca4100001000000000000000000000020a610000100000000000000ee2d10000d000000613510000e000000273510003a000000ee2d10000d0000009f8510000700000096851000090000000735100020000000e434100023000000983410004c000000e3841000280000006f3510003f0000006500000001000000e384100028000000ae351000400000004400000001000000e384100028000000ee351000430000002e0000000100000080291000480000009f0900000a00000086861000230000006f3510003f00000065000000010000008686100023000000ae3510004000000044000000010000008686100023000000ee351000430000002e000000010000007039100039000000b0391000480000001a0200002d00000000000000f83910000a0000000000000000000000887b10001600000000000000000000000000000000000000c0a8100001000000000000000100000000000000023a10000d0000000000000000000000f57910001000000000000000000000000000000000000000c8a81000010000000000000001000000000000000f3a10000c0000000000000000000000f57910001000000000000000000000000000000000000000d0a81000010000000000000001000000000000001b3a10000c0000000000000000000000fb5110000b00000000000000000000000000000000000000d8a8100001000000000000000100000000000000273a10001100000000000000000000001a5210000400000000000000000000000000000000000000e0a8100002000000000000000000000000000000383a1000100000000000000000000000f57910001000000000000000000000000000000000000000f0a8100001000000000000000000000000000000483a10000a0000000100000000000000c37910000e00000000000000523a10000f00000000000000f8a8100001000000000000000000000000000000613a1000110000000000000000000000f5791000100000000000000000000000000000000000000000a91000010000000000000000000000023c10001f000000e33b10001f000000c53b10001e0000009d3b100028000000df3a10005e0000003d3b100060000000af3a1000300000008b3a100024000000723a10001900000000000000213c1000070000000000000098a91000010000000000000000000000b0a9100002000000000000000000000000000000283c10000a00000000000000c0a91000010000000000000000000000d8a9100001000000000000000100000000000000323c10001100000000000000e0a91000010000000000000000000000f8a9100001000000000000000200000000000000223d10000300000000000000253d10000d000000c13c100058000000193d10000900000000000000b05f10000300000000000000756d100024000000663c10005b00000000000000593c10000d000000000000001a52100004000000433c100016000000b03d100048000000bb01000023000000b03d100048000000bc01000023000000893d10001c0000004956100018000000ee0300000d000000403d100049000000910200001d000000403d100049000000a70000003a000000403d100049000000ae0000003000000000000000f83d10000a0000000000000094aa10000100000000000000000000009caa10000200000000000000793e10000b000000023e100055000000573e100022000000e384100028000000843e10003f0000005a000000010000008686100023000000843e10003f0000005a00000001000000e83e10000d000000cd3e10001b000000c33e10000a0000000301000001000000f53e100010000000053f10000f000000143f100013000000273f10000f000000363f1000140000004a3f100016000000e384100028000000bd3f1000470000005a000000080000009044100039000000b0431000480000001a0200002d0000004044100048000000a50900000e0000009043100019000000b043100048000000c50100002d00000000000000c94410000f0000000000000000000000d8441000090000000000000000000000000000000000000008af100001000000000000000100000000000000e14410000b0000000000000000000000ec441000360000000000000000000000000000000000000010af10000100000000000000010000000000000022451000090000000100000000000000d844100009000000000000002b451000290000000000000018af100001000000000000000000000000000000544510000c0000000000000000000000f5791000100000000000000000000000000000000000000020af100001000000000000000100000000000000604510000e0000000000000000000000247b10000c0000000000000000000000000000000000000028af1000010000000000000001000000000000006e4510000b0000000000000000000000f5791000100000000000000000000000000000000000000030af100001000000000000000100000000000000794510000e0000000000000000000000874510000b0000000000000000000000000000000000000038af100001000000000000000100000000000000156610000c0000000000000000000000f57910001000000000000000000000000000000000000000a8ca100001000000000000000100000000000000924510000f0000000000000000000000a14510000f0000000000000000000000000000000000000040af100001000000000000000100000000000000b0451000090000000000000000000000a14510000f0000000000000000000000000000000000000048af100001000000000000000100000000000000b9451000100000000100000000000000a14510000f00000000000000c9451000370000000000000050af100001000000000000000000000000000000004610000d0000000100000000000000f579100010000000000000000d461000360000000000000058af10000100000000000000010000000000000043461000070000000100000000000000c37910000e00000000000000f5791000100000000000000060af1000010000000000000001000000000000004a461000090000000100000000000000a14510000f00000000000000887b1000160000000000000068af100001000000000000000100000000000000534610000600000001000000000000005946100024000000000000007d461000040000000000000070af10000300000000000000010000006c4a10003d0000004c4a1000200000002b4a100021000000f249100039000000a54910004d0000007049100035000000fa48100076000000ac4810004e0000007a481000320000004d4810002d0000001d48100030000000e947100034000000c0471000290000008146100075000000f646100072000000684710005800000000000000de5510000700000000000000a8b01000020000000000000000000000d8b0100001000000000000000000000000000000a94a10000600000000000000e0b01000010000000000000000000000d8b0100001000000000000000100000000000000e55510000400000000000000f8b0100002000000000000000000000028b1100002000000000000000200000000000000af4a1000100000000000000038b1100003000000000000000000000080b1100001000000000000000300000000000000bf4a1000110000000000000088b11000010000000000000000000000a0b1100001000000000000000400000000000000d04a10000d00000000000000a8b11000020000000000000000000000d8b11000010000000000000005000000000000002a56100008000000000000003956100010000000000000007c84100005000000000000001b841000200000000f4c100028000000000000002a5610000800000000000000fd4b10001200000000000000314b100009000000000000003a4b10001800000000000000e555100004000000000000007d46100004000000814b10004d000000ce4b10002f000000000000002a5610000800000000000000395610001000000000000000664b100009000000000000006f4b10000d000000000000007c4b10000500000000000000094b10000e000000524b10001400000000000000314b100009000000000000003a4b1000180000001c4b10001500000000000000054b10000400000000000000094b10000e00000000000000174b10000500000000000000e979100003000000dd4a10002800000000000000374c10000600000000000000e8b21000030000000000000000000000087810000000000000000000000000003d4c1000070000000000000000b3100002000000000000000000000008781000000000000000000000000000444c1000060000000000000010b31000010000000000000000000000087810000000000000000000000000004a4c1000090000000000000010b3100001000000000000000000000008781000000000000000000000000000534c1000090000000000000010b31000010000000000000000000000087810000000000000000000000000005c4c1000080000000000000018b31000020000000000000000000000087810000000000000000000d8441000090000009f85100007000000567310000e000000a14510000f0000006f4b10000d000000a14510000f000000a14510000f0000001a52100004000000e384100028000000644c10004100000058000000010000008686100023000000644c100041000000580000000100000000000000114e10000d00000000000000000000001e4e10003a0000000000000000000000000000000000000008781000000000000000000000000000000000002c5f1000120000000000000018c4100001000000000000000000000030c4100001000000000000000000000000000000584e10000e00000000000000f0b31000010000000000000000000000f8b3100001000000000000008a4e100016000000664e100024000000e384100028000000a04e10003f000000b1000000010000008686100023000000a04e10003f000000b100000001000000625010000600000027000000b74f10000800000028000000c64f10000700000029000000d44f1000070000002a000000e44f1000090000002b000000ed4f1000070000002c000000f44f10000e0000002d000000105010000f0000002e00000026501000070000002f000000355010000800000030000000455010000800000031000000575010000b00000032000000000000006250100006000000000000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000068501000040000000000000033000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000a54f1000090000000000000035000000000000000000000000000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000ae4f1000090000000000000037000000000000000000000000000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000b74f1000080000000000000039000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000c64f100007000000000000003b000000000000000000000000000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000d44f100007000000000000003d000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000e44f100009000000000000003f000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000ed4f1000070000000000000041000000000000000000000000000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000f44f10000e0000000000000043000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000105010000f00000000000000450000000000000000000000000000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000002650100007000000000000004700000000000000000000000000000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000035501000080000000000000049000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004550100008000000000000004b000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000575010000b000000000000004c000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000ef5110000900000000000000a54f1000090000000000000000000000f95e10000900000000000000ae4f10000900000001000000000000000f7b10000800000000000000b74f1000080000000200000000000000bf4f10000700000000000000c64f1000070000000300000000000000cd4f10000700000000000000d44f1000070000000400000000000000db4f10000900000000000000e44f1000090000000500000000000000a96510000700000000000000ed4f1000070000000600000000000000855410000d00000000000000f44f10000e0000000700000000000000025010000e00000000000000105010000f00000008000000000000001f5010000700000000000000265010000700000009000000000000002d501000080000000000000035501000080000000a000000000000003d501000080000000000000045501000080000000b000000000000004d5010000a00000000000000575010000b0000000c000000055110002b0000003051100041000000760000000400000000000000f8511000030000000000000000000000fb5110000b0000000000000000000000000000000000000020bc100001000000000000000100000000000000065210000b0000000000000000000000fb5110000b0000000000000000000000000000000000000028bc100001000000000000000100000000000000115210000900000000000000000000001a521000040000000000000000000000000000000000000030bc10000100000000000000010000007c521000240000004b521000310000001e5210002d00000000000000ad521000030000000000000068bc100001000000000000000000000080bc100008000000000000000000000000000000635410000300000000000000665410001f000000b0521000160000000878100000000000c6521000550000001b5310005b000000765310005d000000d35310002f0000000878100000000000025410006100000000000000925410000d0000000000000000000000f579100010000000000000000000000000000000000000000878100000000000000000000100000000000000156610000c0000000000000000000000f5791000100000000000000000000000000000000000000008781000000000000000000001000000000000009f541000100000000000000000000000f57910001000000000000000000000000000000000000000a0be100001000000000000000100000000000000af541000090000000000000000000000b854100028000000000000000000000000000000000000000878100000000000000000000100000000000000e05410000a0000000100000000000000057a10000900000000000000ea5410000d000000000000000878100000000000000000000000000000000000f75410000e0000000100000000000000057a10000900000000000000887b100016000000000000000878100000000000000000000100000000000000055510000d0000000100000000000000125510001e000000000000001a52100004000000000000000878100000000000000000000000000000000000305510000e0000000100000000000000057a100009000000000000003e5510002d00000000000000087810000000000000000000000000006b5510007300000000000000de551000070000000000000098bf10000100000000000000000000000878100000000000000000000000000000000000e55510000400000000000000b0bf10000200000000000000000000000878100000000000000000000100000000000000e95510000400000000000000e0bf10000100000000000000000000000878100000000000000000000200000000000000ed5510001200000000000000f8bf10000100000000000000000000000878100000000000000000000300000000000000ff5510001100000000000000f8bf100001000000000000000000000008781000000000000000000004000000000000002a56100008000000000000003956100010000000000000002a56100008000000000000002356100007000000000000003256100007000000000000001a5210000400000000000000165610000d00000000000000235610000700000000000000105610000600000000000000756d1000240000000000000061561000100000000000000068c0100004000000000000000000000088c01000020000000000000000000000715610000f0000000000000068c0100004000000000000000000000098c0100002000000000000001b57100004000000e979100003000000e979100003000000e979100003000000db56100040000000b3561000280000008056100033000000b356100028000000e38410002800000030511000410000005700000001000000e3841000280000003a571000420000002200000001000000868610002300000030511000410000005700000001000000f05710003000000030511000410000006500000004000000c857100028000000396210000d000000305110004100000066000000040000007c5710004c00000030511000410000006b0000000400000086861000230000003a5710004200000022000000010000000a5c10001c000000445a1000410000006400000003000000e65b100024000000445a1000410000006c00000003000000a05b10002c000000445a100041000000a60000004c000000685b100038000000445a100041000000a40000002a000000405b100028000000445a100041000000a500000032000000e85a100032000000ac5a10002d000000d95a10000c000000e55a100003000000445a100041000000cc00000003000000855a100027000000445a100041000000d4000000040000001c5a100028000000445a100041000000da000000030000004e00000018000000040000004f0000005000000051000000520000008c5e100022000000505e10003c0000009e00000003000000285e100028000000505e10003c000000a400000003000000e05d1000480000009f0900000a000000605d100039000000a05d10003c0000006500000014000000e05e100019000000a05d10003c0000008d0000001e00000000000000025f1000130000000000000000000000155f1000170000000000000000000000000000000000000008781000000000000000000000000000000000002c5f1000120000000000000018c4100001000000000000000000000030c41000010000000000000000000000000000003e5f10000c0000000000000038c4100001000000000000000000000050c41000010000000000000001000000000000004a5f1000060000000000000058c4100001000000000000000000000070c4100001000000000000000200000000000000505f10000e0000000000000078c4100001000000000000000000000090c41000010000000000000003000000000000005e5f1000080000000000000098c41000010000000000000000000000b0c4100001000000000000000400000000000000665f10000b00000000000000b8c41000010000000000000000000000d0c4100001000000000000000500000000000000d26010000700000000000000b35f100007000000b86010001a000000000000007460100007000000000000007b6010003d0000002360100051000000000000001c6010000700000000000000b35f100007000000016010001b00000000000000f95f10000500000000000000fe5f100003000000ba5f10003f00000000000000b05f10000300000000000000b35f1000070000009e5f100012000000000000008c5f10000500000000000000915f10000d000000715f10001b000000e3841000280000004e6110004d0000003701000009000000e3841000280000009b61100041000000c20000000100000086861000230000009b61100041000000c2000000010000000e6210002b000000396210000d0000009b61100041000000ce00000004000000a0621000480000009f0900000a000000f062100045000000cb0200001e000000f062100045000000ce02000036000000706510003900000020651000480000001a0200002d000000b0641000480000009f0900000a00000000651000190000002065100048000000c50100002d000000b064100048000000a50900000e00000000000000b06510000d0000000000000000000000247b10000c0000000000000000000000000000000000000070ca100001000000000000000100000000000000bd6510000a0000000000000000000000247b10000c0000000000000000000000000000000000000078ca100001000000000000000100000000000000c7651000140000000000000000000000247b10000c0000000000000000000000000000000000000080ca100001000000000000000100000000000000db6510000a0000000000000000000000e9791000030000000000000000000000000000000000000088ca100001000000000000000100000000000000e5651000140000000000000000000000f5791000100000000000000000000000000000000000000090ca100001000000000000000100000000000000f96510001300000000000000000000000c661000090000000000000000000000000000000000000098ca100002000000000000000100000000000000156610000c0000000000000000000000f57910001000000000000000000000000000000000000000a8ca100001000000000000000100000000000000216610000c0000000000000000000000f57910001000000000000000000000000000000000000000b0ca1000010000000000000001000000000000002d6610000c0000000000000000000000e97910000300000000000000000000000000000000000000b8ca100001000000000000000100000000000000396610000d0000000000000000000000466610002d00000000000000000000000000000000000000c0ca100002000000000000000100000000000000736610000900000000000000000000000c6610000900000000000000000000000000000000000000d0ca1000010000000000000001000000000000007c6610000b0000000100000000000000c37910000e00000000000000876610000c00000000000000d8ca100001000000000000000100000000000000936610000e0000000100000000000000c37910000e00000000000000a16610001300000000000000e0ca100002000000000000000000000000000000b46610000c0000000100000000000000c37910000e000000000000000c6610000900000000000000d8ca100001000000000000000000000000000000c0661000060000000000000000000000887b10001600000000000000000000000000000000000000f0ca100001000000000000000100000000000000c66610000a0000000000000000000000887b10001600000000000000000000000000000000000000f8ca100001000000000000000100000000000000d06610000e0000000000000000000000e979100003000000000000000000000000000000000000000878100000000000000000000100000000000000de6610000c0000000000000000000000ea661000330000000000000000000000000000000000000000cb1000010000000000000000000000000000001d6710001000000000000000000000002d671000140000000000000000000000000000000000000008cb100001000000000000000100000000000000416710000b00000000000000000000004c671000290000000000000000000000000000000000000010cb1000010000000000000000000000da6b100041000000986b100042000000556b100043000000086b10004d000000b96a10004f0000004b6a10005a000000a56a1000140000001d6a10002e000000f769100026000000bd6910003a000000596910005b000000b4691000090000001869100041000000d868100040000000636810005f000000c2681000160000004b681000180000002f6810001c000000e767100048000000ad6710003a0000007567100038000000000000001b6c10000d00000000000000c8cc1000020000000000000000000000f8cc100002000000000000000000000000000000286c1000130000000000000008cd100004000000000000000000000068cd1000050000000000000001000000000000003b6c10000d0000000000000090cd1000010000000000000000000000a8cd100001000000000000000200000000000000486c10001000000000000000b0cd1000010000000000000000000000c8cd100003000000000000000300000000000000586c10000e00000000000000e0cd100003000000000000000000000028ce100003000000000000000400000000000000666c1000110000000000000040ce100001000000000000000000000058ce100003000000000000000500000000000000776c10000d0000000000000070ce100001000000000000000000000088ce100003000000000000000600000000000000846c10001900000000000000a0ce1000010000000000000000000000b8ce1000020000000000000007000000000000009d6c10001100000000000000a0ce1000010000000000000000000000c8ce100002000000000000000800000000000000b97210000500000000000000be721000090000000000000044701000050000000000000049701000120000005172100058000000a97210001000000000000000287210000e000000000000004a6f10000c00000000000000eb8310000300000000000000646e100026000000000000003672100009000000000000004a6f10000c000000000000003f721000120000000000000049701000120000000c71100058000000647110005c000000c0711000280000000878100000000000e871100040000000000000004470100005000000000000004a6f10000c000000c17010004b00000000000000bd70100004000000000000004a6f10000c0000005b7010001e0000000878100000000000797010004400000000000000367010000900000000000000646e100026000000000000003f70100005000000000000001b84100020000000000000004470100005000000000000004970100012000000566f100059000000af6f100069000000187010001e00000000000000706d100005000000000000004a6f10000c0000008a6e100059000000e36e10005a0000003d6f10000d00000000000000eb8310000300000000000000646e100026000000996d10005c000000f56d100050000000456e10001f00000000000000706d10000500000000000000756d1000240000001a6d100056000000026d100018000000ae6c100054000000026d10001800000000000000c77210000b0000000000000088cf100002000000000000000000000098cf1000010000000000000000000000d2721000100000000000000000d81000010000000000000000000000a0cf1000010000000000000000000000e27210000c00000000000000a8cf1000010000000000000000000000b0cf1000010000000000000000000000ee7210000e00000000000000b8cf1000020000000000000000000000c8cf1000010000000000000096851000090000009685100009000000b073100015000000a17310000f000000e979100003000000647310003d000000567310000e000000567310000e000000fc7210005a000000e384100028000000c57310004100000058000000010000008686100023000000c5731000410000005800000001000000347910001e000000527910003e000000370100000300000000000000b77910000c0000000100000000000000c37910000e00000000000000d17910000a000000000000000878100000000000000000000100000000000000db7910000e0000000000000000000000e979100003000000000000000000000000000000000000000878100000000000000000000000000000000000ec791000090000000100000000000000f57910001000000000000000057a1000090000000000000008781000000000000000000001000000000000000e7a10000d0000000100000000000000e979100003000000000000001b7a10000a000000000000000878100000000000000000000100000000000000257a10000a0000000000000000000000057a1000090000000000000000000000000000000000000008781000000000000000000001000000000000002f7a1000060000000000000000000000f5791000100000000000000000000000000000000000000070d2100001000000000000000100000000000000357a10000a0000000000000000000000057a1000090000000000000000000000000000000000000008781000000000000000000001000000000000003f7a10000e0000000000000000000000057a1000090000000000000000000000000000000000000008781000000000000000000001000000000000004d7a1000060000000000000000000000537a10000b0000000000000000000000000000000000000008781000000000000000000001000000000000005e7a1000060000000000000000000000647a1000220000000000000000000000000000000000000008781000000000000000000001000000867a10004200000000000000177b10000d0000000000000000000000247b10000c000000000000000000000000000000000000000cd5100001000000000000000100000000000000307b1000120000000000000000000000247b10000c0000000000000000000000000000000000000014d5100001000000000000000100000000000000427b10000d0000000000000000000000247b10000c000000000000000000000000000000000000001cd51000010000000000000001000000000000004f7b10000b0000000000000000000000247b10000c0000000000000000000000000000000000000024d51000010000000000000001000000000000005a7b10000b0000000000000000000000247b10000c000000000000000000000000000000000000002cd5100001000000000000000100000000000000657b10000b0000000000000000000000707b1000110000000000000000000000000000000000000034d5100001000000000000000100000000000000817b1000070000000100000000000000707b10001100000000000000887b100016000000000000003cd51000010000000000000001000000000000009e7b10000b0000000100000000000000c37910000e00000000000000247b10000c0000000000000044d510000b000000000000000100000000000000a97b10000f0000000100000000000000c37910000e00000000000000247b10000c000000000000009cd510000c000000000000000100000000000000b87b1000120000000000000000000000247b10000c00000000000000000000000000000000000000fcd5100001000000000000000100000000000000ca7b1000120000000000000000000000247b10000c0000000000000000000000000000000000000004d6100001000000000000000100000052821000290000001e82100034000000d48110004a000000af811000250000006681100049000000478110001f0000003181100016000000fd7e1000270000000878100000000000247f100053000000777f10005a000000d17f100055000000268010004f0000007580100050000000c5801000150000000878100000000000da80100057000000b87e100045000000567c10005d000000b37c1000270000000878100000000000da7c10005b000000357d10005c000000917d10004a0000000878100000000000db7d10005d000000387e10002d0000000878100000000000657e100053000000b87e1000450000001f7c100037000000dc7b10004300000070831000190000002083100048000000c50100002d000000e08210003900000020831000480000001a0200002d00000000000000b383100008000000000000009cd61000020000000000000000000000ccd6100001000000000000000000000000000000bb8310000b00000000000000d4d610000300000000000000000000001cd7100001000000000000000100000000000000788410000400000000000000ee83100029000000000000007c84100005000000000000001b84100020000000438410003500000000000000eb8310000300000000000000ee83100029000000000000001784100004000000000000001b84100020000000000000003b84100008000000000000001b84100020000000c6831000250000000878100000000000e184100002000000cc84100015000000f103000005000000e3841000280000000b851000400000008900000001000000000000004b8510000a00000000000000e0d71000030000000000000000000000f8d71000010000000000000000000000558510000d0000000000000000d8100001000000000000000000000008d8100001000000000000000000000062851000080000000000000010d8100004000000000000000000000030d8100001000000000000009685100009000000d88510000c000000e485100011000000bd8510001b0000009685100009000000a685100017000000968510000900000096851000090000009f851000070000009f851000070000006a8510002c00000086861000230000000b8510004000000089000000010000000084e201046e616d6501fbe1018103000a6578745f6d616c6c6f6301086578745f66726565020c6578745f74776f785f313238030f6578745f7365745f73746f7261676504146578745f6765745f73746f726167655f696e746f05236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74060e6578745f7072696e745f75746638070d6578745f7072696e745f6e756d08116578745f636c6561725f73746f72616765090d6578745f7072696e745f6865780a106578745f73746f726167655f726f6f740b166578745f73616e64626f785f6d656d6f72795f6765740c166578745f73616e64626f785f6d656d6f72795f7365740d0e6578745f626c616b65325f3235360e126578745f6578697374735f73746f726167650f126578745f656432353531395f76657269667910166578745f73616e64626f785f6d656d6f72795f6e6577111b6578745f73616e64626f785f6d656d6f72795f74656172646f776e12176578745f73616e64626f785f696e7374616e746961746513126578745f73616e64626f785f696e766f6b65141d6578745f73616e64626f785f696e7374616e63655f74656172646f776e15106578745f636c6561725f70726566697816186578745f73746f726167655f6368616e6765735f726f6f74176a3c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a68306236623466366461346538373665631834616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68336266363834353061623434666161391908727573745f6f6f6d1a3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68333232646334366162613238303934351b603c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68663764353631653136666139653166371c513c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68333266306464303361323264616431321d3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68663331653466613238626138666331611e397061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a68626330623333363063626331633430311f347061726974795f636f6465633a3a636f6465633a3a4f75747075743a3a707573683a3a6838313566653232633763303662643265204d3c6e6f64655f72756e74696d653a3a4c6f67206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a683365336666643831633034316465613021347061726974795f636f6465633a3a636f6465633a3a4f75747075743a3a707573683a3a686538303962323333366637303837366322347061726974795f636f6465633a3a636f6465633a3a4f75747075743a3a707573683a3a686561363435613332326264363635656323397061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a683662393231623537643563663264353024397061726974795f636f6465633a3a636f6465633a3a4f75747075743a3a707573685f627974653a3a6862306432656639343134396639366136253a3c616c6c6f633a3a7665633a3a5665633c543e3e3a3a657874656e645f66726f6d5f736c6963653a3a6830323330353563303066343835343636263a3c616c6c6f633a3a7665633a3a5665633c543e3e3a3a657874656e645f66726f6d5f736c6963653a3a6832323737303332306462633063333738272f3c616c6c6f633a3a7665633a3a5665633c543e3e3a3a726573697a653a3a68393831313962643838303862306137312830636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68326362393663383734366439366336362930636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68393330333832623738643031336533392a30636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68366630356264663035333564626666662b443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68343337313931343437326333616538352c4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303066373734353263343130626335312d443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68656332623639623565643637376538352e39636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723a3a636c6f6e65643a3a68303564333339363765643661616339632f443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6866353535383361663936313938643335304b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830633235656638373134636437386334314b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6835623338303962633463643635623665324b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864316339616133376634623565326263334b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864326436396238363534643134643438344e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830353336303362626136386532326439355d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6839623836353935616334643136626331364e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830653465623535316339376364376436374e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833623866346264663934663066393133384e3c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830373866616633333065346264303636394e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68343966303734326533666661323764393a5d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613632383439356235353134656533643b4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68346437643432393932393332366438303c4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68376136383132626538363435363039313d4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68376564376339343431633737323433623e4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68666431393930366365666134663066363f543c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a737065635f657874656e643a3a683130663732383666316236313061346140523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a683635646439663430383036383430313941523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a6836373832316538346664396365336665422e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683866326530643464626366323339633543523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a683764653066333130376433393631366144523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a683862386137373466383033333365316445523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a686464313165353565613236313832313946523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a686534653766613332613464396438313847543c636f72653a3a697465723a3a436861696e3c412c20423e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6833353030383335356135613263613835483c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a683261643237386561316332623064623849467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a68316136653363323564383336373233644a41707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a68363434643937666330363536356434314b543c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a737065635f657874656e643a3a68653936363766393466336235373162334c323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68613863393464383765633333643361374d25616c6c6f633a3a666d743a3a666f726d61743a3a68333765643964643530643432616162624e36636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68646337663865393837366163363963384f29636f72653a3a70616e69636b696e673a3a70616e69633a3a683263643034333836326363366463346150383c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26276120543e3e3a3a636c6f6e65643a3a686331343935643766333563343963363551457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6862636335663864373331653538336662523f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6864343738623366396237386236383230533c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6835393865633632333536353431363035546a3c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a686361633363666436356638643535623155523c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3e3a3a707573685f66756e6374696f6e3a3a686431366332313437333330613765643656a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a683366303436613061343264323161363957623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663635363339666532633165313536325849636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a686565646333383036343831626262633959463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68333833383262313738653434303735325a37707761736d5f7574696c733a3a6761733a3a696e6a6563745f6761735f636f756e7465723a3a68643262613033653738303061376331655b553c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3e3a3a7265736f6c76655f747970655f7265663a3a68623839356231303738323632376631345c3a707761736d5f7574696c733a3a72756c65733a3a496e737472756374696f6e547970653a3a6f703a3a68343863613134303834333430326664355d2f3c616c6c6f633a3a7665633a3a5665633c543e3e3a3a696e736572743a3a68333539373733353834333136663030315e46707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a68326330323632633333303139613332355f4b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6862646437383034646434356133393261604b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a686537656636316331393830633337666561443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839633664336463383130373636656361622f73726d6c5f73797374656d3a3a4576656e743a3a6d657461646174613a3a683561383362396331656164663132306663423c5b545d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a686632333334306337393366306235336264463c26276120737472206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683631356438343866656333653937303265603c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683231613463376265306233326466626466633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683234343236303735393762306331383467633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a686337343634626366353666356366376468633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683637636433383538373036353063396469633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68306331616461616436393462336238636a633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68643437396462633833396663333931386b6c3c73725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362061732073725f7072696d6974697665733a3a7472616974733a3a486173683e3a3a656e756d6572617465645f747269655f726f6f743a3a68323465386134343735663630383061366c11727573745f626567696e5f756e77696e646d23636f72653a3a666d743a3a77726974653a3a68323836633239633038353338343136396e2e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a68656239323632633139373462656135616f3e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686239323837373837626265313963613770323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6834316166646162613931333239383738712d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68633834626633393031633130393564347230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6832346331386664653835663366373632735f3c636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a416461707465723c275f2c20543e20617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a683837316261373134643738393836653174603c636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a416461707465723c275f2c20543e20617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6866396462383536633866663432626231755f3c636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a416461707465723c275f2c20543e20617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68393536396133623130303866626231327634636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68386532623636346463343035623830377735636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a686236326537356361336165303436363378353c5420617320636f72653a3a616e793a3a416e793e3a3a6765745f747970655f69643a3a68613466646438383262613662313861357942636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a7b7b636c6f737572657d7d3a3a68353130346139663834616235313537617a36636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a68353232386663346466303130353434637b49636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207536343e3a3a666d743a3a68613863353265323134646138636561337c2c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a68356339313832616130316666633536647d2e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a68323763313936373563306565323131647e4a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68363464653066663265643266393233627f323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683764616234323839613436626363366580013d636f72653a3a756e69636f64653a3a626f6f6c5f747269653a3a426f6f6c547269653a3a6c6f6f6b75703a3a6862366564333062666338363062313136810149636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a6832656366663232333562343761393362820134636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a68356161383436616430316232656133358301453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68656130353130613364653965643665378401483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683437623235613431633630363735383485018001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a6830636661376366316536666563313033860127636f72653a3a7374723a3a66726f6d5f757466383a3a68626562396238633766356234356565378701483c636f72653a3a666d743a3a417267756d656e74733c275f3e20617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68636332343431303363366536356336358801367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68323739306136636564323436346331348901397061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a68373139393933303635356130376363318a01373c73726d6c5f636f6e74726163743a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a68623935393333373637633964633066628b01453c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a68306338303661333233353230323931318c013f3c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a68313031366636633137616263343134398d01423c5b545d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68306233643262313830396162386237668e01433c5b75385d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68306332373562376365643566323031658f014a3c73726d6c5f636f6e74726163743a3a5261774576656e743c42616c616e63652c204163636f756e7449643e3e3a3a6d657461646174613a3a683966626661383533393633663765653790014f3c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a5261774576656e743c486173682c204163636f756e7449643e3e3a3a6d657461646174613a3a68633061653865363666666463626663629101443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663938313366393061613331306132619201493c73726d6c5f636f6e73656e7375733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68346665313962363661376161336632329301493c73726d6c5f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a683164363364373931666661323633336494014e3c73726d6c5f636f756e63696c3a3a73656174733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686664393363313738366239376330333395014f3c73726d6c5f636f756e63696c3a3a766f74696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686364373231613938653835306238376196015e3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686137366664636563336333343161333597015d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683030613839386163303465323232333298015e3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683337373131393139396365326136643599015d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613465306430383765643731326665369a01613c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68633865393931666464643566636664359b01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68386130313238303039326432393730359c01603c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68613339336330636531353265623364309d01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68376439306261303436613632623133619e01363c73726d6c5f636f6e74726163743a3a436f6e6669673c543e3e3a3a7072656c6f61643a3a68393937303235633635323831363538619f0130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6833376236326364343237633463656636a00135636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68326362393663383734366439366336362e31323431a1015b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6e6f64653a3a4e6f64655265663c426f72726f77547970652c204b2c20562c20547970653e3e3a3a6b6579733a3a6831646239333437393336306636333732a201743c73726d6c5f62616c616e6365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830646662656136393365323133636539a301743c73726d6c5f62616c616e6365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6835333136323465613033306632656537a401773c73726d6c5f62616c616e6365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6862303636616463666236313762336636a501b00173725f7072696d6974697665733a3a67656e657269633a3a626c6f636b3a3a5f494d504c5f4445434f44455f464f525f426c6f636b3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073725f7072696d6974697665733a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c4865616465722c2045787472696e7369633e3e3a3a6465636f64653a3a6865636438316533663130343539353838a6017c3c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c20486173682c204469676573744974656d3e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830343537376133623865326163383738a701a9013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f6d6f7274616c5f65787472696e7369633a3a556e636865636b65644d6f7274616c45787472696e7369633c416464726573732c20496e6465782c2043616c6c2c205369676e61747572653e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831356465643265656137326131353662a8013873726d6c5f636f6e74726163743a3a6761733a3a726566756e645f756e757365645f6761733a3a6833373134396362616136616636633162a9013b3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a667265655f62616c616e63653a3a6838303062636339356161613637333134aa013f3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f667265655f62616c616e63653a3a6863626432656439346637613736393331ab012e73726d6c5f636f6e74726163743a3a6761733a3a6275795f6761733a3a6831303232653939303062616365396234ac013c3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6831316534333733383239666331353131ad01423c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6f6e5f6f66666c696e655f76616c696461746f723a3a6864356136393932383334313061323636ae01343c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a736c6173683a3a6835653538646433353831643334303361af01443c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a63757272656e745f6e6f6d696e61746f72735f666f723a3a6863336334643436336236383133653738b0013c3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a746f74616c5f62616c616e63653a3a6862336334306462383563333964666336b1016c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a6830623763613830346636646533386265b2013c3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6e6f6d696e61746f72735f666f723a3a6866623831353634373839353864313962b3013b3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6170706c795f756e7374616b653a3a6832633939323665393233386233656566b4013a3c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6465706f7369745f6576656e743a3a6862343734646130376166366536366438b5012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6861633261623134356234393732323433b601363c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6839323933393432346562653736313466b7013d3c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6832633266636164393165333939653362b801373c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6834373665353665323830326232346633b901383c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a70726f706f73616c733a3a6861643362306236666439383333396266ba01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834393532613038613939323965383633bb01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865626333366332396363363537323363bc01403c73726d6c5f757067726164655f6b65793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6863303135666437323630666161303239bd013a3c73726d6c5f757067726164655f6b65793a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6866633530626636643739656261396264be01443c73726d6c5f757067726164655f6b65793a3a5261774576656e743c4163636f756e7449643e3e3a3a6d657461646174613a3a6865393766633835366539643338386137bf01493c73726d6c5f7374616b696e673a3a5261774576656e743c42616c616e63652c204163636f756e7449643e3e3a3a6d657461646174613a3a6863613133623565666433366561656463c0014a3c73726d6c5f74726561737572793a3a5261774576656e743c42616c616e63652c204163636f756e7449643e3e3a3a6d657461646174613a3a6830346662333038343338316633353765c101523c28522c2053292061732073726d6c5f73657373696f6e3a3a4f6e53657373696f6e4368616e67653c543e3e3a3a6f6e5f73657373696f6e5f6368616e67653a3a6833653732666563353137306139323734c201353c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7265776172643a3a6861613962356462353732646235393335c3012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6833353530623132396438626231303735c4014273726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765745f6f725f64656661756c743a3a6830626565353732343035303538353232c501493c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a736176655f6f726967696e616c5f617574686f7269746965733a3a6866636361623530613230356463333762c6013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a7075743a3a6866623635326161363138366430393936c7016c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a6839646661323065316233393634303236c801b1013c73726d6c5f7374616b696e673a3a4e6f6d696e6174696e673c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c203c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6765743a3a6833623036303232343530383239383134c901493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6839326464313363636332313132323666ca01633c28582c2059292061732073726d6c5f62616c616e6365733a3a456e737572654163636f756e744c69717569643c4163636f756e7449643e3e3a3a656e737572655f6163636f756e745f6c69717569643a3a6830386635373761376661353238623863cb01723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a6837343439366133643330373264363931cc01623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6837623162656661326536313466666233cd016b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6836313965643733383235376533616633ce01623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833316330393134323734613736313661cf01723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a496e746f4974657261746f723e3a3a696e746f5f697465723a3a6837653539333535313365366665376462d001623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6832376663373765616664633733303332d1016b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835333036313866666431646566313763d201623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864643935663531666461643330633639d3016b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a497465723c27612c204b2c20563e20617320636f72653a3a697465723a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6866306530346461343465333164623665d4013c3c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6830383430343761316634313063326166d501363c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6833366562346533363238653537633531d6012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6862626266343535396430343433396232d70134636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6836326662316266316161386165306163d8012e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6839643432336261616534613463393638d9013c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6863616261623933353263383063306335da0134636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6834353430636134616534636663316235db012e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6831363061616235383861636335663964dc013c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6834633166383564353063336663373139dd01423c73726d6c5f73657373696f6e3a3a5261774576656e743c426c6f636b4e756d6265723e3e3a3a6d657461646174613a3a6862323737303539366135616663363838de01483c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a6765743a3a6863373164353762303432626564643630df014a3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a656e7472793a3a6863323361343266333338396237646136e0014b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6835613661303530353265373665663466e1014b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6866396266666365323833356636333732e201523c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c27612c204b2c20563e3e3a3a696e736572743a3a6832393331373330363962333132323237e3010c436f72655f76657273696f6ee40110436f72655f617574686f726974696573e50112436f72655f657865637574655f626c6f636be601373c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a696e697469616c6973653a3a6865393230626439393539353037666466e701373c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f686173683a3a6834663965323232626163636631326633e8014173725f7072696d6974697665733a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a6866636335613135613362356166326231e9017f3c73726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c20426c6f636b2c20436f6e746578742c205061796d656e742c2046696e616c69736174696f6e3e3e3a3a6170706c795f65787472696e7369635f6e6f5f6e6f74655f776974685f6c656e3a3a6836353039373764323930323766646637ea01453c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6e6f74655f66696e69736865645f65787472696e736963733a3a6835333731373337353834366535303430eb01793c284d2c204e2c204f2c20502c20512c20522c20532c20542c20552c20562c20572c20582c20592c205a292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c6973653c4e756d6265723e3e3a3a6f6e5f66696e616c6973653a3a6836636363373037333335386134663338ec01353c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a66696e616c6973653a3a6864326563653865613532386264333564ed0115436f72655f696e697469616c6973655f626c6f636bee01114d657461646174615f6d65746164617461ef011c426c6f636b4275696c6465725f6170706c795f65787472696e736963f0013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830646461376533323666653731616434f1011b426c6f636b4275696c6465725f66696e616c6973655f626c6f636bf20120426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373f3011c426c6f636b4275696c6465725f636865636b5f696e686572656e7473f40118426c6f636b4275696c6465725f72616e646f6d5f73656564f501367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6832383635396130656337653835376332f6012b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ef701b6013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f6d6f7274616c5f65787472696e7369633a3a556e636865636b65644d6f7274616c45787472696e7369633c416464726573732c20496e6465782c2043616c6c2c205369676e61747572653e2061732073725f7072696d6974697665733a3a7472616974733a3a436865636b61626c653c436f6e746578743e3e3a3a636865636b3a3a6836313365393335646531646666323334f80187013c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4d616b655061796d656e743c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f7061796d656e743a3a6838613861383233626131663862663036f9013a3c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6163636f756e745f6e6f6e63653a3a6836383134666135323539323437306161fa0135636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68326362393663383734366439366336362e31393735fb01367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6835333233643861613261333635316638fc01214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e6765fd01a70173725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a5f494d504c5f4445434f44455f464f525f4469676573743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573743c4974656d3e3e3a3a6465636f64653a3a6862343662306434373639623933346639fe011e4772616e6470614170695f6772616e6470615f617574686f726974696573ff01bd043c6e6f64655f72756e74696d653a3a52756e74696d65206173207375627374726174655f66696e616c6974795f6772616e6470615f7072696d6974697665733a3a72756e74696d655f6465636c5f666f725f4772616e6470614170693a3a4772616e6470614170693c73725f7072696d6974697665733a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c7536342c2073725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362c206e6f64655f72756e74696d653a3a4c6f673e2c2073725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f6d6f7274616c5f65787472696e7369633a3a556e636865636b65644d6f7274616c45787472696e7369633c73726d6c5f62616c616e6365733a3a616464726573733a3a416464726573733c3c6e6f64655f72756e74696d653a3a52756e74696d652061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c203c6e6f64655f72756e74696d653a3a52756e74696d652061732073726d6c5f62616c616e6365733a3a54726169743e3a3a4163636f756e74496e6465783e2c207536342c206e6f64655f72756e74696d653a3a43616c6c2c2073725f7072696d6974697665733a3a456432353531395369676e61747572653e3e3e3e3a3a6772616e6470615f617574686f7269746965733a3a6865623435363935346339353965353935800215417572614170695f736c6f745f6475726174696f6e81023c73726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6761733a3a683238396237303561346234633163333782024873726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f7365745f73746f726167653a3a683435663461623039343062326663356483024273726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a726561645f73616e64626f785f6d656d6f72793a3a683334346231326362313665336666633484022e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a683737386461623134373131656335343785024873726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f6765745f73746f726167653a3a683634666661333530333739656139656686027f3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a683633653937326232356535653532623687024173726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f63616c6c3a3a68616537653366613137623532613763648802473c73726d6c5f636f6e74726163743a3a657865633a3a457865637574696f6e436f6e746578743c27612c20543e3e3a3a63616c6c3a3a686461643235643432633630333339653189024373726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f6372656174653a3a68336534346430326238353463386462368a02493c73726d6c5f636f6e74726163743a3a657865633a3a457865637574696f6e436f6e746578743c27612c20543e3e3a3a6372656174653a3a68383866343836623232643138303062378b024373726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f72657475726e3a3a68313861653766386332653764383434318c024373726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f63616c6c65723a3a68386638306665626230636435666630658d024773726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f696e7075745f73697a653a3a68646261323139336461323733353238648e024773726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f696e7075745f636f70793a3a68656536303930663731666361303132328f024973726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f736372617463685f73697a653a3a686233613130346163626331336230373890024973726d6c5f636f6e74726163743a3a766d3a3a72756e74696d653a3a696e69745f656e763a3a6578745f736372617463685f636f70793a3a686633323061623135303433636461663191023a3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a6465706f7369745f6f663a3a68343336383836326634666636626362379202413c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e6a6563745f7265666572656e64756d3a3a683061353835316365623064633364333493023f3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a7265666572656e64756d5f696e666f3a3a68303261653534343131633764386439389402e9013c73726d6c5f64656d6f63726163793a3a446973706174636851756575653c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265722c20616c6c6f633a3a7665633a3a5665633c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c283c542061732073726d6c5f64656d6f63726163793a3a54726169743e3a3a50726f706f73616c2c20753332293e3e3e3e3a3a74616b653a3a686634383839376638626132643564653495023a3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a766f746572735f666f723a3a68343461303266366561333837396664639602403c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a636c6561725f7265666572656e64756d3a3a68376235626639303235643238303332629702727061726974795f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f7220284a2c204b293e3a3a656e636f64655f746f3a3a683235376132613066306335666561666598023e3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a68646434356265396639346530376636379902373c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a766f74655f6f663a3a68303336346263313136343264303363619a02383c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a68376332393636623835643234313861339b024b3c73726d6c5f64656d6f63726163793a3a5261774576656e743c42616c616e63652c204163636f756e7449643e3e3a3a6d657461646174613a3a68313164363831363466336166336166309c02493c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663938313366393061613331306132612e313436369d02493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a68666535633437323034373034333737669e026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a68303433353637313533343234373162649f026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a6832643863363566616662393464396536a0026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6835323133303237303034626139616337a1026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6838373662616436636563306661346562a2026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6839616631663634376662663236653136a3026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6839626232333030643233323066326165a4026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6863643534386539326433633163373162a5026c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a7075743a3a6866653631616136636232346430633765a6026d3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a74616b653a3a6861616530343533613936633463643665a7026d3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a74616b653a3a6864343464653666653266303433306630a802683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6863303663313033303063636362623437a9026b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6863393838626262313539386631396161aa026c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6866303361333864326430363865653335ab026f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6835383065373330353663333636313862ac02743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6838376534656166386634343034373236ad02793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6839376665636665373065613933353838ae026b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6861353538643563343832383333343033af02727061726974795f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f7220284a2c204b293e3a3a656e636f64655f746f3a3a6865316264306330643338396233396239b0023c3c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6862653263633736653733626466313766b102363c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6830636539643766613166373737333539b202413c73726d6c5f6772616e6470613a3a5261774576656e743c53657373696f6e4b65793e3e3a3a6d657461646174613a3a6839386331636239346433313365306261b3026b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6839643738353062383133333332646534b4026f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e7437206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6832663035333535316234323234666133b502713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6838663965323261626663626339393766b60282017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a73657269616c697a653a3a6865646666623637303635636139653365b702693c7061726974795f7761736d3a3a656c656d656e74733a3a66756e633a3a46756e63426f6479206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6865616439393631303834633130383332b802713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6830323839373530613264333436396665b90282017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a73657269616c697a653a3a6866303639336538353738303237373461ba026f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862393537323437643166393663343761bb02457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6837643066373138633638393464653633bc0286017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a6863653139643461363761373862613738bd027c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6838613238383864306263373061626463be02773c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6833346564366333323837393832323131bf02773c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6833353335376465333835653731306164c0023673726d6c5f636f6e74726163743a3a646f75626c655f6d61703a3a66756c6c5f6b65793a3a6831643235623335313333316634396231c102723c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6863643832396465313835323130373030c202483c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f667265655f62616c616e63655f6372656174696e673a3a6830653965623035396634663535353761c302743c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6862323935633932646464393530343737c402563c73726d6c5f636f6e73656e7375733a3a43616c6c3c543e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6834373966653533653633613130303061c5027f3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6866656163613164313130353137626162c6022e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6835306461613337623235623032376538c7027a3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6836313832626335376361623233313564c8027c3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6862663138633132366638333462626534c902373c636f72653a3a736c6963653a3a497465723c27612c20543e3e3a3a61735f736c6963653a3a6839626234323536303932396635363035ca0280013c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d5265663c27612c20486173682c20417574686f7269747949643e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6864333935323333376132646263386431cb027b6e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f4576656e743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a6465636f64653a3a6865663334386465393162656266363764cc02593c6e6f64655f72756e74696d653a3a43616c6c2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6865356334326533383465643635346265cd025e3c73726d6c5f636f6e73656e7375733a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6866633439373238323161356437323639ce02373c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a656e756d5f7365743a3a6865646161633831303465396633383037cf02433c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a69735f636f756e63696c6c6f723a3a6862353636316638326430656239386565d002633c73726d6c5f636f756e63696c3a3a73656174733a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6831333133346662663266313462663062d102643c73726d6c5f636f756e63696c3a3a766f74696e673a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6834363863383266353462333230623761d202363c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a726573657276653a3a6839346664646565623736313266333231d302433c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f72657365727665645f62616c616e63653a3a6832366433393933313533376638336135d4023d3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a736c6173685f72657365727665643a3a6865343364613863393535636230353335d5024e3c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6863393663336264393333356162343834d602c2013c6e6f64655f72756e74696d653a3a4c6f6720617320636f72653a3a636f6e766572743a3a46726f6d3c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c7375627374726174655f7072696d6974697665733a3a686173683a3a483235362c207375627374726174655f7072696d6974697665733a3a617574686f726974795f69643a3a417574686f7269747949643e3e3e3a3a66726f6d3a3a6838316466343634633964346230373964d702367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6861383331323439346564646233333334d802a7017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f4445434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a6866393566653334333861633532303566d902aa017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f454e434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a6836346639666566626233363864666434da023e3c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6838353762306366393236653834363830db02383c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6864623231643531336436313533316633dc02443c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6837333165613734336231333938633061dd023e3c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6832623338353665663164616662346433de02433c73726d6c5f636f756e63696c3a3a766f74696e673a3a5261774576656e743c486173683e3e3a3a6d657461646174613a3a6839343236383031343265393531346431df023d3c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a7665746f5f6f663a3a6830613436396435386435386163306662e002383c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6465706f7369745f6c6f673a3a6832666663636136363437613462346337e102383c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a756e726573657276653a3a6866333762376136396438636139333664e2028d013c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c6973653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c6973653a3a6861613362383536643032303461653763e3023073726d6c5f636f6e74726163743a3a657865633a3a7472616e736665723a3a6831623965666434326138336233653237e4022d73726d6c5f636f6e74726163743a3a766d3a3a657865637574653a3a6866316632613064376261343333656233e5023273725f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a6862353232626663363062663532336232e60230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6864313463666633313830626361663065e702333c73726d6c5f617572613a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6832363736343037663036323432336632e8023e3c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6866393666333064653139343333666665e902383c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6838646135303462663035663936303838ea02a70173725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a5f494d504c5f4445434f44455f464f525f4469676573743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573743c4974656d3e3e3a3a6465636f64653a3a6835653165653665636239383335626662eb02473c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a63616e6469646174655f7265675f696e666f3a3a6831333730623136366362643830363134ec02433c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6865666233616438393038653261313766ed023d3c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6863643436626661393930383534346466ee02473c73726d6c5f636f756e63696c3a3a73656174733a3a5261774576656e743c4163636f756e7449643e3e3a3a6d657461646174613a3a6835333338356464656533646239323264ef02413c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a72656d6f76655f766f7465723a3a6830333234633666623632626461396437f002413c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a617070726f76616c735f6f663a3a6865383436353866313332616662326338f1023b3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a726561705f6163636f756e743a3a6832356534336238663665323165663830f2023b3c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6864663130353166623036333361356330f3023d3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174613a3a6863616236336139363839373665386334f402493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6837643863306239343539356234343663f502373c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a6d657461646174613a3a6830396531613439646237316238663233f602583c73726d6c5f62616c616e6365733a3a5261774576656e743c4163636f756e7449642c204163636f756e74496e6465782c2042616c616e63653e3e3a3a6d657461646174613a3a6861353537333434333632363539343132f702066d656d736574f802066d656d637079f902076d656d6d6f7665fa02066d656d636d70fb02095f5f75646976746933fc02085f5f6d756c746933fd02095f5f756d6f64746933fe023f636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a727573745f693132385f73686c3a3a6838616661636336353330643766396236ff023f636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a727573745f753132385f7368723a3a686533646132363863336233396232393480030c5f5f756469766d6f6474693400590970726f64756365727302086c616e677561676501045275737404323031350c70726f6365737365642d62790105727573746325312e33322e302d6e696768746c79202831343939376435366120323031382d31322d303529", - "0x3a6772616e6470613a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c0100000000000000", - "0x3a6772616e6470613a617574683a6c656e": "0x04000000", - "0xf718f07ec955fb94f1b3069713461089": "0x0010a5d4e80000000000000000000000", - "0x4664fb5d4e16f894df23cadb3faaa9a6": "0x04000000", - "0x472b8f236d06a2ff7f1e9b2e848ef1d5": "0x0080e03779c311000000000000000000", - "0x78f4ad73d6b7279f8d06f359e363c829": "0x0000a0dec5adc9353600000000000000", - "0x7935e46f94f24b82716c0142e2271de9": "0x8070000000000000", - "0x90d5871cf3f4d0a3642cf2043a7d8eda": "0x0010a5d4e80000000000000000000000", - "0x500603c2af44c475f017a2bbd8d08cbf": "0x04f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd", - "0x2dce29f1a768624dc5343063cb77f77d": "0x07000000", - "0x579ab55d37b1220812be3c3df29d4858": "0x0000000000000000", - "0x24b2518f9a9ee24ab0b62346d83d90b0": "0x11080000", - "0xdd9b01f8462dc19488279cb351a6d861": "0x20a10700", - "0x62f532424b7b1c52f522857315040f27": "0x00407a10f35a00000000000000000000", - "0x799192c17c5cc562d709af11ace92e6a": "0x00040000", - "0xa361c08e2d7768113505020abde19e30": "0x00000000", - "0xb7b6ec0f25eb1ed8b91d05f697d7a874": "0x0c00000000000000", - "0x637414312dac3b280120bf15b4f66cee": "0x00000000", - "0x1f3cb74fca639d825d2f0a0955afbf4a": "0xf295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd", - "0x90e2849b965314409e8bc00011f3004f": "0x04000000", - "0x329586a7b97f2ac15f6c26a02c3c5621": "0x1082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", - "0x52c9048efbfc40fd1e312b7bed451dee": "0x06000000", - "0x0e4944cfd98d6f4cc374d16f5a4e3f9c": "0x0000000000000000", - "0xfb4fdd0ab2d85118e220e2e7473cd3b5": "0x0000a0dec5adc9353600000000000000", - "0x2b89d3b6f46fc8a3aee48c9cb06d7670": "0x0010a5d4e80000000000000000000000", - "0x59b17352bea17cb7dec6dde697de7db4": "0x6400000000000000", - "0x4a8b1a5c7681353a6a320553abbbca49": "0x4038000000000000", - "0x99e2aba8a2b7c8ccba2d740fb86adb0c": "0x00", - "0x717a2ee9c64ad3424e10e4461ec08296": "0x010000000000000001000000000000000100000000000000010000000000000001000000000000000000010010000000", - "0x0b21b3456b23e90d061941ab416f5ea2": "0x00000000000000000000000000000000", - "0xfe7030fd433199728c516e4392091aa5": "0x0080c6a47e8d03000000000000000000", - "0x53d1471b684c8a776c80353e5981c960": "0x00407a10f35a00000000000000000000", - "0xdee5bbb035d9ebc2c9338b5aedf744d7": "0x4038000000000000", - "0x2ec6e5652282d579398fb8fdfa531ef6": "0x0000000000000000", - "0x6e45a8645fa8f905c49fecfef3d06c67": "0x01000000", - "0x9651d20f401bfac47731a01d6eba33b4": "0x00000000", - "0xf4039aa8ae697861be900c58239e96f7": "0x0010a5d4e80000000000000000000000", - "0xdade128e67a5ed110063f56a01ab6bbf": "0x0000000000000000", - "0xb553f17a95cb65012a4326bbaae97035": "0x0010a5d4e80000000000000000000000", - "0x3a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5", - "0x74d5dca6735bab024bc25136daaab7c0": "0x06", - "0x934302c5ec4cb4f73a395e2184ab0aa6": "0x00e40b54020000000000000000000000", - "0xe026dd082e3158e72eb7c985fc8bac4f": "0x4038000000000000", - "0xa36baa0f89eff09b2facf282f27a11ba": "0x50c30000", - "0xf14d23a9d4492a1efc9194e257b3c3d9": "0x00000000", - "0xdfaac108e0d4bc78fc9419a7fcfa84dc": "0x1082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", - "0xd437fe93b0bd0a5d67d30d85d010edc2": "0x40420f00", - "0x3a6772616e6470613a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf50100000000000000", - "0x3a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7", - "0x3a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5", - "0xb9b861cab4bbce870c811515bd5f33d7": "0x00", - "0x125dc846383907f5846f72ce53ca0e4b": "0x00ca9a3b000000000000000000000000", - "0x3a617574683a6c656e": "0x04000000" - } - } -} \ No newline at end of file diff --git a/node/cli/res/dried-danta.json b/node/cli/res/dried-danta.json new file mode 100644 index 0000000000000000000000000000000000000000..1830a6411a39f6c32b2fc489eaf4a4fe7bf95543 --- /dev/null +++ b/node/cli/res/dried-danta.json @@ -0,0 +1,95 @@ +{ + "name": "Dried Danta", + "id": "dried-danta", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "DAN" + }, + "bootNodes": [ + "/ip4/104.211.54.233/tcp/30333/p2p/QmWxNqJeKEBWjJXeX8s882ZdphuVPgUV43THfGAJn7UBWB", + "/ip4/104.211.48.51/tcp/30333/p2p/QmXd7MQAuXkQK1r3ejSbaXKgjXmT2FvbJ3yNfLZpsQ2t8S", + "/ip4/104.211.48.247/tcp/30333/p2p/QmV2zjgFRfxbgYZQC9qFr4aHsQt7tDBJRAdgqqxqTq1Kta", + "/ip4/40.114.120.164/tcp/30333/p2p/QmQbPCeurXuKhzCw6Ar6ovizNKATMTnkkqFJKgZzbF2MJs" + ], + "telemetryEndpoints": [ + ["wss://telemetry.polkadot.io/submit/", 0] + ], + "protocolId": null, + "consensusEngine": null, + "genesis": { + "raw": { + "0xf718f07ec955fb94f1b3069713461089": "0x0010a5d4e80000000000000000000000", + "0xdee5bbb035d9ebc2c9338b5aedf744d7": "0x4038000000000000", + "0xdfaac108e0d4bc78fc9419a7fcfa84dc": "0x1082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0xfbb77d814ac81cfe0ef7030e8bd686f0": "0xe803000000000000", + "0x3a636f6465": "0x0061736d0100000001fd012360037f7f7f017f60047f7f7f7f0060037f7f7f0060057f7f7f7f7f0060027f7f017f60017f0060027f7f0060057f7f7f7f7f017f60047f7f7f7f017f60047f7f7e7f017f60067f7f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f60017e0060017f017f60000060037f7e7f0060047f7f7f7f017e60027e7f0060037f7e7e0060057f7e7f7f7e0060027f7e0060037f7e7e017f60037e7f7f0060017f017e60087f7f7e7e7f7f7f7f0060097f7f7f7e7e7f7f7f7f0060047f7f7e7e0060057f7e7e7e7e0060037f7f7e0060027e7f017f60027f7f017e60087f7f7f7f7f7e7e7f0060087f7f7f7f7f7f7f7f0060047f7e7e7f0060067f7e7e7e7e7f0002cc041703656e76146578745f6765745f73746f726167655f696e746f000703656e760c6578745f74776f785f313238000203656e76116578745f636c6561725f73746f72616765000603656e760f6578745f7365745f73746f72616765000103656e760e6578745f7072696e745f75746638000603656e760e6578745f626c616b65325f323536000203656e76126578745f656432353531395f766572696679000803656e76106578745f73746f726167655f726f6f74000503656e76186578745f73746f726167655f6368616e6765735f726f6f74000903656e76166578745f73616e64626f785f6d656d6f72795f676574000803656e76166578745f73616e64626f785f6d656d6f72795f736574000803656e761b6578745f73616e64626f785f6d656d6f72795f74656172646f776e000503656e76126578745f6578697374735f73746f72616765000403656e76106578745f636c6561725f707265666978000603656e760d6578745f7072696e745f686578000603656e76166578745f73616e64626f785f6d656d6f72795f6e6577000403656e76176578745f73616e64626f785f696e7374616e7469617465000a03656e76126578745f73616e64626f785f696e766f6b65000b03656e761d6578745f73616e64626f785f696e7374616e63655f74656172646f776e000503656e76236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74000103656e760d6578745f7072696e745f6e756d000c03656e760a6578745f6d616c6c6f63000d03656e76086578745f6672656500050388038603020205000d060e03020f060604060606060605020e100606060606020602060606060c06020505110506060605060612121306020c06020514020606060606060506150606060606061406050606051617060606050e05050505050506020101180101010e0101010101030101050e04010101010501011901010602050606060606050505060606060606060602020d061a1a06050605060405060606060606060606021201060606060505050606060606060e020d0606060605050506050505060606060605060d06060606061b1c0505050505050604060404060104040605050505050506050505041d0a0406050104040006061e1e1e06020106041e1e06020606061e1e1e0606021e01061e1e041e1e1e020605060505050606060205050505050505050505050505050505050606021f0220061a0501060605060604060d02060202020e0605050502060602030206020205050506060606060605020604020206060202050206050d05000d000e0405000404170004040404000000001b1b21212204070170018b018b0105030100110619037f01418080c0000b7f004190e8c3000b7f004190e8c3000b07d70312066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000b5f5f686561705f6261736503010a5f5f646174615f656e6403020c436f72655f76657273696f6e008d0210436f72655f617574686f726974696573008e0212436f72655f657865637574655f626c6f636b008f0215436f72655f696e697469616c6973655f626c6f636b009502114d657461646174615f6d657461646174610096021c426c6f636b4275696c6465725f6170706c795f65787472696e736963009c021b426c6f636b4275696c6465725f66696e616c6973655f626c6f636b009d0220426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373009e021c426c6f636b4275696c6465725f636865636b5f696e686572656e747300a20218426c6f636b4275696c6465725f72616e646f6d5f7365656400a5022b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00a602214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e676500a8021e4772616e6470614170695f6772616e6470615f617574686f72697469657300a90215417572614170695f736c6f745f6475726174696f6e00aa02098a02010041010b8a01238902f10194028102f501f0018402f4019003910388028c01830180018d01767875797d7c7a8f01820190018a017f7e890188012cf8029303890392036efd01b101d401b202a201c702a101a0019f01b5019e019d019c01b801b701b601b301b201c401d801e702ea02e602e9026b6db602b702ff018002fe01717270f801f901f701b802eb01ec01ea01b902e801e901e701ba02ad01b001ab01bb02fb01fc01fa01bc029a019b019901bd02c201c301c101be02b002b102af02bf02e102e202e002c002d601d701d501c102ed02ee02ec02c202d201d301d101c302c402c502c602cf028101c902eb02cd02f402f302f202f102f002ef028a038b038c038d038e030aada02c8603c404020d7f017e230041c0006b22032400200128020022042001280208220541047422066a2107200128020421080240024002400240024002402005450d00200341306a41017221094100210a200341306a41026a210b200341206a410172220c41076a210d0340200b2004200a6a220141036a2d00003a00002003200141016a2f00003b013020012d0000220e41ac01460d022003410c6a41026a220f200b2d00003a0000200320032f01303b010c200141046a2902002110200341306a410c6a2001410c6a280200360200200920032f010c3b0000200941026a200f2d00003a00002003200e3a003020032010370234200341206a200341306a200210182003200c2900003703102003200d29000037001720032d0020220e411a470d052006200a41106a220a470d000c040b0b200422012007470d010c020b200141106a22012007460d010b03400240024020012d0000220a4109460d00200a41ac01470d010c030b200141086a28020041ffffffff0371450d00200141046a28020010190b200141106a22012007470d000b0b02402008450d00200410190b2000411a3a00000c010b200020032903103700012000200e3a0000200041086a20032900173700000240200541047441706a200a460d00200141186a2101034002400240200141786a220a2d0000220b4109460d00200b41ac01470d010c030b200128020041ffffffff0371450d002001417c6a28020010190b200141106a2101200a41106a2007470d000b0b2008450d0020041019200341c0006a24000f0b200341c0006a24000bd0ec0203077f017e037f230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220441aa014b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040eab01000b1c1001ab01a801aa01a401240d14a90104151b9b01541e2555063607a201890173279201a101a70135090f8a013a9e01a50105023b44754c74578e01030a47177a7c4285017926297b8b01080e282f1319950197012399019d01a6015ea301189c01611f5d129f01a00121930177760c1145482b1698011d6332940191018c012c1a379a013d2a674d5868644e8001437f318d0188012e8f019601204941309001723e228101624b7d86012d34333940705f6f84018301388701515282017869657e6c603c563f6a4f466d506e5a6b664a59535b5c000b200241086a2802002002410c6a2802002204470dcf01200441016a22052004490dfe0720044101742206200520052006491b22064100480dfe072004450d9f03200241046a28020020042006101a2205450da0030c8e080b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfd0720044101742206200520052006491b22064100480dfd072004450dd602200241046a28020020042006101a2205450dd7020c8b080b200241046a2107200141086a2802002106200141046a2802002105200241086a2802002002410c6a2802002204470daa01200441016a22082004490d870820044101742209200820082009491b22084100480d87082004450dd702200728020020042008101a2209450dd8020c85080b200241046a2105200141086a290300210a200241086a2802002002410c6a2802002204470daa01200441016a22062004490d860820044101742208200620062008491b22084100480d86082004450dd802200528020020042008101a2206450dd9020c82080b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfa0720044101742206200520052006491b22064100480dfa072004450dd902200241046a28020020042006101a2205450dda020cff070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490d840820044101742209200820082009491b22084100480d84082004450dda02200728020020042008101a2209450ddb020cfc070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df80720044101742209200820082009491b22084100480df8072004450ddb02200728020020042008101a2209450ddc020cf6070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df70720044101742209200820082009491b22084100480df7072004450ddc02200728020020042008101a2209450ddd020cf3070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d810820044101742206200520052006491b22064100480d81082004450ddd02200241046a28020020042006101a2205450dde020cf0070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df50720044101742209200820082009491b22084100480df5072004450dde02200728020020042008101a2209450ddf020ced070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dff0720044101742206200520052006491b22064100480dff072004450ddf02200241046a28020020042006101a2205450de0020cea070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490df30720044101742209200620062009491b22094100480df3072004450de002200528020020042009101a2206450de1020ce7070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490da30520044101742206200520052006491b22064100480da3052004450de102200241046a28020020042006101a2205450de2020ce4070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490df10720064101742208200520052008491b22054100480df1072006450de202200728020020062005101a2208450de3020ce1070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfb0720044101742206200520052006491b22064100480dfb072004450de302200241046a28020020042006101a2205450de4020cde070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490dfa0720044101742209200820082009491b22084100480dfa072004450de402200728020020042008101a2209450de5020cdb070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490dee0720044101742209200620062009491b22094100480dee072004450de502200528020020042009101a2206450de6020cd8070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d9e0520044101742206200520052006491b22064100480d9e052004450de602200241046a28020020042006101a2205450de7020cd5070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df70720044101742206200520052006491b22064100480df7072004450de702200241046a28020020042006101a2205450de8020cd2070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df60720044101742206200520052006491b22064100480df6072004450de802200241046a28020020042006101a2205450de9020ccf070b200241046a210b200141046a280200210520012d0001210c200241086a2802002002410c6a2802002204470daa01200441016a22062004490dea0720044101742208200620062008491b22064100480dea072004450de902200b28020020042006101a2208450dea020ccc070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de90720064101742208200520052008491b22054100480de9072006450dea02200728020020062005101a2208450deb020cc9070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d990520044101742206200520052006491b22064100480d99052004450deb02200241046a28020020042006101a2205450dec020cc6070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df20720044101742206200520052006491b22064100480df2072004450dec02200241046a28020020042006101a2205450ded020cc3070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df10720044101742206200520052006491b22064100480df1072004450ded02200241046a28020020042006101a2205450dee020cc0070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df00720044101742206200520052006491b22064100480df0072004450dee02200241046a28020020042006101a2205450def020cbd070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d950520044101742206200520052006491b22064100480d95052004450def02200241046a28020020042006101a2205450df0020cba070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de30720064101742208200520052008491b22054100480de3072006450df002200728020020062005101a2208450df1020cb7070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490de20720044101742209200620062009491b22094100480de2072004450df102200528020020042009101a2206450df2020cb4070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d920520044101742206200520052006491b22064100480d92052004450df202200241046a28020020042006101a2205450df3020cb1070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de00720064101742208200520052008491b22054100480de0072006450df302200728020020062005101a2208450df4020cae070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dea0720044101742206200520052006491b22064100480dea072004450df402200241046a28020020042006101a2205450df5020cab070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d8f0520044101742206200520052006491b22064100480d8f052004450df502200241046a28020020042006101a2205450df6020ca8070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490de80720044101742206200520052006491b22064100480de8072004450df602200241046a28020020042006101a2205450df7020ca5070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d8d0520044101742206200520052006491b22064100480d8d052004450df702200241046a28020020042006101a2205450df8020ca2070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490de60720044101742206200520052006491b22064100480de6072004450df802200241046a28020020042006101a2205450df9020c9f070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dda0720044101742206200520052006491b22064100480dda072004450df902200241046a28020020042006101a2205450dfa020c9c070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd90720044101742209200820082009491b22084100480dd9072004450dfc02200728020020042008101a2209450dfd020c99070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de30720044101742206200520052006491b22064100480de3072004450dfd02200241046a28020020042006101a2205450dfe020c96070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd70720044101742209200820082009491b22084100480dd7072004450dfe02200728020020042008101a2209450dff020c93070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de10720044101742206200520052006491b22064100480de1072004450dff02200241046a28020020042006101a2205450d80030c90070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00720044101742206200520052006491b22064100480de0072004450d8003200241046a28020020042006101a2205450d81030c8d070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d850520044101742206200520052006491b22064100480d85052004450d8103200241046a28020020042006101a2205450d82030c8a070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d840520044101742206200520052006491b22064100480d84052004450d8203200241046a28020020042006101a2205450d83030c87070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d830520044101742206200520052006491b22064100480d83052004450d8303200241046a28020020042006101a2205450d84030c84070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d820520044101742206200520052006491b22064100480d82052004450d8403200241046a28020020042006101a2205450d85030c81070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d810520044101742206200520052006491b22064100480d81052004450d8503200241046a28020020042006101a2205450d86030cfe060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dda0720044101742206200520052006491b22064100480dda072004450d8603200241046a28020020042006101a2205450d87030cfb060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dff0420044101742206200520052006491b22064100480dff042004450d8703200241046a28020020042006101a2205450d88030cf8060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfe0420044101742206200520052006491b22064100480dfe042004450d8803200241046a28020020042006101a2205450d89030cf5060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfd0420044101742206200520052006491b22064100480dfd042004450d8903200241046a28020020042006101a2205450d8a030cf2060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfc0420044101742206200520052006491b22064100480dfc042004450d8a03200241046a28020020042006101a2205450d8b030cef060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfb0420044101742206200520052006491b22064100480dfb042004450d8b03200241046a28020020042006101a2205450d8c030cec060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc90720044101742209200820082009491b22084100480dc9072004450d8c03200728020020042008101a2209450d8d030ce9060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc80720044101742209200820082009491b22084100480dc8072004450d8d03200728020020042008101a2209450d8e030ce6060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df80420044101742206200520052006491b22064100480df8042004450d8e03200241046a28020020042006101a2205450d8f030ce3060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df70420044101742206200520052006491b22064100480df7042004450d8f03200241046a28020020042006101a2205450d90030ce0060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df60420044101742206200520052006491b22064100480df6042004450d9003200241046a28020020042006101a2205450d91030cdd060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dcf0720044101742209200820082009491b22084100480dcf072004450d9103200728020020042008101a2209450d92030cda060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dce0720044101742209200820082009491b22084100480dce072004450d9203200728020020042008101a2209450d93030cd7060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df30420044101742206200520052006491b22064100480df3042004450d9303200241046a28020020042006101a2205450d94030cd4060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df20420044101742206200520052006491b22064100480df2042004450d9403200241046a28020020042006101a2205450d95030cd1060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df10420044101742206200520052006491b22064100480df1042004450d9503200241046a28020020042006101a2205450d96030cce060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df00420044101742206200520052006491b22064100480df0042004450d9603200241046a28020020042006101a2205450d97030ccb060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490def0420044101742206200520052006491b22064100480def042004450d9703200241046a28020020042006101a2205450d98030cc8060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dee0420044101742206200520052006491b22064100480dee042004450d9803200241046a28020020042006101a2205450d99030cc5060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc70720044101742206200520052006491b22064100480dc7072004450d9903200241046a28020020042006101a2205450d9a030cc2060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dec0420044101742206200520052006491b22064100480dec042004450d9a03200241046a28020020042006101a2205450d9b030cbf060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc50720044101742209200820082009491b22084100480dc5072004450d9b03200728020020042008101a2209450d9c030cbc060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0420044101742206200520052006491b22064100480dea042004450d9c03200241046a28020020042006101a2205450d9d030cb9060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0420044101742206200520052006491b22064100480dea042004450d9d03200241046a28020020042006101a2205450d9e030cb6060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc20720044101742206200520052006491b22064100480dc2072004450d9e03200241046a28020020042006101a2205450d9f030cb3060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de70420044101742206200520052006491b22064100480de7042004450d9f03200241046a28020020042006101a2205450da0030cb0060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60420044101742206200520052006491b22064100480de6042004450da003200241046a28020020042006101a2205450da1030cad060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60420044101742206200520052006491b22064100480de6042004450da103200241046a28020020042006101a2205450da2030caa060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de40420044101742206200520052006491b22064100480de4042004450da203200241046a28020020042006101a2205450da3030ca7060b200241046a210520012d00012108200241086a2802002002410c6a2802002204470dab01200441016a22062004490dbd0720044101742209200620062009491b22094100480dbd072004450da303200528020020042009101a2206450da4030ca4060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de20420044101742206200520052006491b22064100480de2042004450da403200241046a28020020042006101a2205450da5030ca1060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de10420044101742206200520052006491b22064100480de1042004450da503200241046a28020020042006101a2205450da6030c9e060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00420044101742206200520052006491b22064100480de0042004450da603200241046a28020020042006101a2205450da7030c9b060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00420044101742206200520052006491b22064100480de0042004450da703200241046a28020020042006101a2205450da8030c98060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dde0420044101742206200520052006491b22064100480dde042004450da803200241046a28020020042006101a2205450da9030c95060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ddd0420044101742206200520052006491b22064100480ddd042004450da903200241046a28020020042006101a2205450daa030c92060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ddd0420044101742206200520052006491b22064100480ddd042004450daa03200241046a28020020042006101a2205450dab030c8f060b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490daa0720064101742208200520052008491b22054100480daa072006450dab03200728020020062005101a2208450dac030c8c060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490da90720044101742209200820082009491b22084100480da9072004450dac03200728020020042008101a2209450dad030c89060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd90420044101742206200520052006491b22064100480dd9042004450dad03200241046a28020020042006101a2205450dae030c86060b200141086a290300210a200241086a2802002002410c6a2802002204470dab01200441016a22052004490db20720044101742206200520052006491b22064100480db2072004450dae03200241046a28020020042006101a2205450daf030c82060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd70420044101742206200520052006491b22064100480dd7042004450daf03200241046a28020020042006101a2205450db0030cff050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd70420044101742206200520052006491b22064100480dd7042004450db003200241046a28020020042006101a2205450db1030cfc050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd60420044101742206200520052006491b22064100480dd6042004450db103200241046a28020020042006101a2205450db2030cf9050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd50420044101742206200520052006491b22064100480dd5042004450db203200241046a28020020042006101a2205450db3030cf6050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd40420044101742206200520052006491b22064100480dd4042004450db303200241046a28020020042006101a2205450db4030cf3050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dac0720044101742206200520052006491b22064100480dac072004450db403200241046a28020020042006101a2205450db5030cf0050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dab0720044101742206200520052006491b22064100480dab072004450db503200241046a28020020042006101a2205450db6030ced050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd00420044101742206200520052006491b22064100480dd0042004450db603200241046a28020020042006101a2205450db7030cea050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcf0420044101742206200520052006491b22064100480dcf042004450db703200241046a28020020042006101a2205450db8030ce7050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da80720044101742206200520052006491b22064100480da8072004450db803200241046a28020020042006101a2205450db9030ce4050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcd0420044101742206200520052006491b22064100480dcd042004450db903200241046a28020020042006101a2205450dba030ce1050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcc0420044101742206200520052006491b22064100480dcc042004450dba03200241046a28020020042006101a2205450dbb030cde050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcb0420044101742206200520052006491b22064100480dcb042004450dbb03200241046a28020020042006101a2205450dbc030cdb050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dca0420044101742206200520052006491b22064100480dca042004450dbc03200241046a28020020042006101a2205450dbd030cd8050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dca0420044101742206200520052006491b22064100480dca042004450dbd03200241046a28020020042006101a2205450dbe030cd5050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc80420044101742206200520052006491b22064100480dc8042004450dbe03200241046a28020020042006101a2205450dbf030cd2050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc70420044101742206200520052006491b22064100480dc7042004450dbf03200241046a28020020042006101a2205450dc0030ccf050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc60420044101742206200520052006491b22064100480dc6042004450dc003200241046a28020020042006101a2205450dc1030ccc050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc50420044101742206200520052006491b22064100480dc5042004450dc103200241046a28020020042006101a2205450dc2030cc9050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc50420044101742206200520052006491b22064100480dc5042004450dc203200241046a28020020042006101a2205450dc3030cc6050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc30420044101742206200520052006491b22064100480dc3042004450dc303200241046a28020020042006101a2205450dc4030cc3050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc30420044101742206200520052006491b22064100480dc3042004450dc403200241046a28020020042006101a2205450dc5030cc0050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc20420044101742206200520052006491b22064100480dc2042004450dc503200241046a28020020042006101a2205450dc6030cbd050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc00420044101742206200520052006491b22064100480dc0042004450dc603200241046a28020020042006101a2205450dc7030cba050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dbf0420044101742206200520052006491b22064100480dbf042004450dc703200241046a28020020042006101a2205450dc8030cb7050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8d0720044101742206200520052006491b22064100480d8d072004450dc803200241046a28020020042006101a2205450dc9030cb4050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dbd0420044101742206200520052006491b22064100480dbd042004450dc903200241046a28020020042006101a2205450dca030cb1050b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490d8b0720044101742209200820082009491b22084100480d8b072004450dca03200728020020042008101a2209450dcb030cae050b200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22052004490d950720044101742208200520052008491b22084100480d95072004450dcb03200241046a28020020042008101a2205450dcc030cab050b200241046a210520012d00012108200241086a2802002002410c6a2802002204470dab01200441016a22062004490d940720044101742209200620062009491b22094100480d94072004450dcc03200528020020042009101a2206450dcd030ca8050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db90420044101742206200520052006491b22064100480db9042004450dcd03200241046a28020020042006101a2205450dce030ca5050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db80420044101742206200520052006491b22064100480db8042004450dce03200241046a28020020042006101a2205450dcf030ca2050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db70420044101742206200520052006491b22064100480db7042004450dcf03200241046a28020020042006101a2205450dd0030c9f050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d900720044101742206200520052006491b22064100480d90072004450dd003200241046a28020020042006101a2205450dd1030c9c050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8f0720044101742206200520052006491b22064100480d8f072004450dd103200241046a28020020042006101a2205450dd2030c99050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8e0720044101742206200520052006491b22064100480d8e072004450dd203200241046a28020020042006101a2205450dd3030c96050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8d0720044101742206200520052006491b22064100480d8d072004450dd303200241046a28020020042006101a2205450dd4030c93050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db20420044101742206200520052006491b22064100480db2042004450dd403200241046a28020020042006101a2205450dd5030c90050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db10420044101742206200520052006491b22064100480db1042004450dd503200241046a28020020042006101a2205450dd6030c8d050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db00420044101742206200520052006491b22064100480db0042004450dd603200241046a28020020042006101a2205450dd7030c8a050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490daf0420044101742206200520052006491b22064100480daf042004450dd703200241046a28020020042006101a2205450dd8030c87050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dae0420044101742206200520052006491b22064100480dae042004450dd803200241046a28020020042006101a2205450dd9030c84050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dad0420044101742206200520052006491b22064100480dad042004450dd903200241046a28020020042006101a2205450dda030c81050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dac0420044101742206200520052006491b22064100480dac042004450dda03200241046a28020020042006101a2205450ddb030cfe040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dab0420044101742206200520052006491b22064100480dab042004450ddb03200241046a28020020042006101a2205450ddc030cfb040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d840720044101742206200520052006491b22064100480d84072004450ddc03200241046a28020020042006101a2205450ddd030cf8040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da90420044101742206200520052006491b22064100480da9042004450ddd03200241046a28020020042006101a2205450dde030cf5040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da80420044101742206200520052006491b22064100480da8042004450dde03200241046a28020020042006101a2205450ddf030cf2040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da70420044101742206200520052006491b22064100480da7042004450ddf03200241046a28020020042006101a2205450de0030cef040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490df50620044101742209200820082009491b22084100480df5062004450de003200728020020042008101a2209450de1030cec040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dff0620044101742209200820082009491b22084100480dff062004450de103200728020020042008101a2209450de2030ce9040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfe0620044101742206200520052006491b22064100480dfe062004450de203200241046a28020020042006101a2205450de3030ce6040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da30420044101742206200520052006491b22064100480da3042004450de303200241046a28020020042006101a2205450de4030ce3040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da20420044101742206200520052006491b22064100480da2042004450de403200241046a28020020042006101a2205450de5030ce0040b200241046a2105200141046a2802002108200241086a2802002002410c6a2802002204470dab01200441016a22062004490dfb0620044101742209200620062009491b22094100480dfb062004450de503200528020020042009101a2206450de6030cdd040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da00420044101742206200520052006491b22064100480da0042004450de603200241046a28020020042006101a2205450de7030cda040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9f0420044101742206200520052006491b22064100480d9f042004450de703200241046a28020020042006101a2205450de8030cd7040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9e0420044101742206200520052006491b22064100480d9e042004450de803200241046a28020020042006101a2205450de9030cd4040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dec0620044101742209200820082009491b22084100480dec062004450de903200728020020042008101a2209450dea030cd1040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df60620044101742206200520052006491b22064100480df6062004450dea03200241046a28020020042006101a2205450deb030cce040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9b0420044101742206200520052006491b22064100480d9b042004450deb03200241046a28020020042006101a2205450dec030ccb040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df40620044101742206200520052006491b22064100480df4062004450dec03200241046a28020020042006101a2205450ded030cc8040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d990420044101742206200520052006491b22064100480d99042004450ded03200241046a28020020042006101a2205450dee030cc5040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df20620044101742206200520052006491b22064100480df2062004450dee03200241046a28020020042006101a2205450def030cc2040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d970420044101742206200520052006491b22064100480d97042004450def03200241046a28020020042006101a2205450df0030cbf040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df00620044101742206200520052006491b22064100480df0062004450df003200241046a28020020042006101a2205450df1030cbc040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d950420044101742206200520052006491b22064100480d95042004450df103200241046a28020020042006101a2205450df2030cb9040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490de30620064101742208200520052008491b22054100480de3062006450df203200728020020062005101a2208450df3030cb6040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ded0620044101742206200520052006491b22064100480ded062004450df303200241046a28020020042006101a2205450df4030cb3040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dec0620044101742206200520052006491b22064100480dec062004450df403200241046a28020020042006101a2205450df5030cb0040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490deb0620044101742209200820082009491b22084100480deb062004450df503200728020020042008101a2209450df6030cad040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0620044101742206200520052006491b22064100480dea062004450df603200241046a28020020042006101a2205450df7030caa040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de90620044101742206200520052006491b22064100480de9062004450df703200241046a28020020042006101a2205450df8030ca7040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490ddd0620044101742209200820082009491b22084100480ddd062004450df803200728020020042008101a2209450df9030ca4040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490ddc0620044101742209200820082009491b22084100480ddc062004450df903200728020020042008101a2209450dfa030ca1040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60620044101742206200520052006491b22064100480de6062004450dfa03200241046a28020020042006101a2205450dfb030c9e040b200241046a21092001410c6a2802002104200141086a280200210b200141046a280200210d200241086a2802002002410c6a2802002205470dab01200541016a22012005490dda0620054101742206200120012006491b22014100480dda062005450dfb03200928020020052001101a2206450dfc030c9b040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490de40620044101742209200820082009491b22084100480de4062004450dfc03200728020020042008101a2209450dfd030c98040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de30620044101742206200520052006491b22064100480de3062004450dfd03200241046a28020020042006101a2205450dfe030c95040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd70620044101742209200820082009491b22084100480dd7062004450dfe03200728020020042008101a2209450dff030c92040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490dd60620064101742208200520052008491b22054100480dd6062006450dff03200728020020062005101a2208450d80040c8f040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd50620044101742206200520052006491b22064100480dd5062004450d8004200241046a28020020042006101a2205450d81040c8c040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490dd40620064101742208200520052008491b22054100480dd4062006450d8104200728020020062005101a2208450d82040c89040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd30620044101742206200520052006491b22064100480dd3062004450d8204200241046a28020020042006101a2205450d83040c86040b200241046a28020021050ce1060b200728020021090cdb060b200528020021060cd8060b200241046a28020021050cd5060b200728020021090cd2060b200728020021090ccc060b200728020021090cc9060b200241046a28020021050cc6060b200728020021090cc3060b200241046a28020021050cc0060b200528020021060cbd060b200241046a28020021050cba060b200728020021080cb7060b200241046a28020021050cb4060b200728020021090cb1060b200528020021060cae060b200241046a28020021050cab060b200241046a28020021050ca8060b200241046a28020021050ca5060b200b28020021080ca2060b200728020021080c9f060b200241046a28020021050c9c060b200241046a28020021050c99060b200241046a28020021050c96060b200241046a28020021050c93060b200241046a28020021050c90060b200728020021080c8d060b200528020021060c8a060b200241046a28020021050c87060b200728020021080c84060b200241046a28020021050c81060b200241046a28020021050cfe050b200241046a28020021050cfb050b200241046a28020021050cf8050b200241046a28020021050cf5050b200241046a28020021050cf2050b200241046a28020021050cbf060b200728020021090cee050b200241046a28020021050ceb050b200728020021090ce8050b200241046a28020021050ce5050b200241046a28020021050ce2050b200241046a28020021050cdf050b200241046a28020021050cdc050b200241046a28020021050cd9050b200241046a28020021050cd6050b200241046a28020021050cd3050b200241046a28020021050cd0050b200241046a28020021050ccd050b200241046a28020021050cca050b200241046a28020021050cc7050b200241046a28020021050cc4050b200241046a28020021050cc1050b200728020021090cbe050b200728020021090cbb050b200241046a28020021050cb8050b200241046a28020021050cb5050b200241046a28020021050cb2050b200728020021090caf050b200728020021090cac050b200241046a28020021050ca9050b200241046a28020021050ca6050b200241046a28020021050ca3050b200241046a28020021050ca0050b200241046a28020021050c9d050b200241046a28020021050c9a050b200241046a28020021050c97050b200241046a28020021050c94050b200728020021090c91050b200241046a28020021050c8e050b200241046a28020021050c8b050b200241046a28020021050c88050b200241046a28020021050c85050b200241046a28020021050c82050b200241046a28020021050cff040b200241046a28020021050cfc040b200528020021060cf9040b200241046a28020021050cf6040b200241046a28020021050cf3040b200241046a28020021050cf0040b200241046a28020021050ced040b200241046a28020021050cea040b200241046a28020021050ce7040b200241046a28020021050ce4040b200728020021080ce1040b200728020021090cde040b200241046a28020021050cdb040b200241046a28020021050cd7040b200241046a28020021050cd4040b200241046a28020021050cd1040b200241046a28020021050cce040b200241046a28020021050ccb040b200241046a28020021050cc8040b200241046a28020021050cc5040b200241046a28020021050cc2040b200241046a28020021050cbf040b200241046a28020021050cbc040b200241046a28020021050cb9040b200241046a28020021050cb6040b200241046a28020021050cb3040b200241046a28020021050cb0040b200241046a28020021050cad040b200241046a28020021050caa040b200241046a28020021050ca7040b200241046a28020021050ca4040b200241046a28020021050ca1040b200241046a28020021050c9e040b200241046a28020021050c9b040b200241046a28020021050c98040b200241046a28020021050c95040b200241046a28020021050c92040b200241046a28020021050c8f040b200241046a28020021050c8c040b200241046a28020021050c89040b200241046a28020021050c86040b200728020021090c83040b200241046a28020021050c80040b200528020021060cfd030b200241046a28020021050cfa030b200241046a28020021050cf7030b200241046a28020021050cf4030b200241046a28020021050cf1030b200241046a28020021050cee030b200241046a28020021050ceb030b200241046a28020021050ce8030b200241046a28020021050ce5030b200241046a28020021050ce2030b200241046a28020021050cdf030b200241046a28020021050cdc030b200241046a28020021050cd9030b200241046a28020021050cd6030b200241046a28020021050cd3030b200241046a28020021050cd0030b200241046a28020021050ccd030b200241046a28020021050cca030b200241046a28020021050cc7030b200241046a28020021050cc4030b200728020021090cc1030b200728020021090cbe030b200241046a28020021050cbb030b200241046a28020021050cb8030b200241046a28020021050cb5030b200528020021060cb2030b200241046a28020021050caf030b200241046a28020021050cac030b200241046a28020021050ca9030b200728020021090ca6030b200241046a28020021050ca3030b200241046a28020021050ca0030b200241046a28020021050c9d030b200241046a28020021050c9a030b200241046a28020021050c97030b200241046a28020021050c94030b200241046a28020021050c91030b200241046a28020021050c8e030b200728020021080c8b030b200241046a28020021050c88030b200241046a28020021050c85030b200728020021090c82030b200241046a28020021050cff020b200241046a28020021050cfc020b200728020021090cf9020b200728020021090cf6020b200241046a28020021050cf3020b200928020021060cf0020b200728020021090ced020b200241046a28020021050cea020b200728020021090ce7020b200728020021080ce4020b200241046a28020021050ce1020b200728020021080cde020b200241046a28020021050cdb020b2006101b22050db4050b20064101101c000b2008101b22090dad050b20084101101c000b2008101b22060da9050b20084101101c000b2006101b22050da5050b20064101101c000b2008101b22090da1050b20084101101c000b2008101b22090d9a050b20084101101c000b2008101b22090d96050b20084101101c000b2006101b22050d92050b20064101101c000b2008101b22090d8e050b20084101101c000b2006101b22050d8a050b20064101101c000b2009101b22060d86050b20094101101c000b2006101b22050d82050b20064101101c000b2005101b22080dfe040b20054101101c000b2006101b22050dfa040b20064101101c000b2008101b22090df6040b20084101101c000b2009101b22060df2040b20094101101c000b2006101b22050dee040b20064101101c000b2006101b22050dea040b20064101101c000b2006101b22050de6040b20064101101c000b2006101b22080de2040b20064101101c000b2005101b22080dde040b20054101101c000b2006101b22050dda040b20064101101c000b2006101b22050dd6040b20064101101c000b2006101b22050dd2040b20064101101c000b2006101b22050dce040b20064101101c000b2006101b22050dca040b20064101101c000b2005101b22080dc6040b20054101101c000b2009101b22060dc2040b20094101101c000b2006101b22050dbe040b20064101101c000b2005101b22080dba040b20054101101c000b2006101b22050db6040b20064101101c000b2006101b22050db2040b20064101101c000b2006101b22050dae040b20064101101c000b2006101b22050daa040b20064101101c000b2006101b22050da6040b20064101101c000b2006101b22050da2040b20064101101c000b2006101b22050dee040b20064101101c000b2008101b22090d9c040b20084101101c000b2006101b22050d98040b20064101101c000b2008101b22090d94040b20084101101c000b2006101b22050d90040b20064101101c000b2006101b22050d8c040b20064101101c000b2006101b22050d88040b20064101101c000b2006101b22050d84040b20064101101c000b2006101b22050d80040b20064101101c000b2006101b22050dfc030b20064101101c000b2006101b22050df8030b20064101101c000b2006101b22050df4030b20064101101c000b2006101b22050df0030b20064101101c000b2006101b22050dec030b20064101101c000b2006101b22050de8030b20064101101c000b2006101b22050de4030b20064101101c000b2006101b22050de0030b20064101101c000b2008101b22090ddc030b20084101101c000b2008101b22090dd8030b20084101101c000b2006101b22050dd4030b20064101101c000b2006101b22050dd0030b20064101101c000b2006101b22050dcc030b20064101101c000b2008101b22090dc8030b20084101101c000b2008101b22090dc4030b20084101101c000b2006101b22050dc0030b20064101101c000b2006101b22050dbc030b20064101101c000b2006101b22050db8030b20064101101c000b2006101b22050db4030b20064101101c000b2006101b22050db0030b20064101101c000b2006101b22050dac030b20064101101c000b2006101b22050da8030b20064101101c000b2006101b22050da4030b20064101101c000b2008101b22090da0030b20084101101c000b2006101b22050d9c030b20064101101c000b2006101b22050d98030b20064101101c000b2006101b22050d94030b20064101101c000b2006101b22050d90030b20064101101c000b2006101b22050d8c030b20064101101c000b2006101b22050d88030b20064101101c000b2006101b22050d84030b20064101101c000b2009101b22060d80030b20094101101c000b2006101b22050dfc020b20064101101c000b2006101b22050df8020b20064101101c000b2006101b22050df4020b20064101101c000b2006101b22050df0020b20064101101c000b2006101b22050dec020b20064101101c000b2006101b22050de8020b20064101101c000b2006101b22050de4020b20064101101c000b2005101b22080de0020b20054101101c000b2008101b22090ddc020b20084101101c000b2006101b22050dd8020b20064101101c000b2006101b22050dd3020b20064101101c000b2006101b22050dcf020b20064101101c000b2006101b22050dcb020b20064101101c000b2006101b22050dc7020b20064101101c000b2006101b22050dc3020b20064101101c000b2006101b22050dbf020b20064101101c000b2006101b22050dbb020b20064101101c000b2006101b22050db7020b20064101101c000b2006101b22050db3020b20064101101c000b2006101b22050daf020b20064101101c000b2006101b22050dab020b20064101101c000b2006101b22050da7020b20064101101c000b2006101b22050da3020b20064101101c000b2006101b22050d9f020b20064101101c000b2006101b22050d9b020b20064101101c000b2006101b22050d97020b20064101101c000b2006101b22050d93020b20064101101c000b2006101b22050d8f020b20064101101c000b2006101b22050d8b020b20064101101c000b2006101b22050d87020b20064101101c000b2006101b22050d83020b20064101101c000b2006101b22050dff010b20064101101c000b2006101b22050dfb010b20064101101c000b2006101b22050df7010b20064101101c000b2006101b22050df3010b20064101101c000b2006101b22050def010b20064101101c000b2006101b22050deb010b20064101101c000b2006101b22050de7010b20064101101c000b2008101b22090de3010b20084101101c000b2008101b22050ddf010b20084101101c000b2009101b22060ddb010b20094101101c000b2006101b22050dd7010b20064101101c000b2006101b22050dd3010b20064101101c000b2006101b22050dcf010b20064101101c000b2006101b22050dcb010b20064101101c000b2006101b22050dc7010b20064101101c000b2006101b22050dc3010b20064101101c000b2006101b22050dbf010b20064101101c000b2006101b22050dbb010b20064101101c000b2006101b22050db7010b20064101101c000b2006101b22050db3010b20064101101c000b2006101b22050daf010b20064101101c000b2006101b22050dab010b20064101101c000b2006101b22050da7010b20064101101c000b2006101b22050da3010b20064101101c000b2006101b22050d9f010b20064101101c000b2006101b22050d9b010b20064101101c000b2006101b22050d97010b20064101101c000b2006101b22050d93010b20064101101c000b2006101b22050d8f010b20064101101c000b2008101b22090d8b010b20084101101c000b2008101b22090d87010b20084101101c000b2006101b22050d83010b20064101101c000b2006101b22050d7f0b20064101101c000b2006101b22050d7b0b20064101101c000b2009101b22060d770b20094101101c000b2006101b22050d730b20064101101c000b2006101b22050d6f0b20064101101c000b2006101b22050d6b0b20064101101c000b2008101b22090d670b20084101101c000b2006101b22050d630b20064101101c000b2006101b22050d5f0b20064101101c000b2006101b22050d5b0b20064101101c000b2006101b22050d570b20064101101c000b2006101b22050d530b20064101101c000b2006101b22050d4f0b20064101101c000b2006101b22050d4b0b20064101101c000b2006101b22050d470b20064101101c000b2005101b22080d430b20054101101c000b2006101b22050d3f0b20064101101c000b2006101b22050d3b0b20064101101c000b2008101b22090d370b20084101101c000b2006101b22050d330b20064101101c000b2006101b22050d2f0b20064101101c000b2008101b22090d2b0b20084101101c000b2008101b22090d270b20084101101c000b2006101b22050d230b20064101101c000b2001101b22060d1f0b20014101101c000b2008101b22090d1b0b20084101101c000b2006101b22050d170b20064101101c000b2008101b22090d130b20084101101c000b2005101b22080d0f0b20054101101c000b2006101b22050d0b0b20064101101c000b2005101b22080d070b20054101101c000b2006101b22050d030b20064101101c000b101d000b101d000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000cdd020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a410d3a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490dcf0220024101742209200620062009491b22094100480dcf022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cdd020b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000cd9020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a410c3a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490dcb0220024101742209200620062009491b22094100480dcb022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cd9020b0b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41333a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dca022004410174220d20092009200d491b220d4100480dca022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dca0220024101742209200620062009491b22094100480dca022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cd8020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000cd3020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413a3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dd1022004410174220d20092009200d491b220d4100480dd1022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dd10220024101742209200620062009491b22094100480dd1022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cd4020b0b200d4101101c000b20094101101c000b200241086a2001360200200241046a20063602002002410c6a28020021050b2002410c6a2201200541016a360200200620056a410e3a00002003200b200d200d200b4102746a2002101e0240024020032d0000411a470d00200241086a2106200241046a210703400240024002400240200628020020012802002202470d00200241016a22052002490dc40220024101742208200520052008491b22084100480dc4022002450d01200928020020022008101a22050d020c060b200928020021050c020b2008101b2205450d040b2006200836020020072005360200200128020021020b2001200241016a360200200520026a200441807f72200441ff0071200441077622021b3a00002002210420020d000b0240200b41ffffffff0371450d00200d10190b2000411a3a0000200341106a24000f0b20002003290300370200200041086a200341086a290300370200200b41ffffffff0371450dd102200d1019200341106a24000f0b20084101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000ccd020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412d3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dc0022004410174220d20092009200d491b220d4100480dc0022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dc00220024101742209200620062009491b22094100480dc0022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cce020b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41323a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dbe022004410174220d20092009200d491b220d4100480dbe022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dbe0220024101742209200620062009491b22094100480dbe022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000ccc020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000cc7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000cc5020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41393a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dc3022004410174220d20092009200d491b220d4100480dc3022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dc30220024101742209200620062009491b22094100480dc3022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cc6020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000cc1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000cbf020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41223a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490db10220024101742209200620062009491b22094100480db1022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cbf020b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000cbb020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000cb9020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000cb7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000cb5020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000cb3020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000cb1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000caf020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000cad020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41313a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490da0022004410174220d20092009200d491b220d4100480da0022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490da00220024101742209200620062009491b22094100480da0022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cae020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000ca9020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000ca7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000ca5020b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41c3003a000002400240024002400240200241086a2802002206200928020022046b41044f0d00200441046a22092004490da10220064101742204200920092004491b22044100480da1022006450d01200528020020062004101a2205450d020c030b200528020021050c030b2004101b22050d010b20044101101c000b200241086a2004360200200241046a20053602002002410c6a28020021040b2002410c6a200441046a360200200520046a20083600000ca3020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000ca1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c9f020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c9d020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41373a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d9b022004410174220d20092009200d491b220d4100480d9b022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d9b0220024101742209200620062009491b22094100480d9b022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c9e020b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412e3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d8e022004410174220d20092009200d491b220d4100480d8e022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d8e0220024101742209200620062009491b22094100480d8e022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c9c020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c97020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c95020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c93020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c91020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c8f020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c8d020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c8b020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c89020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c87020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c85020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c83020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c81020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000cff010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000cfd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000cfb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000cf9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000cf7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000cf5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000cf3010b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a413f3a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490def0120044101742209200620062009491b22064100480def012004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a20083a00000cf1010b200241086a2008360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a0000200320062002101f20032d0000411a460def0120002003290300370200200041086a200341086a29030037020020012d00004109470df0010c3a0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412f3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490de2012004410174220d20092009200d491b220d4100480de2012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490de20120024101742209200620062009491b22094100480de2012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cf0010b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000ceb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000ce9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000ce7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000ce5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000ce3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000ce1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000cdf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000cdd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000cdb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000cd9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000cd7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000cd5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000cd3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000cd1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000ccf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000ccd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000ccb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000cc9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000cc7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000cc5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000cc3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000cc1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000cbf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000cbd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000cbb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000cb9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000cb7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200a2002102020032d0000411a460db50120002003290300370200200041086a200341086a29030037020020012d00004109470db6010b200141086a28020041ffffffff0371450db501200141046a2802001019200341106a24000f0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000cb2010b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41293a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490da5012004410174220d20092009200d491b220d4100480da5012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490da50120024101742209200620062009491b22094100480da5012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cb3010b0b200d4101101c000b20094101101c000b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41233a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490da20120024101742209200620062009491b22094100480da2012002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cb0010b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000cac010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000caa010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000ca8010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000ca6010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000ca4010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000ca2010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000ca0010b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41c0003a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d9c0120044101742209200620062009491b22064100480d9c012004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a20083a00000c9e010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c9c010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c9a010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c98010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c96010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c94010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c92010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c90010b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413e3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d8e012004410174220d20092009200d491b220d4100480d8e012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d8e0120024101742209200620062009491b22094100480d8e012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c91010b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c8c010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c8a010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c88010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c86010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c84010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c82010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c80010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c7e0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413d3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d7c2004410174220d20092009200d491b220d4100480d7c2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d7c20024101742209200620062009491b22094100480d7c2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c7f0b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41383a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d7a2004410174220d20092009200d491b220d4100480d7a2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d7a20024101742209200620062009491b22094100480d7a2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c7d0b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c780b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c760b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c740b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412b3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d672004410174220d20092009200d491b220d4100480d672004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d6720024101742209200620062009491b22094100480d672002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c750b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41343a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d652004410174220d20092009200d491b220d4100480d652004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d6520024101742209200620062009491b22094100480d652002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c730b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c6e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c6c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c6a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c680b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c660b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c640b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c620b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c600b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c5e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c5c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c5a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c580b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c560b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41303a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d492004410174220d20092009200d491b220d4100480d492004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d4920024101742209200620062009491b22094100480d492002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c570b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c520b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41283a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d452004410174220d20092009200d491b220d4100480d452004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d4520024101742209200620062009491b22094100480d452002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c530b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000c4e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c4c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c4a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c480b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c460b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c440b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41243a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d3620024101742209200620062009491b22094100480d362002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c440b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c400b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41033a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d3120044101742209200620062009491b22064100480d312004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c3e0b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41213a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d3020024101742209200620062009491b22094100480d302002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c3e0b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c3a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c380b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c360b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c340b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c320b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41203a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d2420024101742209200620062009491b22094100480d242002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c320b0b20094101101c000b200241086a2006360200200241046a20083602002002410c6a28020021040b2002410c6a2206200441016a360200200820046a41113a0000200241086a2109200241046a210d02400240024003400240024002400240200928020020062802002204470d00200441016a22082004490d2420044101742207200820082007491b22074100480d242004450d01200b28020020042007101a22080d020c050b200b28020021080c020b2007101b2208450d030b20092007360200200d2008360200200628020021040b2006200441016a360200200820046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b024002400240200241086a2802002002410c6a2802002204470d00200441016a22052004490d2220044101742206200520052006491b22064100480d222004450d01200b28020020042006101a2205450d020c040b200b28020021050c040b2006101b22050d020b20064101101c000b20074101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a200c3a00000c2e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c2c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c2a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c280b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41043a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d1920044101742209200620062009491b22064100480d192004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c260b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41363a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d242004410174220d20092009200d491b220d4100480d242004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d2420024101742209200620062009491b22094100480d242002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c270b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c220b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41103a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d1420024101742209200620062009491b22094100480d142002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c220b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c1e0b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41023a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d0f20044101742209200620062009491b22064100480d0f2004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c1c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c1a0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41353a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d182004410174220d20092009200d491b220d4100480d182004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d1820024101742209200620062009491b22094100480d182002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c1b0b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c160b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412c3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d092004410174220d20092009200d491b220d4100480d092004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0920024101742209200620062009491b22094100480d092002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c170b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412a3a0000200241086a210b200241046a210c03400240024002400240200b28020020082802002204470d00200441016a22092004490d052004410174220d20092009200d491b220d4100480d052004450d0120072802002004200d101a22090d020c060b200728020021090c020b200d101b2209450d040b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0520024101742209200620062009491b22094100480d052002450d01200728020020022009101a22060d020c070b200728020021060c020b2009101b2206450d050b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c130b0b101d000b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413b3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d0d2004410174220d20092009200d491b220d4100480d0d2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0d20024101742209200620062009491b22094100480d0d2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c100b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c0b0b200241086a2008360200200241046a20063602002002410c6a28020021040b2002410c6a2208200441016a360200200620046a41c4003a000002400240024002400240200241086a2802002206200828020022046b41084f0d00200441086a22082004490d0720064101742204200820082004491b22044100480d072006450d01200528020020062004101a2205450d020c030b200528020021050c030b2004101b22050d010b20044101101c000b200241086a2004360200200241046a20053602002002410c6a28020021040b2002410c6a200441086a360200200520046a200a3700000c090b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413c3a0000200241086a210b200241046a210c03400240024002400240200b28020020082802002204470d00200441016a22092004490d052004410174220d20092009200d491b220d4100480d052004450d0120072802002004200d101a22090d020c060b200728020021090c020b200d101b2209450d040b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22052002490d0520024101742209200520052009491b22094100480d052002450d01200728020020022009101a22050d020c070b200728020021050c020b2009101b2205450d050b20082009360200200b2005360200200428020021020b2004200241016a360200200520026a200641807f72200641ff0071200641077622021b3a00002002210620020d000c080b0b101d000b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000c020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000b2000411a3a000020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010190b200341106a24000b070020001084030b0b002000200120021085030b070020001083030b0d0041f985c2004122100400000b0a004194d8c3001029000bc60301067f2004410c6a2105200441086a2106200441046a210702400240024003400240024002400240200628020020052802002208470d00200841016a22092008490d052008410174220a20092009200a491b220a4100480d052008450d0120072802002008200a101a22090d020c070b200728020021090c020b200a101b2209450d050b2006200a36020020072009360200200528020021080b2005200841016a360200200920086a200141807f72200141ff0071200141077622081b3a00002008210120080d000b024020022003460d002004410c6a2105200441086a2106200441046a210703402002280200210103400240024002400240200628020020052802002208470d00200841016a22092008490d072008410174220a20092009200a491b220a4100480d072008450d0120072802002008200a101a22090d020c080b200728020021090c020b200a101b2209450d060b2006200a36020020072009360200200528020021080b2005200841016a360200200920086a200141807f72200141ff0071200141077622081b3a00002008210120080d000b200241046a22022003470d000b0b2000411a3a00000f0b101d000b200a4101101c000b200a4101101c000bd40301077f200141c000712103200141ff00712104024002400240024002400240200141077522050d002003450d010b2002410c6a2106200241086a2107200241046a2108034002402005417f470d00200341ff01710d020b0240024002400240200728020020062802002209470d00200941016a22032009490d0620094101742204200320032004491b22044100480d062009450d01200828020020092004101a22030d020c070b200828020021030c020b2004101b2203450d050b2007200436020020082003360200200628020021090b2006200941016a360200200320096a200141807f723a0000200541c000712103200541ff007121042005210120054107752209210520090d002009210520030d000b0b024002400240200241086a2802002002410c6a2802002205470d00200541016a22092005490d0320054101742206200920092006491b22064100480d032005450d01200241046a28020020052006101a2209450d020c050b200241046a28020021090c050b2006101b22090d030b20064101101c000b101d000b20044101101c000b200241086a2006360200200241046a20093602002002410c6a28020021050b2002410c6a200541016a360200200920056a20043a00002000411a3a00000bd40301077f2001a7220341c000712104200341ff00712105024002400240024002400240200142078722014200520d002004450d010b2002410c6a2106200241086a2107200241046a2108034002402001427f520d00200441ff01710d020b0240024002400240200728020020062802002204470d00200441016a22052004490d0620044101742209200520052009491b22094100480d062004450d01200828020020042009101a22050d020c070b200828020021050c020b2009101b2205450d050b2007200936020020082005360200200628020021040b2006200441016a360200200520046a200341807f723a00002001a7220341c000712104200341ff00712105200142078722014200520d0020040d000b0b024002400240200241086a2802002002410c6a2802002204470d00200441016a22032004490d0320044101742206200320032006491b22064100480d032004450d01200241046a28020020042006101a2203450d020c050b200241046a28020021030c050b2006101b22030d030b20064101101c000b101d000b20094101101c000b200241086a2006360200200241046a20033602002002410c6a28020021040b2002410c6a200441016a360200200320046a20053a00002000411a3a00000bd403020a7f017e230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a2001102220022802184101460d01200220032900003703082002200429000037000f200241186a41086a2d0000210a2002200229000f37001f20022002290308370318024020072008470d00200741016a220b2007490d032005200b200b2005491b2208ad420486220c422088a70d03200ca7220b4100480d0302402007450d0020092006200b101a22090d010c050b200b101b2209450d040b200920066a220b200a3a0000200b41086a200229001f370000200b41016a2002290318370000200541026a2105200641106a2106200741016a2107200a41ff01714106470d000b20002009360204200041003602002000410c6a2007360200200041086a2008360200200241306a24000f0b2000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d00200741086a28020041ffffffff0371450d00200741046a28020010190b200741106a2107200641706a22060d000b0b02402008450d00200910190b200241306a24000f0b101d000b200b4108101c000bacb40103087f017e037f230041d0006b22022400024020012802082203200128020c2204470d00200241013a0027200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241276a3602182002200241186a360248200241286a200241386a1024200241c3006a200241306a2802003600002002200229032837003b20022002413f6a29000037000f20022002290038370308200041053a000420004101360200200020022903083700052000410c6a200229000f370000200241d0006a24000f0b200441016a21050240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004417f460d0020032005490d012001280200220620046a2d000021072001410c6a2208200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020070ec00183048304008401248304aa01aa01aa01aa01aa01a801a501a701a101200b11aa01aa01aa01aa01aa01aa01aa01aa01a60103aa01aa01aa01aa0112189801511aaa01aa01aa0121520533069f0186016f238f019e01a40132080d8801379b01a20104013841714970548b010209441476783f8101752226778701070c252c1016920194011f96019a01a3015ba0011599015e1b5a0f9c019d011d900174720a0e42452813950119602f91018e01890129173497013a27644b5565624a7d407b2e8a0185012b8c0193011c463e2d8d016e3b1e7c5f487982012a3130363d6d5c6c80017f3583014e4f7e7366617a695d39533c674c436a4d6b576863475650585983040b200241386a2001102520022d00384101470dae012000200229023c370204200041013602002000410c6a200241386a410c6a290200370200200241d0006a24000f0b410120036b2107200441026a2101410021054100210903402005411f4b0db201200720016a4102460dd2012001450dff0220032001490d8003200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d960220046741686a41ff017141044f0d9602410d21010cd2010b200320056b41084f0da801200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a10242002290308210a200041106a2002280210360200200041086a200a37020020004281808080d000370300200241d0006a24000f0b410e21070ca5010b410120036b2107200441026a2101410021054100210903402005411f4b0db001200720016a4102460dd1012001450dfe0220032001490dff02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d940220046741686a41ff017141044f0d9402410d21010cd1010b410120036b2107200441026a2101410021054100210903402005411f4b0db001200720016a4102460dd2012001450dff0220032001490d8003200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d940220046741686a41ff017141044f0d9402410d21010cd2010b410120036b2107200441026a2101410021054100210903402005411f4b0db001200720016a4102460dd3012001450d800320032001490d8103200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d940220046741686a41ff017141044f0d9402410d21010cd3010b413d21070ca1010b410120036b2107200441026a2101410021054100210903402005411f4b0daf01200720016a4102460dd3012001450d800320032001490d8103200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d930220046741686a41ff017141044f0d9302410d21010cd3010b413121070c9f010b41d70021070c9e010b410021014100210903402001411f4b0dad0120032005460dd2012005417f460dff022003200541016a2207490d8003200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490dd3010b410b21070cf6030b413e21070c9c010b410120036b2107200441026a2101410021054100210903402005411f4b0dac01200720016a4102460dd2012001450dff0220032001490d8003200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d8f0220046741686a41ff017141044f0d8f02410d21010cd2010b41d80021070c9a010b41d00021070c99010b41c10021070c98010b410021014100210903402001411f4b0da90120032005460dd0012005417f460dfd022003200541016a2204490dfe02200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b024020014120490d00410d210120076741686a41ff01714104490dd1010b20032004470d9f02200241013a0027200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241276a3602182002200241186a360248200241286a200241386a1024200241c3006a200241306a2802003600002002200229032837003b20022002413f6a29000037000f20022002290038370308200041053a000420004101360200200020022903083700052000410c6a200229000f370000200241d0006a24000f0b410021014100210903402001411f4b0da90120032005460dd1012005417f460dfe022003200541016a2207490dff02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490dd2010b410f21070cef030b41dc0021070c95010b413321070c94010b41cb0021070c93010b41c20021070c92010b41e50021070c91010b410021014100210903402001411f4b0da40120032005460dcd012005417f460dfa022003200541016a2207490dfb02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490dce010b411021070ce9030b41de0021070c8f010b410021014100210903402001411f4b0da30120032005460dcd012005417f460dfa022003200541016a2207490dfb02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490dce010b411321070ce7030b41ce0021070c8d010b41f90021070c8c010b41d30021070c8b010b41800121070c8a010b41c50021070c89010b410a21070c88010b410120036b2107200441026a2101410021054100210903402005411f4b0d9d01200720016a4102460dc8012001450df50220032001490df602200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490dfc0120046741686a41ff017141044f0dfc01410d21010cc8010b413921070c86010b410120036b2107200441026a2101410021054100210903402005411f4b0d9c01200720016a4102460dc8012001450df50220032001490df602200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490dfb0120046741686a41ff017141044f0dfb01410d21010cc8010b200241386a2001102520022d00384101470d87012000200229023c370204200041013602002000410c6a200241386a410c6a290200370200200241d0006a24000f0b413f21070c83010b413a21070c82010b41e90021070c81010b41db0021070c80010b41e40021070c7f0b41860121070c7e0b41f60021070c7d0b41c00021070c7c0b41fc0021070c7b0b41f30021070c7a0b41e00021070c790b41880121070c780b41870121070c770b410120036b2107200441026a2101410021054100210903402005411f4b0d8e01200720016a4102460dbb012001450de80220032001490de902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490ded0120046741686a41ff017141044f0ded01410d21010cbb010b410120036b2107200441026a2101410021054100210903402005411f4b0d8e01200720016a4102460dbc012001450de90220032001490dea02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490ded0120046741686a41ff017141044f0ded01410d21010cbc010b41e60021070c740b41900121070c730b41890121070c720b410120036b2107200441026a2101410021054100210903402005411f4b0d8b01200720016a4102460dba012001450de70220032001490de802200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490dea0120046741686a41ff017141044f0dea01410d21010cba010b410120036b2107200441026a2101410021054100210903402005411f4b0d8b01200720016a4102460dbb012001450de80220032001490de902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490dea0120046741686a41ff017141044f0dea01410d21010cbb010b419b0121070c6f0b41e80021070c6e0b41ff0021070c6d0b419d0121070c6c0b418a0121070c6b0b41fb0021070c6a0b413621070c690b41f10021070c680b410120036b2107200441026a2101410021054100210903402005411f4b0d8301200720016a4102460db4012001450de10220032001490de202200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490de20120046741686a41ff017141044f0de201410d21010cb4010b41d90021070c660b41a00121070c650b413221070c640b41da0021070c630b41fa0021070c620b41a70121070c610b41830121070c600b20032005470d63200241013a0027200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241276a3602182002200241186a360248200241286a200241386a1024200241c3006a200241306a2802003600002002200229032837003b20022002413f6a29000037000f20022002290038370308200041053a000420004101360200200020022903083700052000410c6a200229000f370000200241d0006a24000f0b41ef0021070c5e0b41eb0021070c5d0b419f0121070c5c0b41a20121070c5b0b41920121070c5a0b41930121070c590b41a90121070c580b410021014100210903402001411f4b0d7420032005460da6012005417f460dd3022003200541016a2207490dd402200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490da7010b411221070cb0030b410120036b2107200441026a2101410021054100210903402005411f4b0d74200720016a4102460da7012001450dd40220032001490dd502200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490dd20120046741686a41ff017141044f0dd201410d21010ca7010b419c0121070c550b4200210a410021010340410e21072001413f4b0ddf0120032005460da7012005417f460dd4022003200541016a2209490dd502200620056a2d0000210420082009360200200441ff0071220bad2001413f71ad86200a84210a200141076a21012009210520044118744118752209417f4c0d000b200941c0007121052001413f4b0dd1012005450dd101200a427f2001413f71ad8684210a412e21070cac030b41ec0021070c530b41a80121070c520b41a40121070c510b41aa0121070c500b41ab0121070c4f0b41cf0021070c4e0b41c90021070c4d0b418c0121070c4c0b419a0121070c4b0b41cd0021070c4a0b41820121070c490b41df0021070c480b41970121070c470b41ee0021070c460b41a60121070c450b41ea0021070c440b41ed0021070c430b41960121070c420b419e0121070c410b41a50121070c400b41990121070c3f0b41a10121070c3e0b41a30121070c3d0b418d0121070c3c0b418b0121070c3b0b41fe0021070c3a0b410120036b2107200441026a2101410021054100210903402005411f4b0d58200720016a4102460d8d012001450dbb0220032001490dbc02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490db70120046741686a41ff017141044f0db701410d21010c8d010b41002101410021090340410d210b2001411f4b0d8e0320032005460d8e012005417f460dbc022003200541016a2204490dbd02200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a210120042105200741187441187522044100480d000b200441c0007121052001411f4b0db7012005450db7012009417f2001411f7174722109412d21070c91030b20032005470d3c200241013a0027200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241276a3602182002200241186a360248200241286a200241386a1024200241c3006a200241306a2802003600002002200229032837003b20022002413f6a29000037000f20022002290038370308200041053a000420004101360200200020022903083700052000410c6a200229000f370000200241d0006a24000f0b41d60021070c360b41950121070c350b41d50021070c340b413821070c330b413421070c320b413b21070c310b413521070c300b41840121070c2f0b41980121070c2e0b41f20021070c2d0b41810121070c2c0b41f00021070c2b0b41940121070c2a0b418f0121070c290b418e0121070c280b413721070c270b41850121070c260b41910121070c250b200241386a2001102520022d00384101470d2b2000200229023c370204200041013602002000410c6a200241386a410c6a290200370200200241d0006a24000f0b41f50021070c230b410120036b2107200441026a2101410021054100210903402005411f4b0d42200720016a4102460d792001450da80220032001490da902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490da20120046741686a41ff017141044f0da201410d21010c790b413c21070c210b410120036b2107200441026a2101410021054100210903402005411f4b0d41200720016a4102460d792001450da80220032001490da902200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490da10120046741686a41ff017141044f0da101410d21010c790b41e30021070c1f0b41f40021070c1e0b200320056b41044f0d25200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420004281808080d000370300200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b41f70021070c1c0b41fd0021070c1b0b41e20021070c1a0b410120036b2107200441026a2101410021054100210903402005411f4b0d3b200720016a4102460d742001450da30220032001490da402200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d9b0120046741686a41ff017141044f0d9b01410d21010c740b41d40021070c180b41e10021070c170b41c30021070c160b41f80021070c150b41c40021070c140b41dd0021070c130b41c60021070c120b41e70021070c110b410021014100210903402001411f4b0d3320032005460d6d2005417f460d9c022003200541016a2207490d9d02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490d6e0b411121070ce9020b41cc0021070c0f0b41c70021070c0e0b410120036b2107200441026a2101410021054100210903402005411f4b0d31200720016a4102460d6c2001450d9b0220032001490d9c02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d900120046741686a41ff017141044f0d9001410d21010c6c0b41d10021070c0c0b41d20021070c0b0b410120036b2107200441026a2101410021054100210903402005411f4b0d2f200720016a4102460d6b2001450d9a0220032001490d9b02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d8e0120046741686a41ff017141044f0d8e01410d21010c6b0b410120036b2107200441026a2101410021054100210903402005411f4b0d2f200720016a4102460d6c2001450d9b0220032001490d9c02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d8e0120046741686a41ff017141044f0d8e01410d21010c6c0b41ca0021070c080b200241386a2001102641042109200228023822064101470d10200041013602002000200241386a41047222012902003702042000410c6a200141086a290200370200200241d0006a24000f0b410120036b2107200441026a2101410021054100210903402005411f4b0d2d200720016a4102460d6b2001450d9a0220032001490d9b02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d8c0120046741686a41ff017141044f0d8c01410d21010c6b0b41c80021070c050b410120036b2107200441026a2101410021054100210903402005411f4b0d2c200720016a4102460d6b2001450d9a0220032001490d9b02200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d8b0120046741686a41ff017141044f0d8b01410d21010c6b0b410021014100210903402001411f4b0d2c20032005460d6c2005417f460d9b022003200541016a2207490d9c02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490d6d0b410721070cdc020b410d21070c020b410021014100210903402001411f4b0d2b20032005460d6c2005417f460d9b022003200541016a2207490d9c02200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b024020014120490d00410d210120046741686a41ff01714104490d6d0b410821070cda020b410621070b0cd7020b2000410b3a000420004101360200200041056a20073a0000200241d0006a24000f0b200441096a2101200541784f0dc70220032001490dc802200620056a290000210a20082001360200413021070cd5020b20022d0039210b410421070cd6020b200441026a21012005417f460dc70220032001490dc802200620056a2d00002109200820013602002009450d67200041153a000420004101360200200041056a20093a0000200241d0006a24000f0b200441026a21012005417f460dc80220032001490dc902200620056a2d00002109200820013602002009450d67200041153a000420004101360200200041056a20093a0000200241d0006a24000f0b20022d0039210b410221070cd3020b20022d0039210b410321070cd2020b200441056a21012005417c4f0dc70220032001490dc802200620056a280000210920082001360200412f21070cd0020b200241c0006a280200210b200228023c2103200241c4006a2802002205450d642005410274220c4102752207ad420286220a422088a70dbf02200aa722044100480dbf022004101b2209450dc80220054102742104200c417c6a210c410021050340200920056a200320056a2802003602002004200541046a2205470d000b200c41027641016a210d200b450dcd020ccc020b410f21010c200b410f21010c210b410f21010c220b410f21010c230b410f21010c240b410f21010c250b410f21010c260b410f21010c270b410f21010c280b410f21010c290b410f21010c2a0b410f21010c2b0b410f21010c2c0b410f21010c2d0b410f21010c2e0b410f21010c2f0b410f21010c300b410f21010c310b410f21010c320b410f21010c330b410f21010c350b410f21010c370b410f21010c380b410f21010c390b410f21010c3a0b410f21010c3b0b410f21010c3c0b410f21010c3d0b410f21010c3e0b410f21010c3f0b410f21010c400b410f21010c410b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0027200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241276a3602182002200241186a360248200241086a200241386a1024200228021021012002290308210a410521070c380b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a10244105210b0cff010b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102109200228020c210520022802082103410521010b2000200136020420004101360200200041106a20093602002000410c6a2005360200200041086a2003360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a102420022802102103200228020c210520022802082109410521010b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a2009360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b412c21074100210b0ced010b412b21074100210b0cec010b410021074100210d200b0de7010ce8010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d372001417f460dac012003200141016a2207490dad01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d380b200bad210a412821070ce9010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d382001417f460dad012003200141016a2207490dae01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d390b200bad210a412721070ce8010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d392001417f460dae012003200141016a2207490daf01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3a0b200bad210a411621070ce7010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3a2001417f460daf012003200141016a2207490db001200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3b0b200bad210a411821070ce6010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3b2001417f460db0012003200141016a2207490db101200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3c0b200bad210a412121070ce5010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3c2001417f460db1012003200141016a2207490db201200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3d0b200bad210a412221070ce4010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3d2001417f460db2012003200141016a2207490db301200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3e0b200bad210a411421070ce3010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3e2001417f460db3012003200141016a2207490db401200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d3f0b200bad210a411c21070ce2010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d3f2001417f460db4012003200141016a2207490db501200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b41202107024020054120490d00410d210120046741686a41ff01714104490d400b200bad210a0ce1010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d402001417f460db5012003200141016a2207490db601200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d410b200bad210a411721070ce0010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d412001417f460db6012003200141016a2207490db701200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d420b200bad210a412421070cdf010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d422001417f460db7012003200141016a2207490db801200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d430b200bad210a412921070cde010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d432001417f460db8012003200141016a2207490db901200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d440b200bad210a412a21070cdd010b2001417f6a2101410021054100210b03402005411f4b0d2020032001460d442001417f460db9012003200141016a2207490dba01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d450b200bad210a411521070cdc010b200141c000490d0b2005450d0b200b41ff00470d0c0c0e0b2001417f6a2101410021054100210b03402005411f4b0d1f20032001460d442001417f460db9012003200141016a2207490dba01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d450b200bad210a411b21070cda010b20014120490d0d2005450d0d2004417f7341ff00716741686a41ff01714105490dd5010c0e0b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d442001417f460db9012003200141016a2207490dba01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d450b200bad210a411a21070cd8010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d452001417f460dba012003200141016a2207490dbb01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d460b200bad210a412321070cd7010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d462001417f460dbb012003200141016a2207490dbc01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d470b200bad210a411d21070cd6010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d472001417f460dbc012003200141016a2207490dbd01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d480b200bad210a412521070cd5010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d482001417f460dbd012003200141016a2207490dbe01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d490b200bad210a411e21070cd4010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d492001417f460dbe012003200141016a2207490dbf01200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d4a0b200bad210a411921070cd3010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d4a2001417f460dbf012003200141016a2207490dc001200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d4b0b200bad210a412621070cd2010b2001417f6a2101410021054100210b03402005411f4b0d1e20032001460d4b2001417f460dc0012003200141016a2207490dc101200620016a2d0000210420082007360200200441ff00712005411f7174200b72210b200541076a2105200721012004418001710d000b024020054120490d00410d210120046741686a41ff01714104490d4c0b200bad210a411f21070cd1010b200441016a21012004417f460dca0120032001490dcb01200620046a2d00002105200820013602002005450d4b200041163a000420004101360200200041056a20053a0000200241d0006a24000f0b200141c000490d022009450d020b0b200020022f00283b0005200020073a000420004101360200200041106a2001360200200041086a200a370200200041076a2002412a6a2d00003a0000200241d0006a24000f0b412e21070ccb010b200441ff01716741686a41ff017141044b0d0020014120490d002005450dc7010b412d21070cca010b410f21010c170b410f21010c180b410f21010c190b410f21010c1a0b410f21010c1b0b410f21010c1c0b410f21010c1d0b410f21010c1e0b410f21010c1f0b410f21010c200b410f21010c210b410f21010c220b410f21010c230b410f21010c240b410f21010c250b410f21010c260b410f21010c270b410f21010c280b410f21010c290b410f21010c2a0b410f21010c2b0b410f21010c2c0b410f21010c2d0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b410c21074100210b0c85010b417f20051027000b200520031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f200541016a1027000b200541016a20031028000b417f200541016a1027000b200541016a20031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b417f200541016a1027000b200541016a20031028000b417f200541016a1027000b200541016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20031028000b101d000b200520011027000b200120031028000b417f20011027000b200120031028000b417f20011027000b200120031028000b200520011027000b200120031028000b20044104101c000b417f20011027000b200120031028000b2000200b36020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200241d0006a24000f0b200310190b024020022d003c4105470d002006450d00200241c4006a280200450d00200241c0006a28020010190b0240024002402007200d470d002007210d0c010b2007200d490d010240200d450d0020092007410274200d4102742205101a22090d0120054104101c000b4100210d02402007450d00200910190b410421090b410021052001410c6a210b200141086a210c410021070240024002400240024003402005411f4b0d01200c2802002206200b2802002203460d02200341016a21042003417f460d0420062004490d05200128020020036a2d0000210320082004360200200341ff00712005411f71742007722107200541076a21052003418001710d000b024020054120490d00410d210120036741686a41ff01714104490d030b2007ad422086200dad84210a410921070c070b410f21010c010b200241013a0028200241cc006a41013602002002410136021c2002420137023c200241c4d6c3003602382002200241286a3602182002200241186a360248200241086a200241386a1024410521010b2000200136020420004101360200200041086a2002290208370200200041106a200241086a41086a280200360200200d41ffffffff0371450d0620091019200241d0006a24000f0b417f20041027000b200420061028000b4190a5c2001029000b0b0b20004100360200200041106a200a3703002000410c6a2009360200200041096a200b3a0000200041086a20073a00000b200241d0006a24000b6b000240024020002d000022004101460d0020004102470d01200128021841b181c200410b2001411c6a28020028020c1100000f0b200128021841a481c200410d2001411c6a28020028020c1100000f0b2001280218419881c200410c2001411c6a28020028020c1100000b800301067f230041306b22022400200128020021030240024002400240024002400240200128020422044103742205450d00200341046a2106410021070340200628020020076a2107200641086a2106200541786a22050d000b200141146a280200450d010c020b41002107200141146a2802000d010b200721060c010b2004450d02024002402007410f4b0d002003280204450d010b200720076a220620074f0d010b4101210541002106200241086a21070c010b2006417f4c0d02200241086a210702402006450d002006101b22050d0120064101101c000b41012105410021060b200241003602102002200636020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a290200370300200220012902003703180240200241146a41bcd8c300200241186a1087030d0020002007290200370200200041086a200741086a280200360200200241306a24000f0b108803000b41acd8c30041004100104a000b102b000b810401047f230041d0006b220224000240024002400240024002400240024020012802082203200128020c2204470d00200241013a001f200241c4006a41013602002002410136024c20024201370234200241c4d6c30036023020022002411f6a3602482002200241c8006a360240200241206a200241306a10242002413a6a200241286a280200360100200220022903203701322002200241366a29010037011620022002290130370310410521010c010b200441016a21052004417f460d0520032005490d06200128020020046a2c000021042001410c6a2005360200024020044100480d00200441017441807f71200472220341ff0171220441847e6a220141034b0d02024020010e0400060405000b20004180063b0100200241d0006a24000f0b411821010b2002200229011637010620022002290310370300200041056a20043a0000200041046a20013a0000200041013a0000200041066a20022903003701002000410c6a2002290106370100200241d0006a24000f0b0240200441c001470d0020004180083b0100200241d0006a24000f0b200041013a0000200041056a20033a0000200041046a41063a0000200241d0006a24000f0b20004180023b0100200241d0006a24000f0b200041003b0100200241d0006a24000f0b20004180043b0100200241d0006a24000f0b417f20051027000b200520031028000bbb07030d7f017e017f230041c0006b22022400410021032001410c6a2104200141086a210541002106024002400240024002400240024002400240024002400240024002400240024003402003411f4b0d012005280200220720042802002208460d02200841016a21092008417f460d0920072009490d0a200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b024020034120490d00410d210320086741686a41ff01714104490d030b2006450d032001410c6a2107200141086a210a4100210b4104210c4100210d0340200d220e41016a210d410021034100210403402003411f4b0d07200a280200220520072802002208460d08200841016a21092008417f460d0c20052009490d0d200128020020086a2d0000210820072009360200200841ff00712003411f71742004722104200341076a21032008418001710d000b024020034120490d0020086741686a41ff01714104490d090b0240200b200e470d00200b4101742203200b41016a220820082003491b2203ad420286220f422088a70d0e200fa722084100480d0e02400240200b450d00200c200b4102742008101a220c0d010c110b2008101b220c450d100b2003210b0b20044108762110200c200e4102746a2004360200200d2006490d000c050b0b410f21030c010b200241013a000f2002413c6a4101360200200241013602142002420137022c200241c4d6c30036022820022002410f6a3602102002200241106a360238200241186a200241286a1024410521030b200241086a2208200241186a41086a280200360200200220022902183703002000200336020420004101360200200041086a2002290300370200200041106a20082802003602000c0c0b4104210c4100210b4100210d0b2000200c360204200041003602002000410c6a200d360200200041086a200b360200200241c0006a24000f0b410f21030c080b200241013a00002002413c6a4101360200200241013602142002420137022c200241c4d6c300360228200220023602102002200241106a360238200241186a200241286a102420022802202104200228021c21092002280218210841002110410521030c070b410d21030c060b417f20091027000b200920071028000b417f20091027000b200920051028000b101d000b20084104101c000b20004101360200200041106a20043602002000410c6a2009360200200041086a200836020020002010410874200372360204200b450d00200c1019200241c0006a24000f0b200241c0006a24000b7001017f230041306b2202240020022001360204200220003602002002412c6a41023602002002411c6a4102360200200241023602242002420237020c200241b4d9c3003602082002200241046a360228200220023602202002200241206a360218200241086a41c4d9c30010f201000b7001017f230041306b2202240020022001360204200220003602002002412c6a41023602002002411c6a4102360200200241023602242002420237020c20024194d9c3003602082002200241046a360228200220023602202002200241206a360218200241086a41a4d9c30010f201000b6902017f037e230041306b22012400200029020821022000290210210320002902002104200141146a410036020020012004370318200141d889c200360210200142013702042001200141186a36020020012003370328200120023703202001200141206a10f201000bd0ec0203077f017e037f230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220441aa014b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040eab01000b1c1001ab01a801aa01a401240d14a90104151b9b01541e2555063607a201890173279201a101a70135090f8a013a9e01a50105023b44754c74578e01030a47177a7c4285017926297b8b01080e282f1319950197012399019d01a6015ea301189c01611f5d129f01a00121930177760c1145482b1698011d6332940191018c012c1a379a013d2a674d5868644e8001437f318d0188012e8f019601204941309001723e228101624b7d86012d34333940705f6f84018301388701515282017869657e6c603c563f6a4f466d506e5a6b664a59535b5c000b200241086a2802002002410c6a2802002204470dcf01200441016a22052004490dfe0720044101742206200520052006491b22064100480dfe072004450d9f03200241046a28020020042006101a2205450da0030c8e080b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfd0720044101742206200520052006491b22064100480dfd072004450dd602200241046a28020020042006101a2205450dd7020c8b080b200241046a2107200141086a2802002106200141046a2802002105200241086a2802002002410c6a2802002204470daa01200441016a22082004490d870820044101742209200820082009491b22084100480d87082004450dd702200728020020042008101a2209450dd8020c85080b200241046a2105200141086a290300210a200241086a2802002002410c6a2802002204470daa01200441016a22062004490d860820044101742208200620062008491b22084100480d86082004450dd802200528020020042008101a2206450dd9020c82080b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfa0720044101742206200520052006491b22064100480dfa072004450dd902200241046a28020020042006101a2205450dda020cff070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490d840820044101742209200820082009491b22084100480d84082004450dda02200728020020042008101a2209450ddb020cfc070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df80720044101742209200820082009491b22084100480df8072004450ddb02200728020020042008101a2209450ddc020cf6070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df70720044101742209200820082009491b22084100480df7072004450ddc02200728020020042008101a2209450ddd020cf3070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d810820044101742206200520052006491b22064100480d81082004450ddd02200241046a28020020042006101a2205450dde020cf0070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490df50720044101742209200820082009491b22084100480df5072004450dde02200728020020042008101a2209450ddf020ced070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dff0720044101742206200520052006491b22064100480dff072004450ddf02200241046a28020020042006101a2205450de0020cea070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490df30720044101742209200620062009491b22094100480df3072004450de002200528020020042009101a2206450de1020ce7070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490da30520044101742206200520052006491b22064100480da3052004450de102200241046a28020020042006101a2205450de2020ce4070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490df10720064101742208200520052008491b22054100480df1072006450de202200728020020062005101a2208450de3020ce1070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dfb0720044101742206200520052006491b22064100480dfb072004450de302200241046a28020020042006101a2205450de4020cde070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470daa01200441016a22082004490dfa0720044101742209200820082009491b22084100480dfa072004450de402200728020020042008101a2209450de5020cdb070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490dee0720044101742209200620062009491b22094100480dee072004450de502200528020020042009101a2206450de6020cd8070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d9e0520044101742206200520052006491b22064100480d9e052004450de602200241046a28020020042006101a2205450de7020cd5070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df70720044101742206200520052006491b22064100480df7072004450de702200241046a28020020042006101a2205450de8020cd2070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df60720044101742206200520052006491b22064100480df6072004450de802200241046a28020020042006101a2205450de9020ccf070b200241046a210b200141046a280200210520012d0001210c200241086a2802002002410c6a2802002204470daa01200441016a22062004490dea0720044101742208200620062008491b22064100480dea072004450de902200b28020020042006101a2208450dea020ccc070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de90720064101742208200520052008491b22054100480de9072006450dea02200728020020062005101a2208450deb020cc9070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d990520044101742206200520052006491b22064100480d99052004450deb02200241046a28020020042006101a2205450dec020cc6070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df20720044101742206200520052006491b22064100480df2072004450dec02200241046a28020020042006101a2205450ded020cc3070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df10720044101742206200520052006491b22064100480df1072004450ded02200241046a28020020042006101a2205450dee020cc0070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490df00720044101742206200520052006491b22064100480df0072004450dee02200241046a28020020042006101a2205450def020cbd070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d950520044101742206200520052006491b22064100480d95052004450def02200241046a28020020042006101a2205450df0020cba070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de30720064101742208200520052008491b22054100480de3072006450df002200728020020062005101a2208450df1020cb7070b200241046a210520012d00012108200241086a2802002002410c6a2802002204470daa01200441016a22062004490de20720044101742209200620062009491b22094100480de2072004450df102200528020020042009101a2206450df2020cb4070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d920520044101742206200520052006491b22064100480d92052004450df202200241046a28020020042006101a2205450df3020cb1070b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470daa01200641016a22052006490de00720064101742208200520052008491b22054100480de0072006450df302200728020020062005101a2208450df4020cae070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dea0720044101742206200520052006491b22064100480dea072004450df402200241046a28020020042006101a2205450df5020cab070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d8f0520044101742206200520052006491b22064100480d8f052004450df502200241046a28020020042006101a2205450df6020ca8070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490de80720044101742206200520052006491b22064100480de8072004450df602200241046a28020020042006101a2205450df7020ca5070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490d8d0520044101742206200520052006491b22064100480d8d052004450df702200241046a28020020042006101a2205450df8020ca2070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490de60720044101742206200520052006491b22064100480de6072004450df802200241046a28020020042006101a2205450df9020c9f070b200241086a2802002002410c6a2802002204470daa01200441016a22052004490dda0720044101742206200520052006491b22064100480dda072004450df902200241046a28020020042006101a2205450dfa020c9c070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd90720044101742209200820082009491b22084100480dd9072004450dfc02200728020020042008101a2209450dfd020c99070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de30720044101742206200520052006491b22064100480de3072004450dfd02200241046a28020020042006101a2205450dfe020c96070b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd70720044101742209200820082009491b22084100480dd7072004450dfe02200728020020042008101a2209450dff020c93070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de10720044101742206200520052006491b22064100480de1072004450dff02200241046a28020020042006101a2205450d80030c90070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00720044101742206200520052006491b22064100480de0072004450d8003200241046a28020020042006101a2205450d81030c8d070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d850520044101742206200520052006491b22064100480d85052004450d8103200241046a28020020042006101a2205450d82030c8a070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d840520044101742206200520052006491b22064100480d84052004450d8203200241046a28020020042006101a2205450d83030c87070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d830520044101742206200520052006491b22064100480d83052004450d8303200241046a28020020042006101a2205450d84030c84070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d820520044101742206200520052006491b22064100480d82052004450d8403200241046a28020020042006101a2205450d85030c81070b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d810520044101742206200520052006491b22064100480d81052004450d8503200241046a28020020042006101a2205450d86030cfe060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dda0720044101742206200520052006491b22064100480dda072004450d8603200241046a28020020042006101a2205450d87030cfb060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dff0420044101742206200520052006491b22064100480dff042004450d8703200241046a28020020042006101a2205450d88030cf8060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfe0420044101742206200520052006491b22064100480dfe042004450d8803200241046a28020020042006101a2205450d89030cf5060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfd0420044101742206200520052006491b22064100480dfd042004450d8903200241046a28020020042006101a2205450d8a030cf2060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfc0420044101742206200520052006491b22064100480dfc042004450d8a03200241046a28020020042006101a2205450d8b030cef060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfb0420044101742206200520052006491b22064100480dfb042004450d8b03200241046a28020020042006101a2205450d8c030cec060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc90720044101742209200820082009491b22084100480dc9072004450d8c03200728020020042008101a2209450d8d030ce9060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc80720044101742209200820082009491b22084100480dc8072004450d8d03200728020020042008101a2209450d8e030ce6060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df80420044101742206200520052006491b22064100480df8042004450d8e03200241046a28020020042006101a2205450d8f030ce3060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df70420044101742206200520052006491b22064100480df7042004450d8f03200241046a28020020042006101a2205450d90030ce0060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df60420044101742206200520052006491b22064100480df6042004450d9003200241046a28020020042006101a2205450d91030cdd060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dcf0720044101742209200820082009491b22084100480dcf072004450d9103200728020020042008101a2209450d92030cda060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dce0720044101742209200820082009491b22084100480dce072004450d9203200728020020042008101a2209450d93030cd7060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df30420044101742206200520052006491b22064100480df3042004450d9303200241046a28020020042006101a2205450d94030cd4060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df20420044101742206200520052006491b22064100480df2042004450d9403200241046a28020020042006101a2205450d95030cd1060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df10420044101742206200520052006491b22064100480df1042004450d9503200241046a28020020042006101a2205450d96030cce060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df00420044101742206200520052006491b22064100480df0042004450d9603200241046a28020020042006101a2205450d97030ccb060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490def0420044101742206200520052006491b22064100480def042004450d9703200241046a28020020042006101a2205450d98030cc8060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dee0420044101742206200520052006491b22064100480dee042004450d9803200241046a28020020042006101a2205450d99030cc5060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc70720044101742206200520052006491b22064100480dc7072004450d9903200241046a28020020042006101a2205450d9a030cc2060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dec0420044101742206200520052006491b22064100480dec042004450d9a03200241046a28020020042006101a2205450d9b030cbf060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dc50720044101742209200820082009491b22084100480dc5072004450d9b03200728020020042008101a2209450d9c030cbc060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0420044101742206200520052006491b22064100480dea042004450d9c03200241046a28020020042006101a2205450d9d030cb9060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0420044101742206200520052006491b22064100480dea042004450d9d03200241046a28020020042006101a2205450d9e030cb6060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc20720044101742206200520052006491b22064100480dc2072004450d9e03200241046a28020020042006101a2205450d9f030cb3060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de70420044101742206200520052006491b22064100480de7042004450d9f03200241046a28020020042006101a2205450da0030cb0060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60420044101742206200520052006491b22064100480de6042004450da003200241046a28020020042006101a2205450da1030cad060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60420044101742206200520052006491b22064100480de6042004450da103200241046a28020020042006101a2205450da2030caa060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de40420044101742206200520052006491b22064100480de4042004450da203200241046a28020020042006101a2205450da3030ca7060b200241046a210520012d00012108200241086a2802002002410c6a2802002204470dab01200441016a22062004490dbd0720044101742209200620062009491b22094100480dbd072004450da303200528020020042009101a2206450da4030ca4060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de20420044101742206200520052006491b22064100480de2042004450da403200241046a28020020042006101a2205450da5030ca1060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de10420044101742206200520052006491b22064100480de1042004450da503200241046a28020020042006101a2205450da6030c9e060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00420044101742206200520052006491b22064100480de0042004450da603200241046a28020020042006101a2205450da7030c9b060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de00420044101742206200520052006491b22064100480de0042004450da703200241046a28020020042006101a2205450da8030c98060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dde0420044101742206200520052006491b22064100480dde042004450da803200241046a28020020042006101a2205450da9030c95060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ddd0420044101742206200520052006491b22064100480ddd042004450da903200241046a28020020042006101a2205450daa030c92060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ddd0420044101742206200520052006491b22064100480ddd042004450daa03200241046a28020020042006101a2205450dab030c8f060b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490daa0720064101742208200520052008491b22054100480daa072006450dab03200728020020062005101a2208450dac030c8c060b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490da90720044101742209200820082009491b22084100480da9072004450dac03200728020020042008101a2209450dad030c89060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd90420044101742206200520052006491b22064100480dd9042004450dad03200241046a28020020042006101a2205450dae030c86060b200141086a290300210a200241086a2802002002410c6a2802002204470dab01200441016a22052004490db20720044101742206200520052006491b22064100480db2072004450dae03200241046a28020020042006101a2205450daf030c82060b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd70420044101742206200520052006491b22064100480dd7042004450daf03200241046a28020020042006101a2205450db0030cff050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd70420044101742206200520052006491b22064100480dd7042004450db003200241046a28020020042006101a2205450db1030cfc050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd60420044101742206200520052006491b22064100480dd6042004450db103200241046a28020020042006101a2205450db2030cf9050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd50420044101742206200520052006491b22064100480dd5042004450db203200241046a28020020042006101a2205450db3030cf6050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd40420044101742206200520052006491b22064100480dd4042004450db303200241046a28020020042006101a2205450db4030cf3050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dac0720044101742206200520052006491b22064100480dac072004450db403200241046a28020020042006101a2205450db5030cf0050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dab0720044101742206200520052006491b22064100480dab072004450db503200241046a28020020042006101a2205450db6030ced050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd00420044101742206200520052006491b22064100480dd0042004450db603200241046a28020020042006101a2205450db7030cea050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcf0420044101742206200520052006491b22064100480dcf042004450db703200241046a28020020042006101a2205450db8030ce7050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da80720044101742206200520052006491b22064100480da8072004450db803200241046a28020020042006101a2205450db9030ce4050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcd0420044101742206200520052006491b22064100480dcd042004450db903200241046a28020020042006101a2205450dba030ce1050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcc0420044101742206200520052006491b22064100480dcc042004450dba03200241046a28020020042006101a2205450dbb030cde050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dcb0420044101742206200520052006491b22064100480dcb042004450dbb03200241046a28020020042006101a2205450dbc030cdb050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dca0420044101742206200520052006491b22064100480dca042004450dbc03200241046a28020020042006101a2205450dbd030cd8050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dca0420044101742206200520052006491b22064100480dca042004450dbd03200241046a28020020042006101a2205450dbe030cd5050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc80420044101742206200520052006491b22064100480dc8042004450dbe03200241046a28020020042006101a2205450dbf030cd2050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc70420044101742206200520052006491b22064100480dc7042004450dbf03200241046a28020020042006101a2205450dc0030ccf050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc60420044101742206200520052006491b22064100480dc6042004450dc003200241046a28020020042006101a2205450dc1030ccc050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc50420044101742206200520052006491b22064100480dc5042004450dc103200241046a28020020042006101a2205450dc2030cc9050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc50420044101742206200520052006491b22064100480dc5042004450dc203200241046a28020020042006101a2205450dc3030cc6050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc30420044101742206200520052006491b22064100480dc3042004450dc303200241046a28020020042006101a2205450dc4030cc3050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc30420044101742206200520052006491b22064100480dc3042004450dc403200241046a28020020042006101a2205450dc5030cc0050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc20420044101742206200520052006491b22064100480dc2042004450dc503200241046a28020020042006101a2205450dc6030cbd050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dc00420044101742206200520052006491b22064100480dc0042004450dc603200241046a28020020042006101a2205450dc7030cba050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dbf0420044101742206200520052006491b22064100480dbf042004450dc703200241046a28020020042006101a2205450dc8030cb7050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8d0720044101742206200520052006491b22064100480d8d072004450dc803200241046a28020020042006101a2205450dc9030cb4050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dbd0420044101742206200520052006491b22064100480dbd042004450dc903200241046a28020020042006101a2205450dca030cb1050b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490d8b0720044101742209200820082009491b22084100480d8b072004450dca03200728020020042008101a2209450dcb030cae050b200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22052004490d950720044101742208200520052008491b22084100480d95072004450dcb03200241046a28020020042008101a2205450dcc030cab050b200241046a210520012d00012108200241086a2802002002410c6a2802002204470dab01200441016a22062004490d940720044101742209200620062009491b22094100480d94072004450dcc03200528020020042009101a2206450dcd030ca8050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db90420044101742206200520052006491b22064100480db9042004450dcd03200241046a28020020042006101a2205450dce030ca5050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db80420044101742206200520052006491b22064100480db8042004450dce03200241046a28020020042006101a2205450dcf030ca2050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db70420044101742206200520052006491b22064100480db7042004450dcf03200241046a28020020042006101a2205450dd0030c9f050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d900720044101742206200520052006491b22064100480d90072004450dd003200241046a28020020042006101a2205450dd1030c9c050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8f0720044101742206200520052006491b22064100480d8f072004450dd103200241046a28020020042006101a2205450dd2030c99050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8e0720044101742206200520052006491b22064100480d8e072004450dd203200241046a28020020042006101a2205450dd3030c96050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d8d0720044101742206200520052006491b22064100480d8d072004450dd303200241046a28020020042006101a2205450dd4030c93050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db20420044101742206200520052006491b22064100480db2042004450dd403200241046a28020020042006101a2205450dd5030c90050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db10420044101742206200520052006491b22064100480db1042004450dd503200241046a28020020042006101a2205450dd6030c8d050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490db00420044101742206200520052006491b22064100480db0042004450dd603200241046a28020020042006101a2205450dd7030c8a050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490daf0420044101742206200520052006491b22064100480daf042004450dd703200241046a28020020042006101a2205450dd8030c87050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dae0420044101742206200520052006491b22064100480dae042004450dd803200241046a28020020042006101a2205450dd9030c84050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dad0420044101742206200520052006491b22064100480dad042004450dd903200241046a28020020042006101a2205450dda030c81050b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dac0420044101742206200520052006491b22064100480dac042004450dda03200241046a28020020042006101a2205450ddb030cfe040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dab0420044101742206200520052006491b22064100480dab042004450ddb03200241046a28020020042006101a2205450ddc030cfb040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d840720044101742206200520052006491b22064100480d84072004450ddc03200241046a28020020042006101a2205450ddd030cf8040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da90420044101742206200520052006491b22064100480da9042004450ddd03200241046a28020020042006101a2205450dde030cf5040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da80420044101742206200520052006491b22064100480da8042004450dde03200241046a28020020042006101a2205450ddf030cf2040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da70420044101742206200520052006491b22064100480da7042004450ddf03200241046a28020020042006101a2205450de0030cef040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490df50620044101742209200820082009491b22084100480df5062004450de003200728020020042008101a2209450de1030cec040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dff0620044101742209200820082009491b22084100480dff062004450de103200728020020042008101a2209450de2030ce9040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dfe0620044101742206200520052006491b22064100480dfe062004450de203200241046a28020020042006101a2205450de3030ce6040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da30420044101742206200520052006491b22064100480da3042004450de303200241046a28020020042006101a2205450de4030ce3040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da20420044101742206200520052006491b22064100480da2042004450de403200241046a28020020042006101a2205450de5030ce0040b200241046a2105200141046a2802002108200241086a2802002002410c6a2802002204470dab01200441016a22062004490dfb0620044101742209200620062009491b22094100480dfb062004450de503200528020020042009101a2206450de6030cdd040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490da00420044101742206200520052006491b22064100480da0042004450de603200241046a28020020042006101a2205450de7030cda040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9f0420044101742206200520052006491b22064100480d9f042004450de703200241046a28020020042006101a2205450de8030cd7040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9e0420044101742206200520052006491b22064100480d9e042004450de803200241046a28020020042006101a2205450de9030cd4040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dec0620044101742209200820082009491b22084100480dec062004450de903200728020020042008101a2209450dea030cd1040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df60620044101742206200520052006491b22064100480df6062004450dea03200241046a28020020042006101a2205450deb030cce040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d9b0420044101742206200520052006491b22064100480d9b042004450deb03200241046a28020020042006101a2205450dec030ccb040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df40620044101742206200520052006491b22064100480df4062004450dec03200241046a28020020042006101a2205450ded030cc8040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d990420044101742206200520052006491b22064100480d99042004450ded03200241046a28020020042006101a2205450dee030cc5040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df20620044101742206200520052006491b22064100480df2062004450dee03200241046a28020020042006101a2205450def030cc2040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d970420044101742206200520052006491b22064100480d97042004450def03200241046a28020020042006101a2205450df0030cbf040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490df00620044101742206200520052006491b22064100480df0062004450df003200241046a28020020042006101a2205450df1030cbc040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490d950420044101742206200520052006491b22064100480d95042004450df103200241046a28020020042006101a2205450df2030cb9040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490de30620064101742208200520052008491b22054100480de3062006450df203200728020020062005101a2208450df3030cb6040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490ded0620044101742206200520052006491b22064100480ded062004450df303200241046a28020020042006101a2205450df4030cb3040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dec0620044101742206200520052006491b22064100480dec062004450df403200241046a28020020042006101a2205450df5030cb0040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490deb0620044101742209200820082009491b22084100480deb062004450df503200728020020042008101a2209450df6030cad040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dea0620044101742206200520052006491b22064100480dea062004450df603200241046a28020020042006101a2205450df7030caa040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de90620044101742206200520052006491b22064100480de9062004450df703200241046a28020020042006101a2205450df8030ca7040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490ddd0620044101742209200820082009491b22084100480ddd062004450df803200728020020042008101a2209450df9030ca4040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490ddc0620044101742209200820082009491b22084100480ddc062004450df903200728020020042008101a2209450dfa030ca1040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de60620044101742206200520052006491b22064100480de6062004450dfa03200241046a28020020042006101a2205450dfb030c9e040b200241046a21092001410c6a2802002104200141086a280200210b200141046a280200210d200241086a2802002002410c6a2802002205470dab01200541016a22012005490dda0620054101742206200120012006491b22014100480dda062005450dfb03200928020020052001101a2206450dfc030c9b040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490de40620044101742209200820082009491b22084100480de4062004450dfc03200728020020042008101a2209450dfd030c98040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490de30620044101742206200520052006491b22064100480de3062004450dfd03200241046a28020020042006101a2205450dfe030c95040b200241046a2107200141086a2802002105200141046a2802002106200241086a2802002002410c6a2802002204470dab01200441016a22082004490dd70620044101742209200820082009491b22084100480dd7062004450dfe03200728020020042008101a2209450dff030c92040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490dd60620064101742208200520052008491b22054100480dd6062006450dff03200728020020062005101a2208450d80040c8f040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd50620044101742206200520052006491b22064100480dd5062004450d8004200241046a28020020042006101a2205450d81040c8c040b200241046a2107200141046a2802002104200241086a2802002002410c6a2802002206470dab01200641016a22052006490dd40620064101742208200520052008491b22054100480dd4062006450d8104200728020020062005101a2208450d82040c89040b200241086a2802002002410c6a2802002204470dab01200441016a22052004490dd30620044101742206200520052006491b22064100480dd3062004450d8204200241046a28020020042006101a2205450d83040c86040b200241046a28020021050ce1060b200728020021090cdb060b200528020021060cd8060b200241046a28020021050cd5060b200728020021090cd2060b200728020021090ccc060b200728020021090cc9060b200241046a28020021050cc6060b200728020021090cc3060b200241046a28020021050cc0060b200528020021060cbd060b200241046a28020021050cba060b200728020021080cb7060b200241046a28020021050cb4060b200728020021090cb1060b200528020021060cae060b200241046a28020021050cab060b200241046a28020021050ca8060b200241046a28020021050ca5060b200b28020021080ca2060b200728020021080c9f060b200241046a28020021050c9c060b200241046a28020021050c99060b200241046a28020021050c96060b200241046a28020021050c93060b200241046a28020021050c90060b200728020021080c8d060b200528020021060c8a060b200241046a28020021050c87060b200728020021080c84060b200241046a28020021050c81060b200241046a28020021050cfe050b200241046a28020021050cfb050b200241046a28020021050cf8050b200241046a28020021050cf5050b200241046a28020021050cf2050b200241046a28020021050cbf060b200728020021090cee050b200241046a28020021050ceb050b200728020021090ce8050b200241046a28020021050ce5050b200241046a28020021050ce2050b200241046a28020021050cdf050b200241046a28020021050cdc050b200241046a28020021050cd9050b200241046a28020021050cd6050b200241046a28020021050cd3050b200241046a28020021050cd0050b200241046a28020021050ccd050b200241046a28020021050cca050b200241046a28020021050cc7050b200241046a28020021050cc4050b200241046a28020021050cc1050b200728020021090cbe050b200728020021090cbb050b200241046a28020021050cb8050b200241046a28020021050cb5050b200241046a28020021050cb2050b200728020021090caf050b200728020021090cac050b200241046a28020021050ca9050b200241046a28020021050ca6050b200241046a28020021050ca3050b200241046a28020021050ca0050b200241046a28020021050c9d050b200241046a28020021050c9a050b200241046a28020021050c97050b200241046a28020021050c94050b200728020021090c91050b200241046a28020021050c8e050b200241046a28020021050c8b050b200241046a28020021050c88050b200241046a28020021050c85050b200241046a28020021050c82050b200241046a28020021050cff040b200241046a28020021050cfc040b200528020021060cf9040b200241046a28020021050cf6040b200241046a28020021050cf3040b200241046a28020021050cf0040b200241046a28020021050ced040b200241046a28020021050cea040b200241046a28020021050ce7040b200241046a28020021050ce4040b200728020021080ce1040b200728020021090cde040b200241046a28020021050cdb040b200241046a28020021050cd7040b200241046a28020021050cd4040b200241046a28020021050cd1040b200241046a28020021050cce040b200241046a28020021050ccb040b200241046a28020021050cc8040b200241046a28020021050cc5040b200241046a28020021050cc2040b200241046a28020021050cbf040b200241046a28020021050cbc040b200241046a28020021050cb9040b200241046a28020021050cb6040b200241046a28020021050cb3040b200241046a28020021050cb0040b200241046a28020021050cad040b200241046a28020021050caa040b200241046a28020021050ca7040b200241046a28020021050ca4040b200241046a28020021050ca1040b200241046a28020021050c9e040b200241046a28020021050c9b040b200241046a28020021050c98040b200241046a28020021050c95040b200241046a28020021050c92040b200241046a28020021050c8f040b200241046a28020021050c8c040b200241046a28020021050c89040b200241046a28020021050c86040b200728020021090c83040b200241046a28020021050c80040b200528020021060cfd030b200241046a28020021050cfa030b200241046a28020021050cf7030b200241046a28020021050cf4030b200241046a28020021050cf1030b200241046a28020021050cee030b200241046a28020021050ceb030b200241046a28020021050ce8030b200241046a28020021050ce5030b200241046a28020021050ce2030b200241046a28020021050cdf030b200241046a28020021050cdc030b200241046a28020021050cd9030b200241046a28020021050cd6030b200241046a28020021050cd3030b200241046a28020021050cd0030b200241046a28020021050ccd030b200241046a28020021050cca030b200241046a28020021050cc7030b200241046a28020021050cc4030b200728020021090cc1030b200728020021090cbe030b200241046a28020021050cbb030b200241046a28020021050cb8030b200241046a28020021050cb5030b200528020021060cb2030b200241046a28020021050caf030b200241046a28020021050cac030b200241046a28020021050ca9030b200728020021090ca6030b200241046a28020021050ca3030b200241046a28020021050ca0030b200241046a28020021050c9d030b200241046a28020021050c9a030b200241046a28020021050c97030b200241046a28020021050c94030b200241046a28020021050c91030b200241046a28020021050c8e030b200728020021080c8b030b200241046a28020021050c88030b200241046a28020021050c85030b200728020021090c82030b200241046a28020021050cff020b200241046a28020021050cfc020b200728020021090cf9020b200728020021090cf6020b200241046a28020021050cf3020b200928020021060cf0020b200728020021090ced020b200241046a28020021050cea020b200728020021090ce7020b200728020021080ce4020b200241046a28020021050ce1020b200728020021080cde020b200241046a28020021050cdb020b2006101b22050db4050b20064101101c000b2008101b22090dad050b20084101101c000b2008101b22060da9050b20084101101c000b2006101b22050da5050b20064101101c000b2008101b22090da1050b20084101101c000b2008101b22090d9a050b20084101101c000b2008101b22090d96050b20084101101c000b2006101b22050d92050b20064101101c000b2008101b22090d8e050b20084101101c000b2006101b22050d8a050b20064101101c000b2009101b22060d86050b20094101101c000b2006101b22050d82050b20064101101c000b2005101b22080dfe040b20054101101c000b2006101b22050dfa040b20064101101c000b2008101b22090df6040b20084101101c000b2009101b22060df2040b20094101101c000b2006101b22050dee040b20064101101c000b2006101b22050dea040b20064101101c000b2006101b22050de6040b20064101101c000b2006101b22080de2040b20064101101c000b2005101b22080dde040b20054101101c000b2006101b22050dda040b20064101101c000b2006101b22050dd6040b20064101101c000b2006101b22050dd2040b20064101101c000b2006101b22050dce040b20064101101c000b2006101b22050dca040b20064101101c000b2005101b22080dc6040b20054101101c000b2009101b22060dc2040b20094101101c000b2006101b22050dbe040b20064101101c000b2005101b22080dba040b20054101101c000b2006101b22050db6040b20064101101c000b2006101b22050db2040b20064101101c000b2006101b22050dae040b20064101101c000b2006101b22050daa040b20064101101c000b2006101b22050da6040b20064101101c000b2006101b22050da2040b20064101101c000b2006101b22050dee040b20064101101c000b2008101b22090d9c040b20084101101c000b2006101b22050d98040b20064101101c000b2008101b22090d94040b20084101101c000b2006101b22050d90040b20064101101c000b2006101b22050d8c040b20064101101c000b2006101b22050d88040b20064101101c000b2006101b22050d84040b20064101101c000b2006101b22050d80040b20064101101c000b2006101b22050dfc030b20064101101c000b2006101b22050df8030b20064101101c000b2006101b22050df4030b20064101101c000b2006101b22050df0030b20064101101c000b2006101b22050dec030b20064101101c000b2006101b22050de8030b20064101101c000b2006101b22050de4030b20064101101c000b2006101b22050de0030b20064101101c000b2008101b22090ddc030b20084101101c000b2008101b22090dd8030b20084101101c000b2006101b22050dd4030b20064101101c000b2006101b22050dd0030b20064101101c000b2006101b22050dcc030b20064101101c000b2008101b22090dc8030b20084101101c000b2008101b22090dc4030b20084101101c000b2006101b22050dc0030b20064101101c000b2006101b22050dbc030b20064101101c000b2006101b22050db8030b20064101101c000b2006101b22050db4030b20064101101c000b2006101b22050db0030b20064101101c000b2006101b22050dac030b20064101101c000b2006101b22050da8030b20064101101c000b2006101b22050da4030b20064101101c000b2008101b22090da0030b20084101101c000b2006101b22050d9c030b20064101101c000b2006101b22050d98030b20064101101c000b2006101b22050d94030b20064101101c000b2006101b22050d90030b20064101101c000b2006101b22050d8c030b20064101101c000b2006101b22050d88030b20064101101c000b2006101b22050d84030b20064101101c000b2009101b22060d80030b20094101101c000b2006101b22050dfc020b20064101101c000b2006101b22050df8020b20064101101c000b2006101b22050df4020b20064101101c000b2006101b22050df0020b20064101101c000b2006101b22050dec020b20064101101c000b2006101b22050de8020b20064101101c000b2006101b22050de4020b20064101101c000b2005101b22080de0020b20054101101c000b2008101b22090ddc020b20084101101c000b2006101b22050dd8020b20064101101c000b2006101b22050dd3020b20064101101c000b2006101b22050dcf020b20064101101c000b2006101b22050dcb020b20064101101c000b2006101b22050dc7020b20064101101c000b2006101b22050dc3020b20064101101c000b2006101b22050dbf020b20064101101c000b2006101b22050dbb020b20064101101c000b2006101b22050db7020b20064101101c000b2006101b22050db3020b20064101101c000b2006101b22050daf020b20064101101c000b2006101b22050dab020b20064101101c000b2006101b22050da7020b20064101101c000b2006101b22050da3020b20064101101c000b2006101b22050d9f020b20064101101c000b2006101b22050d9b020b20064101101c000b2006101b22050d97020b20064101101c000b2006101b22050d93020b20064101101c000b2006101b22050d8f020b20064101101c000b2006101b22050d8b020b20064101101c000b2006101b22050d87020b20064101101c000b2006101b22050d83020b20064101101c000b2006101b22050dff010b20064101101c000b2006101b22050dfb010b20064101101c000b2006101b22050df7010b20064101101c000b2006101b22050df3010b20064101101c000b2006101b22050def010b20064101101c000b2006101b22050deb010b20064101101c000b2006101b22050de7010b20064101101c000b2008101b22090de3010b20084101101c000b2008101b22050ddf010b20084101101c000b2009101b22060ddb010b20094101101c000b2006101b22050dd7010b20064101101c000b2006101b22050dd3010b20064101101c000b2006101b22050dcf010b20064101101c000b2006101b22050dcb010b20064101101c000b2006101b22050dc7010b20064101101c000b2006101b22050dc3010b20064101101c000b2006101b22050dbf010b20064101101c000b2006101b22050dbb010b20064101101c000b2006101b22050db7010b20064101101c000b2006101b22050db3010b20064101101c000b2006101b22050daf010b20064101101c000b2006101b22050dab010b20064101101c000b2006101b22050da7010b20064101101c000b2006101b22050da3010b20064101101c000b2006101b22050d9f010b20064101101c000b2006101b22050d9b010b20064101101c000b2006101b22050d97010b20064101101c000b2006101b22050d93010b20064101101c000b2006101b22050d8f010b20064101101c000b2008101b22090d8b010b20084101101c000b2008101b22090d87010b20084101101c000b2006101b22050d83010b20064101101c000b2006101b22050d7f0b20064101101c000b2006101b22050d7b0b20064101101c000b2009101b22060d770b20094101101c000b2006101b22050d730b20064101101c000b2006101b22050d6f0b20064101101c000b2006101b22050d6b0b20064101101c000b2008101b22090d670b20084101101c000b2006101b22050d630b20064101101c000b2006101b22050d5f0b20064101101c000b2006101b22050d5b0b20064101101c000b2006101b22050d570b20064101101c000b2006101b22050d530b20064101101c000b2006101b22050d4f0b20064101101c000b2006101b22050d4b0b20064101101c000b2006101b22050d470b20064101101c000b2005101b22080d430b20054101101c000b2006101b22050d3f0b20064101101c000b2006101b22050d3b0b20064101101c000b2008101b22090d370b20084101101c000b2006101b22050d330b20064101101c000b2006101b22050d2f0b20064101101c000b2008101b22090d2b0b20084101101c000b2008101b22090d270b20084101101c000b2006101b22050d230b20064101101c000b2001101b22060d1f0b20014101101c000b2008101b22090d1b0b20084101101c000b2006101b22050d170b20064101101c000b2008101b22090d130b20084101101c000b2005101b22080d0f0b20054101101c000b2006101b22050d0b0b20064101101c000b2005101b22080d070b20054101101c000b2006101b22050d030b20064101101c000b101d000b101d000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000cdd020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a410d3a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490dcf0220024101742209200620062009491b22094100480dcf022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cdd020b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000cd9020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a410c3a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490dcb0220024101742209200620062009491b22094100480dcb022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cd9020b0b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41333a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dca022004410174220d20092009200d491b220d4100480dca022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dca0220024101742209200620062009491b22094100480dca022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cd8020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000cd3020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413a3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dd1022004410174220d20092009200d491b220d4100480dd1022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dd10220024101742209200620062009491b22094100480dd1022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cd4020b0b200d4101101c000b20094101101c000b200241086a2001360200200241046a20063602002002410c6a28020021050b2002410c6a2201200541016a360200200620056a410e3a00002003200b200d200d200b4102746a2002101e0240024020032d0000411a470d00200241086a2106200241046a210703400240024002400240200628020020012802002202470d00200241016a22052002490dc40220024101742208200520052008491b22084100480dc4022002450d01200928020020022008101a22050d020c060b200928020021050c020b2008101b2205450d040b2006200836020020072005360200200128020021020b2001200241016a360200200520026a200441807f72200441ff0071200441077622021b3a00002002210420020d000b0240200b41ffffffff0371450d00200d10190b2000411a3a0000200341106a24000f0b20002003290300370200200041086a200341086a290300370200200b41ffffffff0371450dd102200d1019200341106a24000f0b20084101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000ccd020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412d3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dc0022004410174220d20092009200d491b220d4100480dc0022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dc00220024101742209200620062009491b22094100480dc0022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cce020b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41323a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dbe022004410174220d20092009200d491b220d4100480dbe022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dbe0220024101742209200620062009491b22094100480dbe022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000ccc020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000cc7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000cc5020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41393a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490dc3022004410174220d20092009200d491b220d4100480dc3022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490dc30220024101742209200620062009491b22094100480dc3022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cc6020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000cc1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000cbf020b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41223a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490db10220024101742209200620062009491b22094100480db1022002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cbf020b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000cbb020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000cb9020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000cb7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000cb5020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000cb3020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000cb1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000caf020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000cad020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41313a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490da0022004410174220d20092009200d491b220d4100480da0022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490da00220024101742209200620062009491b22094100480da0022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cae020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000ca9020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000ca7020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000ca5020b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41c3003a000002400240024002400240200241086a2802002206200928020022046b41044f0d00200441046a22092004490da10220064101742204200920092004491b22044100480da1022006450d01200528020020062004101a2205450d020c030b200528020021050c030b2004101b22050d010b20044101101c000b200241086a2004360200200241046a20053602002002410c6a28020021040b2002410c6a200441046a360200200520046a20083600000ca3020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000ca1020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c9f020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c9d020b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41373a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d9b022004410174220d20092009200d491b220d4100480d9b022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d9b0220024101742209200620062009491b22094100480d9b022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c9e020b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412e3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d8e022004410174220d20092009200d491b220d4100480d8e022004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d8e0220024101742209200620062009491b22094100480d8e022002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c9c020b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c97020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c95020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c93020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c91020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c8f020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c8d020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c8b020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c89020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c87020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c85020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c83020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c81020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000cff010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000cfd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000cfb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000cf9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000cf7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000cf5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000cf3010b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a413f3a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490def0120044101742209200620062009491b22064100480def012004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a20083a00000cf1010b200241086a2008360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a0000200320062002101f20032d0000411a460def0120002003290300370200200041086a200341086a29030037020020012d00004109470df0010c3a0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412f3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490de2012004410174220d20092009200d491b220d4100480de2012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490de20120024101742209200620062009491b22094100480de2012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cf0010b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000ceb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000ce9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000ce7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000ce5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000ce3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000ce1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000cdf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000cdd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000cdb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000cd9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000cd7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000cd5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000cd3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000cd1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000ccf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000ccd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000ccb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000cc9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000cc7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000cc5010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000cc3010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000cc1010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000cbf010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000cbd010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000cbb010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000cb9010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000cb7010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200a2002102020032d0000411a460db50120002003290300370200200041086a200341086a29030037020020012d00004109470db6010b200141086a28020041ffffffff0371450db501200141046a2802001019200341106a24000f0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000cb2010b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41293a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490da5012004410174220d20092009200d491b220d4100480da5012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490da50120024101742209200620062009491b22094100480da5012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000cb3010b0b200d4101101c000b20094101101c000b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41233a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490da20120024101742209200620062009491b22094100480da2012002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000cb0010b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000cac010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000caa010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000ca8010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000ca6010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000ca4010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000ca2010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000ca0010b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41c0003a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d9c0120044101742209200620062009491b22064100480d9c012004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a20083a00000c9e010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c9c010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c9a010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c98010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c96010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c94010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c92010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c90010b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413e3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d8e012004410174220d20092009200d491b220d4100480d8e012004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d8e0120024101742209200620062009491b22094100480d8e012002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c91010b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c8c010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c8a010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c88010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c86010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c84010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c82010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c80010b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c7e0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413d3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d7c2004410174220d20092009200d491b220d4100480d7c2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d7c20024101742209200620062009491b22094100480d7c2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c7f0b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41383a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d7a2004410174220d20092009200d491b220d4100480d7a2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d7a20024101742209200620062009491b22094100480d7a2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c7d0b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c780b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c760b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c740b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412b3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d672004410174220d20092009200d491b220d4100480d672004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d6720024101742209200620062009491b22094100480d672002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c750b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41343a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d652004410174220d20092009200d491b220d4100480d652004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d6520024101742209200620062009491b22094100480d652002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c730b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c6e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c6c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c6a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c680b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c660b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c640b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c620b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c600b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c5e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c5c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c5a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c580b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c560b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41303a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d492004410174220d20092009200d491b220d4100480d492004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d4920024101742209200620062009491b22094100480d492002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c570b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c520b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41283a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d452004410174220d20092009200d491b220d4100480d452004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d4520024101742209200620062009491b22094100480d452002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c530b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000c4e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c4c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c4a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c480b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c460b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c440b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41243a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d3620024101742209200620062009491b22094100480d362002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c440b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c400b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41033a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d3120044101742209200620062009491b22064100480d312004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c3e0b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41213a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d3020024101742209200620062009491b22094100480d302002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c3e0b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c3a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c380b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c360b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c340b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c320b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41203a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d2420024101742209200620062009491b22094100480d242002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c320b0b20094101101c000b200241086a2006360200200241046a20083602002002410c6a28020021040b2002410c6a2206200441016a360200200820046a41113a0000200241086a2109200241046a210d02400240024003400240024002400240200928020020062802002204470d00200441016a22082004490d2420044101742207200820082007491b22074100480d242004450d01200b28020020042007101a22080d020c050b200b28020021080c020b2007101b2208450d030b20092007360200200d2008360200200628020021040b2006200441016a360200200820046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b024002400240200241086a2802002002410c6a2802002204470d00200441016a22052004490d2220044101742206200520052006491b22064100480d222004450d01200b28020020042006101a2205450d020c040b200b28020021050c040b2006101b22050d020b20064101101c000b20074101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a200c3a00000c2e0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c2c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c2a0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c280b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41043a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d1920044101742209200620062009491b22064100480d192004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c260b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41363a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d242004410174220d20092009200d491b220d4100480d242004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d2420024101742209200620062009491b22094100480d242002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c270b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c220b200241086a2005360200200241046a20083602002002410c6a28020021060b2002410c6a2205200641016a360200200820066a41103a0000200241086a2108200241046a210b024003400240024002400240200828020020052802002202470d00200241016a22062002490d1420024101742209200620062009491b22094100480d142002450d01200728020020022009101a22060d020c050b200728020021060c020b2009101b2206450d030b20082009360200200b2006360200200528020021020b2005200241016a360200200620026a200441807f72200441ff0071200441077622021b3a00002002210420020d000c220b0b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c1e0b200241086a2009360200200241046a20063602002002410c6a28020021040b2002410c6a2209200441016a360200200620046a41023a000002400240024002400240200241086a28020020092802002204470d00200441016a22062004490d0f20044101742209200620062009491b22064100480d0f2004450d01200528020020042006101a2205450d020c030b200528020021050c030b2006101b22050d010b20064101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2008410374412073ad42f8018388a7413f7141c000723a00000c1c0b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c1a0b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a41353a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d182004410174220d20092009200d491b220d4100480d182004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d1820024101742209200620062009491b22094100480d182002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c1b0b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c160b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412c3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d092004410174220d20092009200d491b220d4100480d092004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0920024101742209200620062009491b22094100480d092002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c170b0b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a412a3a0000200241086a210b200241046a210c03400240024002400240200b28020020082802002204470d00200441016a22092004490d052004410174220d20092009200d491b220d4100480d052004450d0120072802002004200d101a22090d020c060b200728020021090c020b200d101b2209450d040b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0520024101742209200620062009491b22094100480d052002450d01200728020020022009101a22060d020c070b200728020021060c020b2009101b2206450d050b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c130b0b101d000b200d4101101c000b20094101101c000b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413b3a0000200241086a210b200241046a210c0240024003400240024002400240200b28020020082802002204470d00200441016a22092004490d0d2004410174220d20092009200d491b220d4100480d0d2004450d0120072802002004200d101a22090d020c050b200728020021090c020b200d101b2209450d030b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22062002490d0d20024101742209200620062009491b22094100480d0d2002450d01200728020020022009101a22060d020c060b200728020021060c020b2009101b2206450d040b20082009360200200b2006360200200428020021020b2004200241016a360200200620026a200541807f72200541ff0071200541077622021b3a00002002210520020d000c100b0b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c0b0b200241086a2008360200200241046a20063602002002410c6a28020021040b2002410c6a2208200441016a360200200620046a41c4003a000002400240024002400240200241086a2802002206200828020022046b41084f0d00200441086a22082004490d0720064101742204200820082004491b22044100480d072006450d01200528020020062004101a2205450d020c030b200528020021050c030b2004101b22050d010b20044101101c000b200241086a2004360200200241046a20053602002002410c6a28020021040b2002410c6a200441086a360200200520046a200a3700000c090b200241086a2008360200200241046a20093602002002410c6a28020021040b2002410c6a2208200441016a360200200920046a413c3a0000200241086a210b200241046a210c03400240024002400240200b28020020082802002204470d00200441016a22092004490d052004410174220d20092009200d491b220d4100480d052004450d0120072802002004200d101a22090d020c060b200728020021090c020b200d101b2209450d040b200b200d360200200c2009360200200828020021040b2008200441016a360200200920046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2104200241086a2108200241046a210b03400240024002400240200828020020042802002202470d00200241016a22052002490d0520024101742209200520052009491b22094100480d052002450d01200728020020022009101a22050d020c070b200728020021050c020b2009101b2205450d050b20082009360200200b2005360200200428020021020b2004200241016a360200200520026a200641807f72200641ff0071200641077622021b3a00002002210620020d000c080b0b101d000b200d4101101c000b20094101101c000b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000c020b200241086a2006360200200241046a20053602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000b2000411a3a000020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010190b200341106a24000b0500101d000b850603027f017e087f230041c0006b220424002004200136020c2004200041d889c20020011b3602082004200441086a102d02400240024002400240024002402004280200450d000240024002400240024020042802042205ad2206421c88a70d002006420486a72201417f4c0d00024002402001450d002001101b2207450d032005450d010c040b4108210720050d030b410021014100210b2007450d050c030b102b000b20014108101c000b200441206a4104722108410021094100210a410021002005210b0340200441206a200441086a102e200441306a41086a220c200841086a280200360200200420082902003703302004280220220d4104460d02200041016a2101200441106a41086a220e200c2802003602002004200429033037031002402000200b470d002009200120012009491b220bad4204862206422088a70d052006a7220c4100480d0502402000450d002007200a200c101a22070d010c070b200c101b2207450d060b2007200a6a2200200d3602002000410c6a200e280200360200200041046a2004290310370200200941026a2109200a41106a210a2001210020012005490d000b2007450d020b200441206a20022007200120031101002004410036023820044201370330200428022021004101101b21010240024020004105470d002001450d06200141013a0000200442818080801037023420042001360230420121060c010b2001450d06200141003a0000200442818080801037023420042001360230200141014102101a2101024020004104470d002001450d08200141003a0001200442828080802037023420042001360230420221060c010b2001450d08200141013a0001200442828080802037023420042001360230200441206a200441306a102f200441386a3502002106200428023021010b2001ad42208620068421060240200b450d00200710190b200441c0006a240020060f0b200b450d00200710190b419486c00041f0001030000b101d000b200c4108101c000b41014101101c000b41014101101c000b41024101101c000b41024101101c000bcb0301077f230041106b22022400200241003a0003200241036a200128020022032001280204220441004722051095031a0240024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002402004450d000240024020022d000322034103712204450d00024020044101460d0020044102470d0241002104200241003a000e200241003b010c2002410c6a200520064103200641034922071b22081095031a200141046a200620086b3602002001200520086a36020020070d0520022f010c20022d000e411074724108742003724102762101410121040c050b200241003a000b2002410b6a2005200641004722041095031a20062004490d06200141046a200620046b3602002001200520046a3602002006450d0220022d000b4108742003724102762101410121040c040b20034102762101410121040c030b200341044f0d004100210420024100360204200241046a200520064104200641044922081b22031095031a200141046a200620036b3602002001200520036a36020020080d0120022802042101410121040c020b410021040b0b2000200136020420002004360200200241106a24000f0b200520041027000b200420061027000bcb0401057f230041106b22022400200241003a0008200241086a200128020022032001280204220441004722051095031a024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002400240024002400240024002402004450d0020022d0008417f6a220441034b0d04024020040e0400030204000b20024100360208200241086a20052006410420064104491b22041095031a200141046a200620046b3602002001200520046a360200200641034d0d052000200228020836020420004100360200200241106a24000f0b20004104360200200241106a24000f0b20024100360208200241086a20052006410420064104491b22041095031a200141046a200620046b3602002001200520046a360200200641034d0d042000200228020836020420004102360200200241106a24000f0b20024200370308200241086a20052006410820064108491b22041095031a200141046a200620046b3602002001200520046a360200200641074d0d04200041086a200229030837030020004101360200200241106a24000f0b20024200370308200241086a20052006410820064108491b22041095031a200141046a200620046b3602002001200520046a360200200641074d0d04200041086a200229030837030020004103360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b20004104360200200241106a24000f0b200520041027000ba20b02037f017e0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200028020022024101460d00024020024102460d0020024103470d02200141046a280200200141086a2802002202470d05200241016a22032002490d1720024101742204200320032004491b22044100480d172002450d0b200128020020022004101a2203450d0c0c150b200141046a280200200141086a2802002202470d02200241016a22032002490d1620024101742204200320032004491b22044100480d162002450d06200128020020022004101a2203450d070c120b200141046a280200200141086a2802002202470d02200241016a22032002490d1520024101742204200320032004491b22044100480d152002450d07200128020020022004101a2203450d080c0f0b200141046a280200200141086a2802002202470d03200241016a22032002490d1420024101742204200320032004491b22044100480d142002450d0a200128020020022004101a2203450d0b0c0c0b200128020021030c100b200128020021030c0d0b200128020021030c100b200128020021030c090b2004101b22030d0b0b20044101101c000b2004101b22030d070b20044101101c000b2004101b22030d090b20044101101c000b2004101b22030d010b20044101101c000b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a0000200041046a280200210302400240024002400240200141046a2802002202200428020022006b41044f0d00200041046a22042000490d0b20024101742200200420042000491b22004100480d0b2002450d01200128020020022000101a2202450d020c030b200128020021020c030b2000101b22020d010b20004101101c000b20012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a0000200041086a290300210502400240024002400240200141046a2802002202200428020022006b41084f0d00200041086a22032000490d0920024101742200200320032000491b22004100480d092002450d01200128020020022000101a2202450d020c030b200128020021020c030b2000101b22020d010b20004101101c000b20012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a0000200041046a280200210302400240024002400240200141046a2802002202200428020022006b41044f0d00200041046a22042000490d0720024101742200200420042000491b22004100480d072002450d01200128020020022000101a2202450d020c030b200128020021020c030b2000101b22020d010b20004101101c000b20012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a0000200041086a2903002105024002400240200141046a2802002202200428020022006b41084f0d00200041086a22032000490d0320024101742200200320032000491b22004100480d032002450d01200128020020022000101a2202450d020c040b200128020021020c040b2000101b22020d020b20004101101c000b101d000b20012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000b5f01017f230041306b220224002002200136020c20022000360208200241246a41013602002002410336022c20024201370214200241f8e7c3003602102002200241086a3602282002200241286a360220200241106a4180e8c30010f201000bca07010d7f230041c0086b22022400410021032001410c6a2104200141086a210541002106024002400240024002400240024002400240024002400240024003402003411f4b0d012005280200220720042802002208460d02200841016a21092008417f460d0720072009490d082001280200220a20086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b024020034120490d00410d210320086741686a41ff01714104490d030b2006450d03200241086a41004180081094031a2001410c6a210b200141086a210c4101210d4100210e41002108410021040340200720096b200620046b22034180082003418008491b2203490d05200920036a22052009490d0920072005490d0a200241086a200a20096a20031095031a200b20053602000240024002400240200e20086b20034f0d00200820036a22052008490d0f200e4101742209200520052009491b22094100480d0f200e450d01200d200e2009101a220d0d020c100b200320086a21050c020b2009101b220d450d0e0b2009210e0b200d20086a200241086a20031095031a02402006200320046a22044d0d00200b2802002109200c28020021072001280200210a200521080c010b0b200241086a200d2005103220022802084101470d050240200e450d00200d10190b200041083a000420004101360200200241c0086a24000f0b410f21030c010b200241013a0098082002411c6a41013602002002410136028c082002420137020c200241c4d6c300360208200220024198086a36028808200220024188086a360218200241a8086a200241086a1024410521030b2000200336020420004101360200200041086a20022902a808370200200041106a200241a8086a41086a2802003602000c090b2000428080808010370200200041086a4200370200200241c0086a24000f0b200241013a009708200241bc086a41013602002002410136028c08200242013702ac08200241c4d6c3003602a808200220024197086a36028808200220024188086a3602b80820024198086a200241a8086a1024200241b3086a200241a0086a28020036000020022002290398083700ab08200041053a000420004101360200200020022900a8083700052000410c6a200241af086a290000370000200e450d07200d1019200241c0086a24000f0b2000200d3602042000410c6a2005360200200041086a200e36020020004100360200200241c0086a24000f0b417f20091027000b200920071028000b200920051027000b200520071028000b101d000b20094101101c000b200241c0086a24000bbd0602057f027e0240024002402002450d00200241796a4100200241074b1b2103410021040340024002400240024002400240024002400240024002400240024002400240200120046a22052d0000220641187441187522074100480d002005410371450d01200441016a22042002490d0f0c100b4280808080102108200641d687c2006a2d000022054104460d0120054103460d0220054102470d08200441016a220620024f0d094280808080802021094280808080102108200120066a2d000041c00171418001460d0d0c110b0240200420034f0d000340200120046a220641046a280200200628020072418081828478710d01200441086a22042003490d000b0b0240200420024f0d000340200120046a2c00004100480d01200441016a22042002490d000b0b20042002490d0d0c0e0b42002109200441016a220520024f0d08200120056a2d00002105200641f001460d01200641f401470d022005411874411875417f4a0d06200541ff0171419001490d030c060b42002109200441016a220520024f0d07200120056a2d00002105200641e001460d03200641ed01470d042005411874411875417f4a0d05200541ff017141a001490d090c050b200541f0006a41ff01714130490d010c040b200541ff017141bf014b0d032007410f6a41ff017141024b0d03200541187441187541004e0d030b200441026a220620024f0d04200120066a2d000041c00171418001470d0a42002108200441036a220620024f0d0b200120066a2d000041c00171418001460d070c050b200541e0017141a001470d010c050b02402007411f6a41ff0171410c4f0d002005411874411875417f4a0d01200541ff017141c001490d050c010b200541ff017141bf014b0d00200741fe017141ee01470d0020054118744118754100480d040b4280808080802021090c080b420021090b420021080c060b428080808080e000210942808080801021080c050b42002108200441026a220620024f0d04200120066a2d000041c00171418001470d030b200641016a22042002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c000210942808080801021080b200020092008842004ad84370204200041013602000ba50201027f230041306b2202240020024106360214200241e481c00036021020022001200241106a10340240024002400240200228020022012002280208220341d889c200410041001000417f460d00200241286a4200370300200241206a4200370300200241186a42003703002002420037031020012003200241106a4120410010002203417f460d012003411f4d0d0120002002290310370000200041186a200241106a41186a290300370000200041106a200241106a41106a290300370000200041086a200241106a41086a2903003700002002280204450d030c020b20004200370000200041186a4200370000200041106a4200370000200041086a420037000020022802040d010c020b41fcf9c00041331030000b200110190b200241306a24000bb30101037f024002400240024020022802042203417f4c0d00200228020021044101210202402003450d002003101b2202450d030b200220042003109503210520034101742204200341046a220220022004491b22044100480d01024002402003450d00200520032004101a2205450d010c050b2004101b22050d040b20044101101c000b102b000b101d000b20034101101c000b200020023602082000200436020420002005360200200520036a20013600000bef1004047f017e087f037e230041a0046b22022400200241186a2001102d0240024002400240024002400240024002402002280218450d00200241003a00880220024188026a200128020022032001280204220441004722051095031a20042005490d04200141046a200420056b3602002001200320056a3602002004450d0120022d008802220441ff00714101470d022004411874411875417f4c0d03420221060c080b20004203370370200241a0046a24000f0b20004203370370200241a0046a24000f0b20004203370370200241a0046a24000f0b200241b0016a2001103602400240024020022d00b0014102460d00200241b8036a41206a200241b0016a41206a280200360200200241b8036a41186a200241b0016a41186a290300370300200241b8036a41106a200241b0016a41106a290300370300200241b8036a41086a200241b0016a41086a290300370300200220022903b0013703b80320024188026a41386a2207420037030020024188026a41306a2208420037030020024188026a41286a2209420037030020024188026a41206a220a420037030020024188026a41186a220b420037030020024188026a41106a220c420037030020024188026a41086a220d4200370300200242003703880220024188026a20012802002203200141046a220e280200220441c000200441c000491b22051095031a200e200420056b3602002001200320056a3602002004413f4d0d00200241e0036a41386a2007290300370300200241e0036a41306a2008290300370300200241e0036a41286a2009290300370300200241e0036a41206a200a290300370300200241e0036a41186a200b290300370300200241e0036a41106a200c290300370300200241e0036a41086a200d29030037030020022002290388023703e003200241086a200110372002280208450d002002290310210f200141046a220e2802002104200241003a00880220024188026a20012802002207200441004722051095031a20042005490d04200e200420056b22033602002001200720056a22053602002004450d002002310088022210500d01200241003a00880220024188026a2005200341004722041095031a20032004490d05200141046a200320046b3602002001200520046a3602002003450d0042022010420f838622114204540d00420121062002310088024208862010844204882011420c882210420120104201561b7e22102011540d020b420221060c050b420021060b20024188016a41206a200241b8036a41206a28020036020020024188016a41186a200241b8036a41186a29030037030020024188016a41106a200241b8036a41106a29030037030020024188016a41086a200241b8036a41086a290300370300200241e0026a41086a200241e0036a41086a290300370300200241e0026a41106a200241e0036a41106a290300370300200241e0026a41186a200241e0036a41186a290300370300200241e0026a41206a200241e0036a41206a290300370300200241e0026a41286a200241e0036a41286a290300370300200241e0026a41306a200241e0036a41306a290300370300200241e0026a41386a200241e0036a41386a290300370300200220022903b80337038801200220022903e0033703e0020c030b200520041027000b200520041027000b200420031027000b200241b0016a41206a220420024188016a41206a280200360200200241b0016a41186a220520024188016a41186a290300370300200241b0016a41106a220320024188016a41106a290300370300200241b0016a41086a220e20024188016a41086a29030037030020024188026a41086a2207200241e0026a41086a29030037030020024188026a41106a2208200241e0026a41106a29030037030020024188026a41186a2209200241e0026a41186a29030037030020024188026a41206a220a200241e0026a41206a29030037030020024188026a41286a220b200241e0026a41286a29030037030020024188026a41306a220c200241e0026a41306a29030037030020024188026a41386a220d200241e0026a41386a29030037030020022002290388013703b001200220022903e00237038802024020064202520d0020004203370370200241a0046a24000f0b200241e0006a41206a2004280200360200200241e0006a41186a2005290300370300200241e0006a41106a2003290300370300200241e0006a41086a200e290300370300200241206a41086a2007290300370300200241206a41106a2008290300370300200241206a41186a2009290300370300200241206a41206a200a290300370300200241206a41286a200b290300370300200241206a41306a200c290300370300200241206a41386a200d290300370300200220022903b00137036020022002290388023703200b20024188026a2001103820022d0088022101200241e0026a20024188026a41017241d7001095031a02402001410e470d0020004203370370200241a0046a24000f0b200241b0016a200241e0026a41d7001095031a2000200f37030020002002290360370308200041106a200241e0006a41086a290300370300200041186a200241e0006a41106a290300370300200041206a200241e0006a41186a290300370300200041286a200241e0006a41206a2802003602002000200229032037022c200041346a200241206a41086a2903003702002000413c6a200241206a41106a290300370200200041c4006a200241206a41186a290300370200200041cc006a200241206a41206a290300370200200041d4006a200241206a41286a290300370200200041dc006a200241d0006a290300370200200041e4006a200241d8006a29030037020020004188016a20013a000020004180016a2010370300200020113703782000200637037020004189016a200241b0016a41d7001095031a200241a0046a24000b8f0801067f230041f0006b22022400200241003a0050200241d0006a200128020022032001280204220441004722051095031a0240024020042005490d00200141046a200420056b22063602002001200320056a2205360200024002402004450d0020022d0050220441f0014f0d01410121010c030b200041023a0000200241f0006a24000f0b02400240024002400240200441847e6a220441034b0d00024002400240024020040e0400010203000b200241003b0150200241d0006a20052006410220064102491b22041095031a200141046a200620046b3602002001200520046a36020041012101200641014d0d0441ef01210420022f015041ef014b0d09200041023a0000200241f0006a24000f0b20024100360250200241d0006a20052006410420064104491b22041095031a200141046a200620046b3602002001200520046a360200200641034d0d0441ffff03210441012101200228025041ffff034b0d08200041023a0000200241f0006a24000f0b200041023a0000200141046a20062006410420064104491b22006b3602002001200520006a360200200241f0006a24000f0b41002103200241d0006a2006412020064120491b22046a41004100412020046b2004411f4b1b1094031a200241d0006a200520041095031a200141046a200620046b3602002001200520046a3602002006411f4d0d032002412c6a41026a200241d0006a41026a2d00003a0000200241186a200241df006a290000370300200241206a200241e7006a290000370300200241286a200241d0006a411f6a2d00003a0000200220022f00503b012c2002200229005737031020022800532104410121030c040b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b0b200241cc006a41026a22012002412c6a41026a2d00003a0000200241306a41086a2205200241106a41086a290300370300200241306a41106a2206200241106a41106a290300370300200241306a41186a2207200241106a41186a2d00003a0000200220022f012c3b014c2002200229031037033002402003450d002002410c6a41026a20012d00003a0000200241d0006a41086a2005290300370300200241d0006a41106a2006290300370300200241d0006a41186a20072d00003a0000200220022f014c3b010c20022002290330370350410021010c020b200041023a0000200241f0006a24000f0b200520041027000b200020022f010c3b0001200020013a0000200041046a2004360200200041086a2002290350370200200041036a2002410e6a2d00003a0000200041106a200241d0006a41086a290300370200200041186a200241d0006a41106a290300370200200041206a200241d0006a41186a280200360200200241f0006a24000bc00503057f027e037f230041106b22022400200241003a0008200241086a200128020022032001280204220441004722051095031a02400240024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002402004450d000240024020022d000822044103712203450d002004ad2107024020034101460d0020034102470d02200241003a0006200241003b0104200241046a200520064103200641034922031b22041095031a200141046a200620046b3602002001200520046a36020020030d0320023301042002310006421086844208862007844202882107420121080c050b200241003a0008200241086a2005200641004722041095031a20062004490d07200141046a200620046b3602002001200520046a3602002006450d0220023100084208862007844202882107420121080c040b2004410276ad2107420121080c030b0240024020044102762204450d0020044104470d014200210820024200370308200241086a200520064108200641084922031b22041095031a200141046a200620046b3602002001200520046a36020020030d0320022903082107420121080c040b20024100360208200241086a200520064104200641044922031b22041095031a200141046a200620046b3602002001200520046a36020020030d0120023502082107420121080c030b200441046a220941084b0d0042002107200141046a210a410021030340200241003a0008200241086a2005200641004722041095031a20062004490d05200a200620046b220b3602002001200520046a22053602002006450d0120023100082003410374413871ad86200784210742012108200b2106200341016a22042103200441ff01712009490d000c030b0b420021080b0b2000200737030820002008370300200241106a24000f0b200520041027000b200420061027000b200420061027000ba26705057f057e077f037e067f23004190086b22022400200241003a00b807200241b8076a200128020022032001280204220441004722051095031a0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020042005490d00200141046a200420056b22063602002001200320056a22053602000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004450d0020022d00b8072204410d4b0d0e024020040e0e00090607030a0c080e050d02040b000b200241003a00b807200241b8076a2005200641004722041095031a20062004490d8001200141046a200620046b3602002001200520046a3602002006450dc40120022d00b807450d100cc4010b2000410e3a000020024190086a24000f0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450d2420022d00b807220441044b0d24024020040e05002220211f000b20024188046a200110b402200229038804a7450d2420024198046a29030021072002290390042108200241b8076a200110364102210120022d00b80722044102460d2420022902bc072109200241d4076a290200210a200241cc076a290200210b20022f00b907210520022d00bb0721062002200241c4076a2902003703e806200220093703e0062002200b3703f006200520064110747221050c230b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d1920022d00b8072205450d1720054101460d1620054102470d19200241003a00b807200241b8076a2004200341004722051095031a20032005490d8f0141042106200141046a200320056b3602002001200420056a3602002003450d1920022d00b80721010c180b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22053602002006450d0b4106210420022d00b807220641034b0dbb01024020060e04001c1a1b000b200241003602b807200241b8076a20052003410420034104491b22061095031a200141046a220c200320066b220d3602002001200520066a2205360200200341034d0dbb0120022802b807210e200242003703b807200241b8076a2005200d4108200d4108491b22061095031a200c200d20066b22033602002001200520066a2205360200200d41074d0dbb0120022903b8072108200242003703b807200241b8076a20052003410820034108491b22061095031a200141046a220c200320066b220d3602002001200520066a2205360200200341074d0dbb0120022903b8072107200242003703b807200241b8076a2005200d4108200d4108491b22061095031a200c200d20066b22033602002001200520066a2205360200200d41074d0dbb0120022903b807210a200242003703b807200241b8076a20052003410820034108491b22061095031a200141046a220c200320066b220d3602002001200520066a2205360200200341074d0dbb0120022802bc07210620022802b8072103200242003703b807200241b8076a2005200d4108200d4108491b220f1095031a200c200d200f6b221036020020012005200f6a2205360200200d41074d0dbb0120022802bc07211120022802b8072112200242003703b807200241b8076a20052010410820104108491b220d1095031a200141046a220f2010200d6b220c36020020012005200d6a2205360200201041074d0dbb0120022903b8072109200241003602b807200241b8076a2005200c4104200c4104491b220d1095031a200f200c200d6b221036020020012005200d6a2205360200200c41034d0dbb0120022802b807210c200241003602b807200241b8076a20052010410420104104491b220d1095031a200141046a2010200d6b36020020012005200d6a360200201041034d0dbb01200220022802b8073602f8062002200c3602f4062002200e3602f006200220093703e806200220113602e406200220123602e006410221040cbc010b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d0e20022d00b8072205450d0d20054101470d0e200241b8076a200341202003412049220d1b22056a41004100412020056b2005411f4b1b1094031a200241b8076a200420051095031a41042106200141046a200320056b3602002001200420056a360200200d0d54200220022f00b9073b01840620022d00b807210520022800bb07210420022900c707210720022d00d707210320022900bf07210820022900cf07210a200220022f0184063b018206200241f8036a2001102d20022802f803450d5420022802fc03210d200141046a220e2802002106200241003a00b807200241b8076a2001280200220f2006410047220c1095031a2006200c490d9601200e2006200c6b3602002001200f200c6a3602002006450d53200a422088a7210c2008422088a7210e200aa7210f2008a7210120022d00b8072110200220022f0182063b018006410321060c550b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002000410e3a000020024190086a24000f0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450d0f20022d00b8072204450d0d20044101470d0f200241b8076a2001103620022d00b80722044102460d0f20022d00bb07210520022f00b9072106200241c4076a2902002109200241d4076a2902002107200241cc076a290200210820022902bc07210a200241f0006a200110b4022002290370a7450d0f200241f0006a41106a290300210b20022903782113200241d8006a200110b4022002290358a7450d0f20062005411074722101200241e8006a290300211420022903602115200942808080807083200942ffffffff0f83842109410321050c0e0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450daa0120022d00b807220441084b0daa01024020040e090038353634393b373c000b200241d8026a2001102d20022802d802450daa0120022802dc022210417f4c0d772010450d612010101b2203450da40142002107200141046a210e4100210d410021052010210c0340200e2802002104200241003a00b807200241b8076a2001280200220f200441004722061095031a20042006490d8801200e200420066b3602002001200f20066a3602002004450d64200541016a210420022d00b807210602402005200c470d00200d20042004200d491b220c4100480d880102402005450d0020032005200c101a22030d010c8b010b200c101b2203450d8a010b200320056a20063a000020074280808080107c2107200d41026a210d2004210520042010490d000c630b0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d6e20022d00b807220641054b0d6e4103210d024020060e0600bb01282a272d000b200241106a2001102d2002280210450d6e20022802142204417f4c0d762004450d57200410df012205450d9b0120052001280200200141046a22032802002206200420062004491b22061095031a2003280200220d2006490d9c012003200d20066b3602002001200128020020066a36020020062004470d580cb9010b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22163602002006450d6820022d00b8072204410a4b0d684102210d024020040e0b67004243404647444a4149670b20024198016a2001102d200228029801450d68200228029c01220541087621124103210d0c440b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450d0d20022d00b8072204450d0c20044101470d0d200241b8076a2001103620022d00b80722014102460d0d200241c4076a290200210720022902bc07210820022f00b90720022d00bb07411074722104200241d4076a290200210a200241cc076a2902002109410321050c1e0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450d3c20022d00b807220441054b0d3c024020040e06002b2829262c000b200241b8076a2001103820022d00b8072105200241e0066a200241b8076a41017241d7001095031a2005410e460d3c20024188066a200241e0066a41d7001095031a41d800101b2204450d9501200420053a0000200441016a20024188066a41d7001095031a20024188026a200110b402200229038802a7450d3b20024198026a29030021082002290390022107410221060c2c0b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b3602002001200520046a3602002006450db40120022d00b807450d040cb4010b200241003a00b807200241b8076a2005200641004722041095031a20062004490d7f200141046a200620046b22033602002001200520046a22043602002006450d4720022d00b807220541044b0d47024020050e0500211d1e1a000b200241b8076a2001103820022d00b8072101200241e0066a200241b8076a41017241d7001095031a2001410e460d4720024188066a200241e0066a41d7001095031a41d800101b2204450d9001200420013a0000200441016a20024188066a41d7001095031a410221050c1f0b2000410e3a000020024190086a24000f0b410621040caf010b2002200110372002290300a7450db30120022903082107200041003a0000200041106a2007370300200041086a420237030020024190086a24000f0b20024180046a2001102d200228028004450daf012002280284042204417f4c0d6d2004450d33200410df012206450d870120062001280200200141046a22032802002205200420052004491b22051095031a2003280200220d2005490d88012003200d20056b3602002001200128020020056a36020020052004470d340cac010b200241f0036a2001102d20022802f003450d0020022802f4032104200241b8076a2001103820022d00b8072105200241e0066a200241b8076a41017241d7001095031a2005410e470d270b200220022f0180063b01b8070ca9010b200241b8076a200110364102210520022d00b80722044102460d0120022d00bb07210620022f00b9072103200241c4076a2902002109200241d4076a2902002107200241cc076a290200210820022902bc07210a200241c0006a200110b4022002280240450d0120032006411074722101200241c0006a41106a290300210b200229034821130b200041033a00002000410f6a20014110763a00002000410d6a20013b0000200041c8006a2014370000200041c0006a2015370000200041386a200b370000200041306a2013370000200041186a2009370000200041106a200a370000200041286a2007370000200041206a20083700002000410c6a20043a0000200041086a200536000020024190086a24000f0b2000410e3a000020024190086a24000f0b200241b8076a2001103820022d00b8072104200241e0066a200241b8076a41017241d7001095031a2004410e470d100b2000410e3a000020024190086a24000f0b20024188016a20011037200229038801a7450d022002290390012207422088a7210d2007a7210c410321060c010b200241b8076a20034120200341204922061b22056a41004100412020056b2005411f4b1b1094031a200241b8076a200420051095031a200141046a200320056b3602002001200420056a36020020060d01200220022f00b9073b01860620022d00b807210120022800bb07210e20022900c707210720022d00d707210520022900cf07210820022900bf07210a200220022f01860622043b018406200220043b01e006200a422088a7210d2008422088a72104200aa7210c2008a72103410221060b200220022f01e006220f3b01b8072002200f3b018806200041096a20013a0000200041086a20063a0000200041043a0000200041286a20053a0000200041246a2004360000200041206a2003360000200041186a2007370000200041146a200d360000200041106a200c3600002000410c6a200e3600002000410a6a20022f0188063b000020024190086a24000f0b200220022f01e0063b01b8072000410e3a000020024190086a24000f0b200241b8076a2001103620022d00b80722054102460da10120022d00bb07210320022f00b907210d200241c4076a2902002107200241d4076a290200210b200241cc076a290200210a20022902bc072108200241b0056a200110b40220022903b005a7450d5d200241b0056a41106a290300211320022903b8052114200241a0056a2001103720022903a005a7450d5d20022903a805210920024198056a2001102d200228029805450d5d200228029c052206417f4c0d612006450d5b200610df01220e450d8f01200e2001280200200141046a220f280200220c2006200c2006491b220c1095031a200f2802002210200c490d9001200f2010200c6b36020020012001280200200c6a360200200c2006470d5c0c9e010b200241e0056a200110b40220022903e005a7450da001200241f0056a290300210920022903e805210b200241d0056a2001103720022903d005a7450da00120022903d8052113200241d0076a4200370300200241c8076a4200370300200241c0076a4200370300200242003703b807200241b8076a20012802002206200141046a2203280200220441202004412049220d1b22051095031a2003200420056b3602002001200620056a360200200d0d38200220022f00b9073b01840620022d00b807210d20022800bb07210520022900bf07210820022900c707210720022900cf07210a20022d00d7072103200220022f0184063b018206200241c8056a2001102d4106210420022802c805450d940120022802cc05220c417f4c0d60200c450d5d200c10df012206450d900120062001280200200141046a220f280200220e200c200e200c491b220e1095031a200f2802002210200e490d9101200f2010200e6b36020020012001280200200e6a360200200e200c470d5e0c9c010b20024188056a20011037200229038805a7450d9f01200229039005210720024180056a2001102d200228028005450d9f012002280284052206417f4c0d5f2006450d47200610df012205450d8a0120052001280200200141046a220d2802002203200620032006491b22031095031a200d280200220c2003490d8b01200d200c20036b3602002001200128020020036a36020020032006470d480c9a010b200241f8046a2001102d20022802f804450d0520022802fc0422044108762105410621010c030b200241e8046a2001102d20022802e804450d0420022802ec042104200241d0046a200110b40220022903d004a7450d04200241e0046a290300210720022903d8042108200241c0046a2001103720022903c004a7450d0420022903c804210a200241b8046a2001102d20022802b804450d0420022802bc042101200241f0066a2007370300200220083703e806200220013602e00620044108762105410421010c030b200241f0046a2001102d20022802f004450d0320022802f40422044108762105410521010c010b200241a0046a200110b40220022903a004a7450d02200241b0046a2903002107200220022903a8043703e006200220073703e806410321010b0b200241b8076a41106a200241e0066a41106a2903002209370300200241b8076a41086a200241e0066a41086a290300220b37030020024188066a41086a2206200b37030020024188066a41106a22032009370300200220022903e006220937038806200220093703b807200041386a2007370000200041306a20083700002000410c6a2005410874200441ff017172360000200041086a20013600002000410b3a0000200041286a200a370000200041106a200229038806370000200041186a2006290300370000200041206a200329030037000020024190086a24000f0b200241b8076a41106a200241e0066a41106a290300370300200241b8076a41086a200241e0066a41086a290300370300200220022903e0063703b8072000410e3a000020024190086a24000f0b200241e0036a2001103720022903e003a7450d2d20022903e8032207422088a721012007a72106410621050c040b20024188066a200241e0066a41d7001095031a41d800101b2201450d6d200120043a0000200141016a20024188066a41d7001095031a20014108762104410221050b2000410d3a0000200041146a20073700002000410c6a2008370000200041246a200a3700002000411c6a2009370000200041046a2005360000200041086a2004410874200141ff01717236000020024190086a24000f0b200241b8076a200341202003412049220d1b22066a41004100412020066b2006411f4b1b1094031a200241b8076a200420061095031a41042105200141046a200320066b3602002001200420066a360200200d0d29200220022f00b9073b01860620022d00b807210e20022800bb07210420022900c707210720022d00d707210c20022900cf07210820022900bf07210a200220022f0186063b018206200220022f01820622013b018406200220013b018006200a422088a721012008422088a7210d200aa721062008a7210f0c020b200241d0036a2001103720022903d003a7450d2920022903d8032207422088a721012007a72106410521050b0b200220022f0180063b01b8070c8b010b200241b8076a200341202003412049220d1b22056a41004100412020056b2005411f4b1b1094031a200241b8076a200420051095031a200141046a200320056b22063602002001200420056a2205360200200d0d27200220022f00b9073b01860620022d00b807210e20022800bb07210420022900bf07210820022900c707210720022d00d707210c20022900cf07210a200220022f0186063b01e006200220022f01e00622033b018406200220033b01b807200241003a00e006200241e0066a2005200641004722031095031a20062003490d70200141046a200620036b3602002001200520036a3602002006450d35200a422088a7210d200aa7210f20022d00e0062103200220022f01b8073b0180062008422088a721012008a72106410321050c370b200241206a2001102d2002280220450d4720022802242204417f4c0d4f2004450d2c200410df012205450d7620052001280200200141046a22032802002206200420062004491b22061095031a2003280200220d2006490d772003200d20066b3602002001200128020020066a36020020062004470d2d0c88010b200241186a2001102d2002280218450d46200228021c2204417f4c0d4e2004450d2d200410df012205450d7720052001280200200141046a22032802002206200420062004491b22061095031a2003280200220d2006490d782003200d20066b3602002001200128020020066a36020020062004470d2e0c86010b200241b0026a2001102d20022802b002450d164106210620022802b40221040c060b200242003703b807200241b8076a20042003410820034108491b22051095031a200141046a200320056b3602002001200420056a360200200341074d0d4420022903b80721074105210d0c90010b200241a8026a2001102d20022802a802450d1420022802ac022104200141046a22032802002105200241003a00b807200241b8076a2001280200220d200541004722061095031a20052006490d692003200520066b3602002001200d20066a3602002005450d1420022d00b8072105410421060c050b200241b8076a2001103820022d00b8072105200241e0066a200241b8076a41017241d7001095031a2005410e460d1320024188066a200241e0066a41d7001095031a41d800101b2204450d6d200420053a0000200441016a20024188066a41d7001095031a200141046a220d2802002105200241003a00b807200241b8076a2001280200220c200541004722061095031a20052006490d6e200d200520066b22033602002001200c20066a22063602002005450d1220022d00b807220541024b0d1242002108200242003703b807200241b8076a20062003410820034108491b220d1095031a200141046a2003200d6b36020020012006200d6a360200200341074d0d1220022903b8072107410521060c040b200241386a2001102d2002280238450d41200228023c2217ad42187e2207422088a70d492007a72204417f4c0d492004450d2c2004101b22050d2d20044104101c000b200241a0026a2001102d20022802a002450d114103210620022802a40221040c010b200241c0026a2001103720022903c002a7450d1020022903c8022107200241b8026a2001102d20022802b802450d1020022802bc02210442002108410721060b0b200220022f01860622013b01b807200220013b018406200041186a2008370000200041106a2007370000200041096a20053a0000200041086a20063a0000200041063a00002000410c6a20043600002000410a6a20022f0184063b000020024190086a24000f0b20024188066a200241e0066a41d7001095031a41d800101b2201450d61200120053a0000200141016a20024188066a41d7001095031a200220022f0180063b01b807410221060c200b200241b8076a2001103620022d00b80722034102460d7620022d00bb07210420022f00b9072105200241c4076a2902002107200241d4076a2902002108200241cc076a290200210a20022902bc07211320024190036a200110b402200229039003a7450d7620024190036a41106a2903002109200229039803210b20024188036a2001102d200228028803450d76200520044110747221062007422088a721012007a7210d200228028c03210f201342208821072013a72204410876210c4106210e0c7a0b200241f8026a2001102d20022802f802450d7520022802fc0222034108762106420021074104210e0c040b20024180036a2001102d200228028003450d7420022802840322034108762106420021074105210e0c030b200241b0036a2001103720022903b003a7450d7320022903b803220842208821072008a72204410876210c4109210e0c050b200241f0026a2001102d20022802f002450d7220022802f4022103200241b8076a2001103620022d00b80722044102460d7220022d00bb07210620022f00b907210d200241c4076a2902002108200241d4076a290200210a200220022902bc0722073703e0062002200241cc076a2902003703f006200220083703e8062002200a3703f806200241e8026a2001102d20022802e802450d7220022802ec022105200241e0026a2001102d20022802e002450d72200d200641107472210c2007422088a7210d200a422088a7210f2008a721012003410876210620022902f406210820022902ec06210a20022802e402ad210b420021094103210e0c760b200241a8036a2001102d20022802a803450d7120022802ac0322034108762106420021074107210e0b0c730b200241b8076a2001103620022d00b80722034102460d6f20022902bc07220842208821074108210e2008a72204410876210c20022f00b90720022d00bb07411074722106200241c4076a2902002209422088a72101200241d4076a2902002108200241cc076a290200210a2009a7210d0c730b200241c0036a2001103720022903c003a7450d6e20022903c803220842208821072008a72204410876210c410a210e0b0c700b4101210641002004460d780b2004450d7a200610190c7a0b20041043200410190b200220022f0186063b01b8072000410e3a000020024190086a24000f0b200241c8016a2001102d20022802c801450d2820022802cc012105200241c0016a2001102d20022802c001450d2820022802c4012106200241a8016a200110b40220022903a801a7450d28200241b8016a290300210720022903b0012108200541087621124106210d0c240b200241f8016a2001102d20022802f801450d2720022802fc0122054108762112410b210d0c030b200241b8076a2001103620022d00b80722054102460d26200241c4076a290200210720022902bc07210820022f00b90720022d00bb07411074722112200241d4076a290200220a422088a72110200a421088a7210c200a420888a72111200241cc076a2902002209422088a7210e200aa7210f2009a721064104210d0c220b200241a0016a2001102d20022802a001450d2520022802a401220541087621124105210d0c010b200241f0016a2001102d20022802f001450d2420022802f401220541087621124109210d0b0c200b200241d0016a2001103720022903d001a7450d2220022903d8012207422088a721172007a721184107210d0c010b200241e0016a2001103720022903e001a7450d2120022903e8012207422088a721172007a721184108210d0b0c1d0b20024180026a2001102d200228028002450d1f2002280284022217ad2207421b88a70d2c2007420586a72204417f4c0d2c2004450d192004101b22050d1a20044101101c000b200241003a00b807200241b8076a2016200341004722041095031a20032004490d4c200141046a200320046b3602002001201620046a3602002003450d1e20022d00b8072119410a210d0c1c0b200220022f0182063b0184060b200220022f0180063b01b8070c5e0b200220022f01e0063b018406410721050c0e0b410621040c5b0b410421060b0b200220022f0180063b01b80720064104460d620b200220022f01b8073b01fe05200041056a20053a0000200041046a20063a0000200041093a0000200041286a200d360000200041256a20103a0000200041246a20033a0000200041206a200c3600002000411c6a200f360000200041146a2007370000200041106a200e3600002000410c6a2001360000200041086a2004360000200041066a20022f01fe053b000020024190086a24000f0b4101210541002004460d5b0b20040d180c190b4101210541002004460d580b20040d160c170b4101210541002004460d610b20040d140c150b410421050b024002402017450d00420021074100210e410021044100210d201721110340200241306a2001102d2002280230450d1420022802342203417f4c0d1e024002402003450d00200310df01220f450d38200f2001280200200141046a220c2802002206200320062003491b22061095031a200c28020022102006490d39200c201020066b3602002001200128020020066a36020020062003460d010c150b4101210f41002003470d140b200241286a2001102d2002280228450d13200228022c2206417f4c0d1e024002402006450d00200610df012210450d3520102001280200200141046a2212280200220c2006200c2006491b220c1095031a20122802002218200c490d3620122018200c6b36020020012001280200200c6a360200200c2006460d010c140b4101211041002006470d130b200d41016a210c0240200d2011470d00200e200c200c200e491b2211ad42187e2208422088a70d2e2008a722124100480d2e0240200d450d00200520042012101a22050d010c340b2012101b2205450d330b200520046a220d200f360200200d41146a2006360200200d41106a2006360200200d410c6a2010360200200d41046a2003ad220842208620088437020020074280808080107c2107200e41026a210e200441186a2104200c210d200c2017490d000c020b0b41002111420021070b2005450d1320072011ad8421074107210d0c5f0b410721050b0b200220022f0180063b01b80720054107470d520c4d0b4101210541002006460d520b2006450d56200510190c560b410121034100210c420021070b2003450d47200241d0026a2001102d2007200cad842207a7210420022802d002450d0d20022802d402210d2004410876210c20034108762106200742208821074102210e0c4a0b200c450d460c450b410121050b024002402017450d00200241d0076a2118200241c8076a2119200241c0076a2116200141046a210e200241c7076a211a200241cf076a211b420021074100210c411f210d41002103201721120340201842003703002019420037030020164200370300200242003703b807200241b8076a2001280200220f200e2802002204412020044120491b22061095031a200e200420066b3602002001200f20066a3602002004411f4d0d06200341016a2106200220022f00b9073b018606201a2900002108201b290000210a200241b8076a411f6a2d0000210f20022d00b807211020022800bb07211120022900bf072109200220022f0186063b018406024020032012470d00200c20062006200c491b2212ad420586220b422088a70d24200ba722044100480d2402402003450d002005200d41616a2004101a22050d010c280b2004101b2205450d270b2005200d6a220441616a20103a0000200441786a200a370000200441706a2008370000200441686a2009370000200441646a201136000020022f01840621032004200f3a0000200441626a20033b000020074280808080107c2107200c41026a210c200d41206a210d2006210320062017490d000c020b0b41002112420021070b2005450d0420072012ad84210820054108762112410c210d0b2008422088a721172008a721180b0b200220022f01e00622013b01b807200220013b018806200041096a20193a0000200041086a200d3a0000200041053a00002000412c6a20103600002000412a6a200c3b0000200041296a20113a0000200041286a200f3a0000200041246a200e360000200041206a2006360000200041186a2007370000200041146a2017360000200041106a20183600002000410c6a2012410874200541ff0171723600002000410a6a20022f0188063b000020024190086a24000f0b2012450d00200510190b200220022f01e0063b01b8072000410e3a000020024190086a24000f0b2006450d00201010190b2003450d00200f10190b0240200d450d002005210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141186a2101200441686a22040d000b0b2011450d010b200510190b2000410e3a000020024190086a24000f0b20040d380c390b4101210e41002006460d420b2006450d00200e10190b0c440b410121064100200c460d3e0b200c450d35200610190c350b200520041027000b102b000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b200420061027000b101d000b200620041027000b200c4101101c000b20044101101c000b200520031027000b20124104101c000b20064101101c000b200c20181027000b41d8004108101c000b20034101101c000b200620101027000b20044101101c000b2005200d1027000b200c20061027000b41d8004108101c000b200620051027000b41d8004108101c000b200320061027000b200420031027000b41d8004108101c000b41d8004108101c000b200620051027000b20044101101c000b2006200d1027000b20044101101c000b2006200d1027000b20044101101c000b2006200d1027000b20064101101c000b2003200c1027000b20104101101c000b20064101101c000b200c20101027000b200c4101101c000b200e20101027000b200310190b2000410e3a000020024190086a24000f0b0c0c0b2000410e3a000020024190086a24000f0b0b200041073a0000200041c0006a2009370000200041386a200b370000200041346a2005360000200041306a200f360000200041286a2008370000200041206a200a3700002000411c6a2001360000200041186a200d360000200041086a200e3600002000410c6a2006410874200341ff017172360000200041106a2007422086200cad42ffffff07834208862004ad42ff0183848437000020024190086a24000f0b2004ad220742208620078421074104210d0c0b0b2004ad220742208620078421074106210d0c0a0b200220022f01b8073b01fe05200041096a200e3a0000200041086a20053a0000200041083a0000200041296a20033a0000200041286a200c3a0000200041246a200d360000200041206a200f360000200041186a2007370000200041146a2001360000200041106a20063600002000410c6a20043600002000410a6a20022f01fe053b000020024190086a24000f0b2006ad22084220862008842108410321040c050b200241f0066a20093703002002200b3703e806200220022f0182063b018006200220133703f8062002200cad22094220862009843703e006410521040c040b200241f8066a2013370300200220143703f0062002200e3602e00620022006ad22134220862013843702e406200742808080807083200742ffffffff0f83842107200d2003411074724108742005722105200b422088a72106200ba72103410421040c030b2000410e3a000020024190086a24000f0b2000410a3a0000200041086a2006360000200041046a41023600002000410c6a2004ad220742208620078437000020024190086a24000f0b0b200241b8076a41086a2201200241e0066a41086a290300370300200241b8076a41106a220c200241e0066a41106a290300370300200241b8076a41186a220e200241e0066a41186a290300370300200220022f0180063b018606200220022903e0063703b807024020044106470d002000410e3a000020024190086a24000f0b20024188066a41086a220f200129030037030020024188066a41106a2201200c29030037030020024188066a41186a220c200e290300370300200220022f0186063b01fe05200220022903b80737038806200041096a200d3a0000200041086a20043a00002000410c3a00002000412c6a2006360000200041286a2003360000200041206a200a370000200041186a2007370000200041106a20083700002000410c6a20053600002000410a6a20022f01fe053b0000200041306a200229038806370000200041386a200f290300370000200041c0006a2001290300370000200041c8006a200c290300370000200041d0006a200937000020024190086a24000f0b2000410e3a000020024190086a24000f0b2004ad220742208620078421074102210d0b200041013a0000200041106a20073700002000410c6a2005360000200041086a200d36000020024190086a24000f0b2000410e3a000020024190086a24000befba0121057f027e027f027e087f0b7e1c7f027e027f017e027f027e0c7f027e097f017e2d7f017e0f7f017e067f017e217f017e027f037e0c7f017e057f017e107f027e087f230041d0086b22012400200141d0036a41086a22024200370300200142003703d003418698c1004113200141d0036a1001200141c0036a41086a2002290300370300200120012903d0033703c0030240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141c0036a411041d889c200410041001000417f460d00200141003a00d807200141c0036a4110200141d8076a41014100100041016a41014d0d0220012d00d8072103200141d0036a41086a22044200370300200142003703d003418698c1004113200141d0036a100120014190046a41086a22022004290300370300200120012903d0033703900420014190046a411010022003450d0020024200370300200142003703900441d082c000411d20014190046a1001200141d8076a41086a200229030037030020012001290390043703d8070240200141d8076a411041d889c200410041001000417f460d00200142103702b4042001200141d8076a3602b004200141f8056a200141b0046a103a20012802f8052205450d0420012902fc05210620014190046a41086a22024200370300200142003703900441d082c000411d20014190046a1001200141d0036a41086a200229030037030020012001290390043703d003200141d0036a41101002200141063602fc05200141e481c0003602f805200141d8076a41fbd7c100200141f8056a103b41002104024020012802d807220220012802e007220341d889c200410041001000417f460d00200141003602f80520022003200141f8056a41044100100041016a41044d0d0320012802f80521040b024020012802dc07450d00200210190b024002402004450d002004ad4205862207422088a70d212007a722024100480d212002101b2208450d0841002103200821020340200141d8076a20031033200241186a200141d8076a41186a290000370000200241106a200141d8076a41106a290000370000200241086a200141d8076a41086a290000370000200220012900d807370000200241206a21022004200341016a2203470d000c020b0b410121080b02400240024020042006422088a7470d00024020082005460d002004450d0041002109200821022005210303402002200341201097030d02200241206a2102200341206a2103200941016a22092004490d000b0b2004450d01200810192006a70d020c030b200141e4076a2004360200200141e0076a2004360200200120083602dc07200141013a00d807200141d8076a103c0b2006a7450d010b200510190b200141d0036a41086a22024200370300200142003703d00341d380c1004118200141d0036a1001200141e0036a41086a22032002290300370300200120012903d0033703e00342002106024002400240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0120012903d80721060b20024200370300200142003703d00341d1fbc0004115200141d0036a100120032002290300370300200120012903d0033703e00302400240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0320012903d80722074200520d0141b880c3001029000b42e80721070b200141d0036a41086a22024200370300200142003703d00341e3f9c0004119200141d0036a1001200141e0036a41086a2002290300370300200120012903d0033703e003200020067d200782210a0240200141e0036a411041d889c200410041001000417f460d00200141003a00d807200141e0036a4110200141d8076a41014100100041016a41014d0d0720012d00d8072102200141d0036a41086a22034200370300200142003703d00341e3f9c0004119200141d0036a100120014190046a41086a2003290300370300200120012903d0033703900420014190046a41101002200241004721030c090b200a4200520d09410121030c080b41fcf9c00041331030000b41fcf9c00041331030000b41a091c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b20024101101c000b4200210b200141d0036a41086a22024200370300200142003703d003419399c100410d200141d0036a1001200141c0036a41086a2002290300370300200120012903d0033703c0034200210602400240024002400240024002400240200141c0036a411041d889c200410041001000417f460d00200142003703d807200141c0036a4110200141d8076a41084100100041016a41084d0d0120012903d80721060b20024200370300200142003703d00341eb80c1004114200141d0036a1001200141e0036a41086a2002290300370300200120012903d0033703e0030240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0220012903d807210b0b200141d0036a41086a22024200370300200142003703d00341bdfbc0004114200141d0036a1001200141e0036a41086a22042002290300370300200120012903d0033703e00302400240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0420012903d80742017c21070c010b420121070b200141d8076a41086a2007370300200141033a00d807200141d8076a103d200120073703d80720024200370300200142003703d00341bdfbc0004114200141d0036a1001200141c0036a41086a22092002290300370300200120012903d0033703c003200141c0036a4110200141d8076a41081003200120063703d80720024200370300200142003703d00341eb80c1004114200141d0036a100120092002290300370300200120012903d0033703c003200141c0036a4110200141d8076a4108100320024200370300200142003703d00341ff80c1004119200141d0036a100120042002290300370300200120012903d0033703e00302400240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0520012903d8072107200141d0036a41086a22024200370300200142003703d00341ff80c1004119200141d0036a100120014190046a41086a2002290300370300200120012903d0033703900420014190046a411010024201a74101470d010c060b4200a74101460d050b200a500d060c050b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b200120073703d807200141d0036a41086a22024200370300200142003703d00341d1fbc0004115200141d0036a1001200141c0036a41086a2002290300370300200120012903d0033703c003200141c0036a4110200141d8076a410810030b200141d0036a41086a22024200370300200142003703d003419c82c000410d200141d0036a1001200141c0036a41086a22042002290300370300200120012903d0033703c003420021070240200141c0036a411041d889c200410041001000417f460d00200142003703d807200141c0036a4110200141d8076a41084100100041016a41084d0d0920012903d80721070b200120073703d80720024200370300200142003703d00341d380c1004118200141d0036a100120042002290300370300200120012903d0033703c003200141c0036a4110200141d8076a410810030b2006200b7d2003103e42002106200141d0036a41086a22024200370300200142003703d0034181fcc0004112200141d0036a1001200141e0036a41086a2002290300370300200120012903d0033703e00302400240200141e0036a411041d889c200410041001000417f460d00200142103702fc052001200141e0036a3602f805200141d8076a200141f8056a103a20012802d807220c450d1020012902dc0721060c010b4101210c0b02402006422088a74105742205450d00200c21034100210903404112101b2202450d05200241106a41002f00a881413b0000200241086a41002900a08141370000200241002900988141370000200241124132101a2202450d06200220032900003700122002412a6a200341186a290000370000200241226a200341106a2900003700002002411a6a200341086a290000370000200141d0036a41086a22044200370300200142003703d00320024132200141d0036a1001200141e0036a41086a2004290300370300200120012903d0033703e0030240200141e0036a411041d889c200410041001000417f470d0020021019200341206a2103200941016a2109200541606a22050d010c020b20014190046a41186a220d420037030020014190046a41106a220e420037030020014190046a41086a220842003703002001420037039004200141e0036a411020014190046a412041001000220f417f460d03200f411f4d0d03200141f0036a41186a220f200d290300370300200141f0036a41106a2210200e290300370300200141f0036a41086a2211200829030037030020012001290390043703f00320044200370300200142003703d00320024132200141d0036a100120082004290300370300200120012903d0033703900420014190046a4110100220021019200141f8056a41186a2212200f290300370300200141f8056a41106a22132010290300370300200141f8056a41086a22102011290300370300200120012903f0033703f805200141063602dc07200141e481c0003602d807200141b0046a2009200141d8076a103402400240024020012802b0042202200141b0046a41086a2204280200220f41d889c200410041001000417f470d00200141d8076a41186a4200370300200141d8076a41106a4200370300200141d8076a41086a4200370300200142003703d80720012802b4040d010c020b200d4200370300200e42003703002008420037030020014200370390042002200f20014190046a412041001000220f417f460d09200f411f4d0d09200141d8076a41186a200d290300370300200141d8076a41106a200e290300370300200141d8076a41086a200829030037030020012001290390043703d80720012802b404450d010b200210190b0240200141d8076a200141f8056a4120109703450d0041002102200141003602b004200141b0046a103f200141063602ec06200141e481c0003602e806200141b0046a41fbd7c100200141e8066a103b024020012802b00422082004280200220d41d889c200410041001000417f460d00200141003602e8062008200d200141e8066a41044100100041016a41044d0d0620012802e80621020b024020012802b404450d00200810190b200220094d0d00200141063602ec06200141e481c0003602e806200141b0046a2009200141e8066a10342004280200210820012802b00421044120101b2202450d0d200220012903f805370000200241186a2012290300370000200241106a2013290300370000200241086a2010290300370000200420082002412010032002101920012802b404450d00200410190b200341206a2103200941016a2109200541606a22050d000b0b2006a7450d00200c10190b200141c0036a41086a22024200370300200142003703c00341859fc1004116200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e003024002400240200141e0036a411041d889c200410041001000417f460d00200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0820012903d80722064200510d0f4200211420002006824200520d020c010b42002114200042e807824200520d010b41082110200141c0036a41086a22022014370300200120143703c003419b9fc1004115200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e00341002111024002400240024002400240200141e0036a411041d889c200410041001000417f460d00200142103702fc052001200141e0036a3602f805200141d8076a200141f8056a104020012802d8072210450d1520012802dc072112200141e0076a280200221141077422020d010c020b4100211241004107742202450d010b201020026a2105200141d8076a2010280258104120104180016a210202400240024020012802e8072203450d00200141b0036a20012903d807200141d8076a41086a290300200141f0076a3502004200109903200141b0036a41086a290300210620012903b003210b024020012802ec07450d00200310190b4100210920022005470d010c020b4200210b420021064100210920022005460d010b200141e8076a210d200141f0076a210e200141ec076a210f41012104201021080340200141d8076a200241d8006a280200104102400240200d2802002203450d00200141a0036a20012903d807200141d8076a41086a290300200e3502004200109903200141a0036a41086a290300210720012903a003210a200f280200450d01200310190c010b4200210a420021070b20062007200b200a56200620075620062007511b22031b2106200b200a20031b210b2009200420031b21092008200220031b2108200441016a210420024180016a22022005470d000b2008450d010b201120094d0d15201020094107746a220241186a2209290300210620102011417f6a22044107746a220329030021072003290308210b2003290310210a2009200341186a290300370300200229031021152002200a3703102002290308210a2002200b3703082002290300210b20022007370300200241386a22092900002107200341206a2903002116200341286a2903002117200341306a29030021182009200341386a290300370000200241306a2209290000211920092018370000200241286a2209290000211820092017370000200241206a2209290000211720092016370000200241d8006a22082800002109200341c0006a2903002116200341c8006a290300211a200341d0006a290300211b2008200341d8006a290300370000200241d0006a2208290000211c2008201b370000200241c8006a2208290000211b2008201a370000200241c0006a2208290000211a20082016370000200341e0006a2903002116200341e8006a290300211d200341f0006a290300211e200241f8006a200341f8006a290300370200200241f0006a201e370200200241e8006a201d370200200241e0006a2016370200200141f8056a41d0006a201c370300200141f8056a41c8006a201b370300200141f8056a41c0006a201a370300200141f8056a41386a2007370300200141f8056a41306a2019370300200141f8056a41286a2018370300200141f8056a41206a2017370300200141f8056a41186a200637030020012015370388062001200a370380062001200b3703f805200120043602e007200120123602dc07200120103602d807200141153602b4042001419b9fc1003602b004200141d8076a200141b0046a104202402004450d00201141077441807f6a21032010210203402002104320024180016a2102200341807f6a22030d000b0b02402012450d00201010190b4113101b2202450d162002410f6a41002800bf9f41360000200241086a41002900b89f41370000200241002900b09f41370000200241134126101a2202450d172002200936001320014190046a41086a2203420037030020014200370390042002411720014190046a1001200141d0036a41086a200329030037030020012001290390043703d003200141d0036a411041d889c200410041001000417f460d012001200141d0036a3602e806200141103602ec06200142003703e007200142003703d80720014100200141d0036a4110200141d8076a41104100100022032003417f461b2203411020034110491b3602f0062003410f4d0d14200141d8076a41086a290300210a20012903d8072115200141d8076a200141e8066a103a20012802d8072205450d14200120012902dc0722063703b00420012802b404210820014190046a41086a2203420037030020014200370390042002411720014190046a1001200141c0036a41086a200329030037030020012001290390043703c003200141c0036a41101002200210192006a7210d024020084105742203450d0020052102034020014190036a2002104420014190036a41086a2903002106200129039003210720014180036a2002104520022015200720072015562006200a562006200a511b22041b220b2001290380037c2216200a200620041b221720014180036a41086a2903007c2016200b54ad7c104620022007200b7d200620177d2007200b54ad7d1047200241206a2102200341606a22030d000b0b20014180086a200a370300200141f8076a2015370300200141f0076a2008360200200141ec076a200d360200200141d8076a41106a2005360200200141e4076a2009360200200141d8076a41086a41013a0000200141053a00d807200141d8076a103d200141c0036a41086a22024200370300200142003703c00341b599c1004116200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e003200141e0036a411041d889c200410041001000417f460d02200142003703d807200141e0036a4110200141d8076a41084100100041016a41084d0d0f20012903d80721070c030b02402011450d00201141077421032010210203402002104320024180016a2102200341807f6a22030d000b0b2012450d03201010190c030b20021019200141f8056a10430c020b42e80721070b200141d8076a200141f8056a41d8001095031a42002106200141c0036a41086a22024200370300200142003703c00341c39fc1004115200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e0030240200141e0036a411041d889c200410041001000417f460d00200142003703b004200141e0036a4110200141b0046a41084100100041016a41084d0d0d20012903b00421060b200141b0046a200720007c200141d8076a41002006104820012802b0044101470d0020012802b404200141b0046a41086a28020010040c140b200141c0036a41086a22022014370300200120143703c00341d89fc1004113200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e003410021020240200141e0036a411041d889c200410041001000417f460d00200141003602d807200141e0036a4110200141d8076a41044100100041016a41044d0d0820012802d80721020b200141c0036a41086a22034200370300200142003703c00341eb9fc1004119200141c0036a1001200141e0036a41086a2003290300370300200120012903c0033703e0034100211f0240200141e0036a411041d889c200410041001000417f460d00200141003602d807200141e0036a4110200141d8076a41044100100041016a41044d0d0920012802d807211f0b02402002201f4f0d00200141d8076a200210490240024020012d00c00822034103470d00200141c0086a21040340200241016a2202201f4f0d03200141d8076a2002104920042d000022034103460d000b200241016a21040c010b200241016a21040b200141b0046a41046a2220200141d8076a41e80010950321082001200141d8076a41ec006a2800003600a305200120012800c1083602a005200141e8066a200141b0046a41ec001095031a200120023602d807200141d8076a410472200141e8066a41ec001095031a200141d8076a41f0006a20033a0000200141c9086a220220012802a005360000200141cc086a20012800a305360000024020012903e0072000520d00200141f8056a200141d8076a41f0001095031a2001200241036a2800003600930420012002280000360290044100210920034103460d010c160b200141e8076a1043410321034101210941034103470d150b410821214100212241002125410021020c150b41fcf9c00041331030000b41fcf9c00041331030000b41124101101c000b41324101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41204101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41c096c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41d896c30020092011104a000b41134101101c000b41264101101c000b410421020c010b200141d8076a200141f8056a41f0001095031a20012001280093043600b30420012001280290043602b004024002400240024041f800101b2221450d002021200141d8076a41f000109503220220033a0070200220012802b004360071200241f4006a20012800b3043600004101212220090d032004201f4f0d03200141d8076a200410490240024020012d00c00822234103470d00200141c0086a21030340200441016a2204201f4f0d06200141d8076a2004104920032d000022234103460d000b200441016a21240c010b200441016a21240b2008200141d8076a41e8001095031a2001200141d8076a41ec006a2800003600a305200120012800c1083602a005200141e8066a200141b0046a41ec001095031a200120043602d807200141d8076a410472200141e8066a41ec001095031a200141d8076a41f0006a20233a0000200141c9086a220320012802a005360000200141cc086a20012800a3053600000240024020012903e0072000520d00200141f8056a200141d8076a41f0001095031a2001200341036a280000360093042001200328000036029004410021704103217120234103470d010c040b200141e8076a104341032123410121704103217141034103460d030b200141e8076a21e40141f10021e501200141d8076a41f1006a21e601200141d8076a41047221e701200141c1086a21e801410121e90141f00021ea0142f80021eb01422021ec01410021ed0141f80021ee0141f40021ef0141ff0121f00141e80021f101200141d8076a41e8006a21f20141ec0021f301200141e0076a21f4014101212241012125410421680c010b41f8004108101c000b410621020c020b410121220b4101212541f80021262002202241f8006c6a2127024020220d00410221020c010b410121020b0340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e0700010203040506060b41f80021262021202241f8006c6a21272022450d5b410121020c6c0b41082128200141b0046a41086a2129200141d8076a41086a212a20014199056a212b4104212c200141e8066a41046a212d41ec00212e41f100212f41f400213041f00021314103213241e8002133200141f8056a41086a21344116213541a7fbc00021364100213741d889c200213841102139417f213a4202213b423e213c41fe00213d4102213e4200213f417e214041ff002141423f2142420121434115214441c39fc100214541052146200141e4076a2147410121484113214941d89fc100214a41e000214b200141b0046a41e0006a214c41d800214d200141e1076a214e4106214f42e00021504220215141172152410f2153412e2154411f2155410e215641a07f215741182158412021594107215a4238215b4111215c4131215d4129215e4121215f4119216041c0002161412c216241242163411c2164413421654160216620212167410021680c5e0b202122672027460d050c040b207521720c060b2000104b41082188014200218901200141c0036a41086a228a014200370300200142003703c0034117218b0141e3e1c000218c0141e3e1c0004117200141c0036a1001200141e0036a41086a228d01208a01290300370300200120012903c0033703e0034100218e0141d889c200218f014110219001417f219101200141e0036a411041d889c200410041001000417f460d074101219201200141b0046a4101722193014105219401200141d8076a4105722195014120219601200141d8076a41206a219701200141d8076a4101722198014210219901200141d8076a41086a219a01410e219b0141d700219c014118219d014115219e01419993c000219f01422021a001412821a101410621a20141ff0121a301410c21a401200141b0046a410c6a21a501413021a601200141d8076a41306a21a701412c21a801200141d8076a412c6a21a901410721aa01411c21ab01413c21ac01413421ad01412421ae0141d80021af01410d21b001419c82c00021b101410221b201411621b30141b599c10021b401411e21b50141aee2c00021b601411b21b701413b21b801413321b901412b21ba01412321bb0141f60021bc0141d30021bd0141cb0021be0141c30021bf0141db0021c001415821c101422821c201413821c301410221680c610b207241e0006a22722075470d100c110b024020680e050003050712120b206722022802002108200141d8076a2002202c6a202e1095031a20012002202f6a2800003602f8052001200220306a2800003600fb05200220266a21670240200220316a2d0000220d2032460d00200141e8066a200141d8076a202e1095031a200120012800fb053600d303200120012802f8053602d003200141b0046a202d20331095031a200141b0046a20336a200d3a0000202b20012802d003360000202b20326a20012800d303360000200141f8056a2008104c20012802f805210e02400240024020342802002202450d002002204674210942002107200e210242002106420021164200211442002115420021170340200141f0026a20021045200141f0026a20286a290300211820012903f002210b200141e0026a20021044200141e0026a20286a290300211920012903e002210a200141d8076a20586a2204200220586a290000370300200141d8076a20396a2205200220396a290000370300202a200220286a290000370300200120022900003703d8072039101b2203450d17200320286a20372900d39941370000200320372900cb9941370000200320392059101a2203450d1820032008360010200320592061101a2203450d19200320012903d807370014200320626a2004290300370000200320636a2005290300370000200320646a202a290300370000200141c0036a20286a2204203f3703002001203f3703c00320032065200141c0036a100120014190046a20286a2004290300370300200120012903c0033703900441002104024020014190046a20392038410041001000203a460d00200120373a00a00520014190046a2039200141a0056a20482037100020486a20484d0d1e20012d00a00521040b200220596a2102200141d0026a200a200b7c220b201920187c200b200a54ad7c220a20042058742058752205205a7620047320486aad205b86205b87203f10990320031019200a20067c200b20077c2207200b54ad7c2106203f200141d0026a20286a290300220b200520374822031b20147c203f20012903d002220a20031b221420167c2216201454ad7c2114200b203f20031b20177c200a203f20031b220b20157c2215200b54ad7c2117200920666a22090d000b20012802fc05450d020c010b42002115420021174200211642002114420021074200210620012802fc05450d010b200e10190b4200210a200141c0036a20286a22694200370300200142003703c00320362035200141c0036a1001200141e0036a20286a226a2069290300370300200120012903c0033703e00302400240200141e0036a20392038203720371000203a460d002001203f3703e0072001203f3703d807200141e0036a2039200141d8076a2039203710002202203a460d27200220534d0d27202a290300210b20012903d807210a0c010b4200210b0b0240024002402007203b882006203c868422182007852006203b88221920068584500d002018201984500d004100210202400340200141c0026a200720062002202c6a203d71109b032002203e6a210220012903c0022218200785200141c0026a20286a290300221920068584500d012018201984203f520d000b0b200141b0026a200720062002203d71109b0320012903b002200141b0026a20286a290300842118420021192002450d012018420052ad2118034020014190026a200720062037200220406a2203200320024b1b2202204171109b03200141a0026a2018204386221b204384221a20192043862018204288842219201a2019109903201b201a20012903a00220012903900256200141a0026a20286a290300221820014190026a20286a290300221c562018201c511b1b211820020d000c030b0b420021192007200684420052ad21180c010b2018420052ad21180b02400240024002400240200a203b88200b203c86842206200a85200b203b882207200b8584500d002006200784500d00410021020240034020014180026a200a200b2002202c6a203d71109b032002203e6a21022001290380022206200a8520014180026a20286a2903002207200b8584500d012006200784203f520d000b0b200141f0016a200a200b2002203d71109b0320012903f001200141f0016a20286a290300842106420021072002450d012006420052ad21060340200141d0016a200a200b2037200220406a2203200320024b1b2202204171109b03200141e0016a2006204386221b204384221a20072043862006204288842207201a2007109903201b201a20012903e00120012903d00156200141e0016a20286a2903002206200141d0016a20286a290300221c562006201c511b1b210620020d000b2018201984500d030c020b42002107200a200b84420052ad2106201820198450450d010c020b2006420052ad21062018201984500d010b0240200d203e460d000240200d2048470d000340201921192018211a2006200784203f510d22200141b0016a20152017201a2019109803200141c0016a20162014200620071098034101216b20012903c001221820012903b001221b54200141c0016a20286a290300220b200141b0016a20286a290300220a54200b200a5122021b0d04201b201854200a200b5420021b0d03200141a0016a2018200b2006200710990320014190016a201b200a201a20191099032015200129039001220b7d220a201720014190016a20286a2903007d2015200b54ad7d220b84500d032014200141a0016a20286a2903007d211b201620012903a0012215542102201620157d21182006211520072117200a2106200b2107201a2116201921142018201b2002ad7d22198450450d000c040b0b034020014180016a20162014201820191098032006220a2007221a84203f510d2220014180016a20286a2903002106200129038001210b200141f0006a20152017200a201a1098034101216b200b2001290370221b542006200141f0006a20286a290300220754200620075122021b0d03201b200b54200720065420021b0d02200141e0006a200b200620182019109903200141d0006a201b2007200a201a1099032015200129035022067d22072017200141d0006a20286a2903007d2015200654ad7d220b84500d022014200141e0006a20286a2903007d211b201620012903602206542102201620067d2106201821152019211720072118200b2119200a2116201a21142006201b2002ad7d22078450450d000c030b0b2015201656201720145620172014511b216b0c010b4100216b0b4200210a20694200370300200142003703c00320452044200141c0036a1001206a2069290300370300200120012903c0033703e0030240200141e0036a20392038203720371000203a460d002001203f3703d807200141e0036a2039200141d8076a20282037100020486a20284d0d1d20012903d807210a0b200141d8076a2008104c20012802d807216c20012802dc07216d0240202a2802002202450d00206c20022046746a2112200141f8056a20586a220c206c20586a290000370300200141f8056a20396a226e206c20396a2900003703002034206c20286a2900003703002001206c2900003703f805200141d8076a2008200141f8056a104d20014190046a20586a2203200141d8076a20586a221029030037030020014190046a20396a2204200141d8076a20396a221129030037030020014190046a20286a2209202a290300370300200120012903d80737039004206c20596a2102200141d8076a20596a2113034020132d00002105200141f0036a20586a220d2003290300370300200141f0036a20396a220e2004290300370300200141f0036a20286a220f200929030037030020012001290390043703f0032003200d2903003703002004200e2903003703002009200f290300370300200120012903f0033703900402402005205874205875203748206b45226f730d00034020122002460d03200c200220586a290000370300206e200220396a2900003703002034200220286a290000370300200120022900003703f805200141d8076a2008200141f8056a104d20032010290300370300200420112903003703002009202a290300370300200120012903d8073703900420132c00002105200d2003290300370300200e2004290300370300200f200929030037030020012001290390043703f0032003200d2903003703002004200e2903003703002009200f290300370300200120012903f00337039004200220596a21022005203748206f73450d000b0b200141a0056a20586a220d2003290300370300200141a0056a20396a220e2004290300370300200141a0056a20286a220f200929030037030020012001290390043703a0052010200d2903003703002011200e290300370300202a200f290300370300200120012903a0053703d807205c101b220d450d28200d20396a20372d00eb9941220e3a0000200d20286a20372900e399412207370000200d20372900db9941220b370000200d205c205d101a220d450d29200d20012903d807370011200d205e6a2010290300370000200d205f6a2011290300370000200d20606a202a2903003700004200210620694200370300200142003703c003200d205d200141c0036a1001206a2069290300370300200120012903c0033703e0030240200141e0036a20392038203720371000203a460d002001203f3703f805200141e0036a2039200141f8056a20282037100020486a20284d0d1e20012903f80521060b200d1019205c101b220d450d2a200d20396a200e3a0000200d20286a2007370000200d200b370000200d205c205d101a220d450d2b200d20012903d807370011200d205e6a2010290300370000200d205f6a2011290300370000200d20606a202a2903003700002001200a2005205874205875205a7620057320486aad205b86205b877e20007c2207200620062007541b3703f8052069203f3703002001203f3703c003200d205d200141c0036a1001206a2069290300370300200120012903c0033703e003200141e0036a2039200141f8056a20281003200d101920022012460d01200c200220586a290000370300206e200220396a2900003703002034200220286a290000370300200120022900003703f805200141d8076a2008200141f8056a104d20032010290300370300200420112903003703002009202a290300370300200120012903d80737039004200220596a21020c000b0b0240206d450d00206c10190b2008104e0240024002400240024002400240206b450d0020472008360200202a20323a0000200120463a00d807200141d8076a103d204c2903002206500d01200141f8056a200141b0046a20311095031a20014190046a200620007c2206104f200141d8076a200141f8056a20311095031a200141a0056a202a204d1095031a200128029404220920014190046a20286a22032802002202470d02200220486a22042002490d6f20022048742209200420042009491b2209ad20507e2207205188a70d6f2007a722052037480d6f2002450d032001280290042002204b6c2005101a22040d040c430b20472008360200202a202c3a0000200120463a00d807200141d8076a103d2001200820486a3602d8072069203f3703002001203f3703c003204a2049200141c0036a1001206a2069290300370300200120012903c0033703e003200141e0036a2039200141d8076a202c10032029104320672027470d500c050b200141d8076a2029204d1095031a200120373b01f805200141c8006a200141d8076a200141f8056a10502001280248210220472008360200204e2002453a0000202a204f3a0000200120463a00d807200141d8076a103d2001200820486a3602d8072069203f3703002001203f3703c003204a2049200141c0036a1001206a2069290300370300200120012903c0033703e003200141e0036a2039200141d8076a202c100320672027470d4e0c040b20012802900421040c020b2005101b2204450d3f0b200120093602940420012004360290040b20042002204b6c220e6a200141a0056a204d10950321052003200220486a220d360200200520083602582052101b2202450d33200220536a2037290093a041370000200220286a203729008ca04137000020022037290084a041370000200220522054101a2202450d3420022006370017200120553602dc07200120023602d80720014190046a200141d8076a1051200210190240200d450d00200e204b6a2103200421020340024020022d00002056460d00200210430b2002204b6a2102200320576a22030d000b0b02402009450d00200410190b2001200820486a3602d8072069203f3703002001203f3703c003204a2049200141c0036a1001206a2069290300370300200120012903c0033703e003200141e0036a2039200141d8076a202c100320672027470d490b202721670b20672027460d010b200141e8076a2103200141d8076a41f1006a21020340200141d8076a206741f0001095031a206741f0006a2d000021722001206741f4006a2800003600b3042001206741f1006a2800003602b00420724103460d01200141f8056a200141d8076a41f0001095031a200120012800b3043600eb06200120012802b0043602e806200141d8076a200141f8056a41f0001095031a200141d8076a41f0006a20723a0000200220012802e806360000200241036a20012800eb0636000020031043206741f8006a22672027470d000b0b02402025450d00202110190b4117101b2272450d3b2072410f6a4100290093a041370000207241086a410029008ca04137000020724100290084a04137000020724117412e101a2272450d3c20722000370017200141c0036a41086a22024200370300200142003703c0032072411f200141c0036a1001200141e0036a41086a2002290300370300200120012903c0033703e00302400240200141e0036a411041d889c200410041001000417f460d00200142103702fc052001200141e0036a3602f805200141d8076a200141f8056a105220012802d8072273450d4020012902dc072106200141c0036a41086a22024200370300200142003703c0032072411f200141c0036a100120014190046a41086a2002290300370300200120012903c0033703900420014190046a411010022006422088a721022006a721740c010b4108217341002102410021740b207210192073200241e0006c22036a227521722003450d014101217620732d0000217741d7002178200141b0046a207341016a41d7001095031a207341e0006a2172410f21792077410f460d0141e000217a2073200241e0006c6a217b200141d8076a410172217c41ff01217d410e217e41a07f217f41d8002180014100218101200141e4076a218201200141e1076a218301200141e0076a218401410621850141052186012073218701410121680c5b0b200141e8066a200141b0046a20781095031a200141f8056a200141e8066a20781095031a02402077207d71207e470d000340207b2072460d5520722d00002177200141b0046a207220766a20781095031a20772079460d572072207a6a2172200141e8066a200141b0046a20781095031a200141f8056a200141e8066a20781095031a2077207e460d000b2072207f6a2187010b2087012080016a2802002102200141a0056a200141f8056a20781095031a200120773a00d807207c200141a0056a20781095031a20012081013b01f805200141c0006a200141d8076a200141f8056a10502001280240210320820120023602002083012003453a00002084012085013a000020012086013a00d807200141d8076a103d207222022075460d0b20022d00002177200141b0046a200220766a20781095031a2002207a6a2172200221870120772079470d470b20722075460d0c0c0b0b20012099013702fc052001200141e0036a3602f805200141d8076a200141f8056a105320012802d8072202450d2420012802dc072109410e21030240024002400240209a012802002204450d0020022903002000520d0020014190046a209d016a220520022096016a29000037030020014190046a2090016a220d2002209d016a29000037030020014190046a2088016a220e20022090016a290000370300200120022900083703900420042091016a2204ad20c2017e220620a00188a70d2a2006a722082091014c0d2a024002402008450d002008101b220f0d010c360b4108210f0b200f200220a1016a20081095032108209a012004360200200120043602dc07200120083602d8072001208b013602fc052001208c013602f805200141d8076a200141f8056a105402402004450d00200810190b200141a0056a209d016a22082005290300370300200141a0056a2090016a220f200d290300370300200141a0056a2088016a2210200e29030037030020012001290390043703a005209d01101b2204450d3520042090016a208e0129008ae24037000020042088016a208e01290082e2403700002004208e012900fae1403700002004209d0120c301101a2204450d36200420012903a005370018200420a6016a2008290300370000200420a1016a200f29030037000020042096016a2010290300370000208a0120890137030020012089013703c003200420c301200141c0036a1001208d01208a01290300370300200120012903c0033703e003200141e0036a209001208f01208e01208e011000209101460d0120012099013702d4032001200141e0036a3602d003200141d8076a200141d0036a105520012d00d8072203209b01460d37200141f8056a209801209c011095031a208a0120890137030020012089013703c003200420c301200141c0036a1001200141d0036a2088016a208a01290300370300200120012903c0033703d003200141d0036a2090011002200141b0046a200141f8056a209c011095031a200141e8066a200141b0046a209c011095031a20041019200141f0036a209d016a2005290300370300200141f0036a2090016a200d290300370300200141f0036a2088016a200e29030037030020012001290390043703f0030b2009450d020c010b200410192009450d010b200210190b2003209b01460d00200120033a00b004209301200141e8066a209c011095031a200141a0056a209d016a2211200141f0036a209d016a290300370300200141a0056a2090016a2212200141f0036a2090016a290300370300200141a0056a2088016a2213200141f0036a2088016a290300370300200120012903f0033703a005208a0120890137030020012089013703c003209f01209e01200141c0036a1001208d01208a01290300370300200120012903c0033703e00302400240024002400240200141e0036a209001208f01208e01208e011000209101460d0020012099013702fc052001200141e0036a3602f805200141d8076a200141f8056a105620012802d8072268450d2e20012902dc07220a20a00188a7220c20a1016c2208450d020c010b4200210a41082168420020a00188a7220c20a1016c2208450d010b410021104100210f206821030340200141d8076a209d016a22042011290300370300200141d8076a2090016a22092012290300370300209a012013290300370300200120012903a0053703d80720032088016a290000210620032090016a29000021072003290000210b209701209d016a22052003209d016a2900003700002097012090016a220d20073700002097012088016a220e2006370000209701200b37000020b701101b2202450d142002208b016a208e012800f3df4036000020022090016a208e012900ecdf4037000020022088016a208e012900e4df403700002002208e012900dcdf40370000200220b70120b801101a2202450d15200220012903d80737001b200220b9016a2004290300370000200220ba016a2009290300370000200220bb016a209a01290300370000200220b80120bc01101a2202450d16200220970129000037003b200220bd016a2005290000370000200220be016a200d290000370000200220bf016a200e290000370000200141d0036a2088016a220420890137030020012089013703d003200220c001200141d0036a100120014190046a2088016a2004290300370300200120012903d0033703900402400240024020014190046a209001208f01208e01208e011000209101470d004102210920021019410220a3017120b201470d010c020b2001208e013a00f80520014190046a209001200141f8056a209201208e0110002092016a2092014d0d1a20012d00f8052109200420890137030020012089013703d003200220c001200141d0036a1001208a012004290300370300200120012903d0033703c003200141c0036a209001100220021019200920a3017120b201460d010b20102009209201716a2110200f200920910173209201716a210f0b200320a1016a2103200820c1016a22080d000b200c200f6b2102200aa7450d020c010b4100210f41002110200c41006b2102200aa7450d010b206810190b200220106b210202400240024002400240024020012d00b00420a201470d00200141b0046a2088016a2d000020a3017120a201470d0020a501280200210320a701200236020020a901200f360200200141d8076a20a1016a201036020020950120012903a0053700002095012088016a20132903003700002095012090016a2012290300370000209501209d016a20112903003700002001208e013a00dc07200120aa013a00d807200141d8076a103d200f0d0120020d01200141d8076a20a4016a2003360200209a012094013a000020012094013a00d807200141d8076a103d2003104e0c010b20014190046a209d016a201129030037030020014190046a2090016a201229030037030020014190046a2088016a22092013290300370300200120012903a0053703900420a701200236020020a901200f360200200141d8076a20a1016a201036020020950120012903a0053700002095012088016a20132903003700002095012090016a2012290300370000209501209d016a201129030037000020012092013a00dc07200120aa013a00d807200141d8076a103d20102002200f6a4d0d0020ab01101b2203450d392003209d016a208e012800aae24036000020032090016a208e012900a2e24037000020032088016a208e0129009ae2403700002003208e01290092e240370000200320ab0120ac01101a2203450d3a200320012903a00537001c200320ad016a2011290300370000200320a8016a2012290300370000200320ae016a201329030037000042002106208a014200370300200142003703c003200320ac01200141c0036a1001200141d0036a2088016a2204208a01290300370300200120012903c0033703d003200141d0036a20900110022003101942002107200f450d02208a0120890137030020012089013703c00320b60120b501200141c0036a1001208d01208a01290300370300200120012903c0033703e003200141e0036a209001208f01208e01208e011000209101460d0120012089013703d807200141e0036a209001200141d8076a208801208e0110002092016a2088014d0d2a20012903d80721070c020b200141b0046a10430c020b420021070b200141f8056a200141b0046a20af011095031a208a014200370300200142003703c00320b10120b001200141c0036a10012004208a01290300370300200120012903c0033703d0030240200141d0036a209001208f01208e01208e011000209101460d0020012089013703d807200141d0036a209001200141d8076a208801208e0110002092016a2088014d0d1e20012903d80721060b208a0120890137030020012089013703c00320b40120b301200141c0036a10012004208a01290300370300200120012903c0033703d00302400240200141d0036a209001208f01208e01208e011000209101460d0020012089013703d807200141d0036a209001200141d8076a208801208e0110002092016a2088014d0d2020012903d807210b0c010b42e807210b0b200141d8076a200141f8056a20af011095031a20014190046a200b20067c200141d8076a20b2012092012002200f721b20071048200128029004209201470d0020012802940422020d010b208a0120890137030020012089013703c003208c01208b01200141c0036a1001208d01208a01290300370300200120012903c0033703e003200141e0036a209001208f01208e01208e011000209101470d470c010b2009280200210341cce2c000410f10042002200310040b200141d8076a105720012802e807220f450d04200141f0076a280200210220012802ec07211020012903e0072106024020012903d80722072000520d002002ad42287e220b422088a70d26200ba72203417f4c0d26024002402003450d002003101b22040d0120034108101c000b410821040b2004200f200241286c1095032103200141f0076a2002360200200141ec076a2002360200200141e8076a2003360200200141e0076a2006370300200141023a00d807200141d8076a103c0b024002400240200620077c2000520d002002ad42287e2206422088a70d282006a72203417f4c0d282003450d012003101b22040d0220034108101c000b2010450d06200f10190c060b410821040b2004200f200241286c22091095032103200141e4076a2002360200200141e0076a2002360200200120033602dc07200141093a00d807200141d8076a103d2002450d01200f20096a21c40141002104200f21020340200141d8076a41186a2208200241186a290300370300200141d8076a41106a2205200241106a290300370300200141d8076a41086a220d200241086a290300370300200120022903003703d807200241206a29030021062001410e3602b404200141edd7c1003602b004200141f8056a2004200141b0046a1034200141f8056a41086a280200210e20012802f80521094120101b2203450d27200320012903d807370000200341186a2008290300370000200341106a2005290300370000200341086a200d2903003700002003412041c000101a2203450d28200320063700202009200e20034128100320031019024020012802fc05450d00200910190b200441016a2104200241286a220220c401470d000b2010450d030c020b02400240024020e301450d0020c80120c40120d201746a210220c80120c40120e2016a20d201746a2103034020c40120cb014f0d2d200141f8056a20022802002204105820012903f80520d401520d02200141b0046a20d00120d5011095031a20c70120012903b00422075420c601200141b0046a20cf016a29030022065420c6012006511b450d0320e20120c4016a220420cb014f0d3120032002280200360200200220d6016a2102200320d6016a2103410121c90120cb0120c40120d3016a22c401470d000c090b0b20c80120c40120d201746a2102034020c40120cb014f0d2c200141f8056a20022802002204105820012903f80520d401520d01200141b0046a20d00120d5011095031a20c70120012903b00422075a20c601200141b0046a20cf016a29030022065a20c6012006511b0d02200220d6016a2102410121c90120cb0120c40120d3016a22c401470d000c070b0b20e20120e1016a21e20120e30120d3016a21e30120c40120d3016a22c40120cb01470d470c060b20c40120d3016a21c40120d701101b2202450d3d200220d8016a20d1012f00cae8403b0000200220cf016a20d1012900c2e840370000200220d1012900bae840370000200220d70120d901101a2202450d3e20c60120067d20c701200754ad7d21c60120c70120077d21c70120022004360012200141d0036a20cf016a220320da01370300200120da013703d003200220db01200141d0036a100120014190046a20cf016a2003290300370300200120012903d0033703900420014190046a20d801100220021019200141b0046a20d8016a2903002116200141b0046a20dc016a2903002115200141306a20ce011044200141306a20cf016a290300210b2001290330210a200141206a20ce01104520ce012016200a200a201656200b201556200b2015511b22021b221620012903207c22172015200b20021b2215200141206a20cf016a2903007c2017201654ad7c104620ce01200a20167d200b20157d200a201654ad7d1047200141106a20cd01104520cd012001290310220b20077c220a200141106a20cf016a29030020067c200a200b54ad7c10591a20dd01200637030020de012007370300200141d8076a20cf016a20d2013a000020df01200436020020cc0120cd0129000037000020cc0120cf016a20cd0120cf016a29000037000020cc0120d8016a20cd0120d8016a29000037000020cc0120dc016a20cd0120dc016a290000370000200120e0013a00d807200141d8076a103d20e20120e1016a21e20120e30120d3016a21e30120c40120cb01470d450c050b410021042010450d010b200f10190b2001410e3602fc05200141edd7c1003602f805200141d8076a41fbd7c100200141f8056a103b4100210d024020012802d807220220012802e007220341d889c200410041001000417f460d00200141003602f80520022003200141f8056a41044100100041016a41044d0d3320012802f805210d0b024020012802dc07450d00200210190b0240200d20044d0d00200141e0076a21052004210203402001410e3602fc05200141edd7c1003602f805200141d8076a41fbd7c100200141f8056a103b41002109024020012802d80722032005280200220841d889c200410041001000417f460d00200141003602f80520032008200141f8056a41044100100041016a41044d0d1720012802f80521090b024020012802dc07450d00200310190b200241016a21030240200920024d0d002001410e3602fc05200141edd7c1003602f805200141d8076a2002200141f8056a103420012802d80722022005280200100220012802dc07450d00200210190b20032102200d2003470d000b0b2001410e3602fc05200141edd7c1003602f805200141d8076a41fbd7c100200141f8056a103b20012802e007210320012802d8072102200120043602f80520022003200141f8056a41041003024020012802dc07450d00200210190b20014190046a41086a22024200370300200142003703900441bcdac100411d20014190046a1001200141d0036a41086a200229030037030020012001290390043703d003200141d0036a411010020b200141d0036a41086a22024200370300200142003703d00341f2ebc0004114200141d0036a1001200141c0036a41086a2002290300370300200120012903d0033703c00302400240200141c0036a411041d889c200410041001000417f460d00200142003703d807200141c0036a4110200141d8076a41084100100041016a41084d0d2620012903d80722064200510d36420021c50120002006824200520d040c010b420021c50120004201824200520d030b200141d0036a41086a220220c501370300200120c5013703d00341aee8c000410c200141d0036a1001200141c0036a41086a22032002290300370300200120012903d0033703c00302400240200141c0036a411041d889c200410041001000417f460d00200142003703e007200142003703d807200141c0036a4110200141d8076a4110410010002204417f460d382004410f4d0d38200141e0076a29030021c60120012903d80721c7010c010b420021c701420021c6010b200141f0076a20c601370300200141d8076a41106a20c701370300200141d8076a41086a41013a00002001410a3a00d807200141d8076a103d20024200370300200142003703d0034186ecc0004112200141d0036a100120032002290300370300200120012903d0033703c0030240200141c0036a411041d889c200410041001000417f460d00200142103702fc052001200141c0036a3602f805200141d8076a200141f8056a105a20012802d80722c801450d39200120012902dc0722063702ec06200120c8013602e806410021c901200141003602f0062006a721ca012006422088a722cb01450d01200141e1076a21cc01200141f0046a21cd01200141d0046a21ce01410821cf01200141f8056a41086a21d001410021d101410221d201410121d301420121d40141e00021d501410421d601411221d701411021d801412421d901420021da01411621db01411821dc0120014190086a21dd0120014188086a21de0120014184086a21df01410a21e001417f21e101410021e201410021c901410021e301410021c401410321680c570b410021cb01200141003602f006200142043703e806410421c801410021ca01410021c9010b410021e3010b200141f0066a20cb0120e3016b360200200141123602dc0720014186ecc0003602d807200141e8066a200141d8076a105b024020ca01450d0020c80110190b0240024020c90141ff0171450d0020c701213f0c010b4200213f200141d0036a41086a22724200370300200142003703d0034198ecc000410d200141d0036a1001200141c0036a41086a2072290300370300200120012903d0033703c0030240200141c0036a411041d889c200410041001000417f460d00200141003602d807200141c0036a4110200141d8076a41044100100041016a41044d0d3720013502d807213f0b200120c7014200203f4200109903200141e0076a41033a0000200141f0076a20c601420042edeb82bdef9804200129030042c0843d8020012903084200521b223f20c70156410020c601501b22721b2207370300200141e8076a20c701203f20721b22063703002001410a3a00d80720c70120067d213f20c60120077d20c701200654ad7d21c601200141d8076a103d0b200141f0076a20c601370300200141d8076a41106a203f370300200141d8076a41086a41043a00002001410a3a00d807200141d8076a103d200120c6013703e0072001203f3703d807200141d0036a41086a22724200370300200142003703d00341aee8c000410c200141d0036a1001200141c0036a41086a2072290300370300200120012903d0033703c003200141c0036a4110200141d8076a411010030b20014190046a41086a227220c501370300200120c5013703900441dadbc100411120014190046a1001200141d0036a41086a207229030037030020012001290390043703d003200141d0036a41101002200141c0036a41086a227220c501370300200120c5013703c00341b980c0004115200141c0036a1001200141e0036a41086a2072290300370300200120012903c0033703e0030240200141e0036a411041d889c200410041001000417f460d00200141003602d807200141e0036a4110200141d8076a41044100100041016a41044d0d2620012802d8072203450d0041002167034020672102411a101b2272450d16207241186a41002f00c3c8413b0000207241106a41002900bbc841370000207241086a41002900b3c841370000207241002900abc8413700002072411a4134101a2272450d172072200236001a20014190046a41086a2267420037030020014200370390042072411e20014190046a1001200141d0036a41086a206729030037030020012001290390043703d00302400240200141d0036a411041d889c200410041001000417f460d00200142003703e007200142003703d807200141d0036a4110200141d8076a4110410010002228417f460d152028410f4d0d15200141d8076a41086a290300213f20012903d80721062067420037030020014200370390042072411e20014190046a1001200141c0036a41086a206729030037030020012001290390043703c003200141c0036a41101002420121070c010b420021070b200241016a21672072101902402006203f84500d002007a7450d00200141d8076a41106a203f370300200141d8076a41086a2006370300200141d8076a41186a20023602002001410d3a00d807200141d8076a103d0b20032067470d000b0b200141d0086a24000f0b207522722075460d010b200141d8076a4101722103034020722d00002102200141d8076a207241016a41df001095031a2002410f460d01200141f8056a200141d8076a41df001095031a200120023a00d8072003200141f8056a41df001095031a02402002410e460d00200141d8076a10430b207241e0006a22722075470d000b0b2074450d4620731019410421020c550b200141d8076a200141f8056a20ea011095031a20012001280093043600b30420012001280290043602b004024020252022470d00202220e9016a22022022490d56202220e901742203200220022003491b2225ad20eb017e220620ec0188a70d562006a7220220ed01480d5602402022450d002021202220ee016c2002101a22210d010c360b2002101b2221450d350b2021202220ee016c6a200141d8076a20ea01109503220220ea016a20233a0000200220ef016a20012800b304360000200220e5016a20012802b004360000202220e9016a2122207020f001710d402024201f4f0d3f200141d8076a20241049024020f2012d000022232071470d000340202420e9016a2224201f4f0d40200141d8076a2024104920f2012d000022232071460d000b0b202420e9016a21022020200141d8076a20f1011095031a200120e80120716a2800003600a305200120e8012800003602a005200141e8066a200141b0046a20f3011095031a200120243602d80720e701200141e8066a20f3011095031a200141d8076a20ea016a20233a000020e60120012802a00536000020e60120716a220320012800a305360000024020f4012903002000520d00200141f8056a200141d8076a20ea011095031a2001200328000036009304200120e60128000036029004410021702002212420232071470d3d0c420b20e401104341032123410121702002212441032071470d3d0c420b41104101101c000b41204101101c000b41c0004101101c000b411b4101101c000b413b4101101c000b41f6004101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41e891c3001029000b41e891c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b411a4101101c000b41344101101c000b41fcf9c00041331030000b41114101101c000b41314101101c000b41114101101c000b41314101101c000b41fcf9c00041331030000b41fcf9c00041331030000b102b000b41204101101c000b41c0004101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41b8fdc20020c40120cb01104a000b41174101101c000b412e4101101c000b41fcf9c00041331030000b41c8fdc200200420cb01104a000b20084108101c000b41184101101c000b41384101101c000b41fcf9c00041331030000b411c4101101c000b413c4101101c000b20054108101c000b41fcf9c00041331030000b41174101101c000b412e4101101c000b41a0f1c2001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41124101101c000b41244101101c000b20024108101c000b410021680c120b410021680c120b410021680c120b410121680c130b410221680c140b410321680c150b410321680c150b410421680c150b410421680c150b410021020c150b410021020c140b410021020c130b410021020c120b410021020c110b410221020c100b410321020c0f0b410421020c0e0b410521020c0d0b410621020c0c0b410621020c0b0b410621020c0a0b410621020c090b410621020c080b410621020c070b410621020c060b410621020c050b410621020c040b410621020c030b410621020c020b410621020c010b410621020c000b0b101d000bdc0403027f017e0d7f230041d0006b22022400200241086a2001106802400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421b88a70d032004420586a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0006a24000f0b4101210620030d030b410021054100210d0c030b102b000b20054101101c000b200241306a41186a2107200241306a41106a2108200141046a21094100210a4100210b4100210c2003210d03402007420037030020084200370300200241306a41086a220e420037030020024200370330200141086a2205410020012802002009280200200241306a412020052802001000220f200f417f461b220f4120200f4120491b20052802006a360200200f411f4d0d02200c41016a2105200241106a41186a220f2007290300370300200241106a41106a22102008290300370300200241106a41086a2211200e290300370300200220022903303703100240200c200d470d00200a20052005200a491b220dad4205862204422088a70d042004a7220e4100480d040240200c450d002006200b200e101a22060d010c060b200e101b2206450d050b2006200b6a220c2002290310370000200c41186a200f290300370000200c41106a2010290300370000200c41086a2011290300370000200a41026a210a200b41206a210b2005210c20052003490d000b0b2000200d36020420002006360200200041086a2005360200200241d0006a24000f0b200041003602000240200d450d00200610190b200241d0006a24000f0b101d000b200e4101101c000bc80101037f024002400240024020022802042203417f4c0d00200228020021044101210202402003450d002003101b2202450d030b200220042003109503210520034101742204200341036a220220022004491b22044100480d01024002402003450d00200520032004101a2205450d010c050b2004101b22050d040b20044101101c000b102b000b101d000b20034101101c000b200020023602082000200436020420002005360200200520036a220320012f00003b0000200341026a200141026a2d00003a00000baa0905027f017e037f027e087f230041d0006b220124004108210242002103200141c0006a41086a220442003703002001420037034041fe81c000410d200141c0006a1001200141186a41086a22052004290300370300200120012903403703184100210602400240024002400240024002400240024002400240200141186a411041d889c200410041001000417f460d002001421037020c2001200141186a360208200141c0006a200141086a105c20012802402202450d0520012902442103200141186a41206a200041206a290300370300200141186a41186a200041186a290300370300200141186a41106a200041106a290300370300200141186a41086a200041086a290300370300200120002903003703182003422088a722062003a7470d02200141186a210020062003a7460d010c070b200141186a41206a200041206a290300370300200141186a41186a200041186a290300370300200141186a41106a200041106a2903003703002005200041086a29030037030020012000290300370318200141186a210041004200a7470d060b200641016a22042006490d0720064101742205200420042005491bad220742287e2208422088a70d072008a722044100480d072006450d012002200641286c2004101a2202450d020c040b200141186a21000c050b2004101b22020d020b20044108101c000b41fcf9c00041331030000b20034280808080708320078421030b2003422088a721060b2002200641286c22056a22042000290300370300200441206a200041206a290300370300200441186a200041186a290300370300200441106a200041106a290300370300200441086a200041086a29030037030020014100360248200142013703402001200641016a2209360218200141186a200141c0006a105d024002402009450d00200541286a210a200141c0006a41086a220b28020021002001280244210c200221050340200141186a2005105e2001280218210d0240024002400240200c20006b200141186a41086a280200220e4f0d002000200e6a22042000490d07200c410174220f20042004200f491b22104100480d07200c450d012001280240200c2010101a220f0d020c080b2000200e6a21042001280240210f0c020b2010101b220f450d060b200120103602442001200f3602402010210c0b200b2004360200200f20006a200d200e1095031a0240200128021c450d00200d10190b200541286a210520042100200a41586a220a0d000c020b0b200141c0006a41086a28020021042001280244210c2001280240210f0b200141c0006a41086a220042003703002001420037034041fe81c000410d200141c0006a1001200141186a41086a200029030037030020012001290340370318200141186a4110200f200410030240200c450d00200f10190b02402009450d00200641286c41286a2104200221000340024020002d00002205450d00024020054101470d00200041086a280200450d01200041046a2802001019200041286a2100200441586a22040d020c030b200041146a280200450d00200041106a28020010190b200041286a2100200441586a22040d000b0b02402003a7450d00200210190b200141d0006a24000f0b101d000b20104101101c000bde1303067f017e167f230041d0026b2201240002400240024002400240024002400240024002400240024002400240419384c000411041d889c200410041001000417f460d002001410036028801419384c000411020014188016a41044100100041016a41044d0d022001280288012102410021030c010b410121030b41082104200141f8016a41086a22054200370300200142003703f80141ed82c000410d200141f8016a1001200141106a41086a2005290300370300200120012903f801370310024002400240200141106a411041d889c200410041001000417f460d00200142103702242001200141106a360220200141086a200141206a10682001280208450d07200128020c2206ad42f8007e2207422088a70d042007a72205417f4c0d042005450d012005101b2204450d052006450d020c060b41002115410021110c070b4108210420060d040b41002111410021152004450d040c050b41fcf9c00041331030000b102b000b20054108101c000b20014188016a411c6a210820014188016a4101722109200141206a41086a210a20014188016a410c6a210b20014188016a41106a210c20014188016a41146a210d20014188016a41186a210e4100210f41002110410021052006211102400340200141003a00f801200a200a28020022122001280220221320012802242214200141f8016a41012012100041016a41014b22126a22153602002012450d0141012116024020012d00f80122124101460d0020120d022001410036028801200a41002013201420014188016a41042015100022122012417f461b2212410420124104491b20156a360200201241034d0d022001280288012117410021160b20014188016a200141206a1069200141cc026a41026a2213200941026a2d00003a0000200120092f00003b01cc0220014188016a41086a2802002114200b2802002118200c2802002119200d280200211a200e280200211b200128028c01211c20012d0088012112200141f8016a200841d4001095031a2012410e460d01200541016a211520014184016a41026a221d20132d00003a0000200120012f01cc023b018401200141306a200141f8016a41d4001095031a200141f8016a41026a2213201d2d00003a0000200120012f0184013b01f80120014188016a200141306a41d4001095031a024020052011470d00200f20152015200f491b2211ad42f8007e2207422088a70d072007a7221d4100480d0702402005450d0020042010201d101a22040d010c060b201d101b2204450d050b200420106a220520123a0000200541186a201b360200200541146a201a360200200541106a20193602002005410c6a2018360200200541086a2014360200200541046a201c360200200541036a20132d00003a0000200541016a20012f01f8013b00002005411c6a20014188016a41d4001095031a200541f4006a2017360200200541f0006a2016360200200f41026a210f201041f8006a21102015210520152006490d000c030b0b02402005450d00200441186a2101034002400240200141686a2d000022054109460d00024020054106460d0020054105470d02200141706a2d00004101470d022001417c6a280200450d02200141786a2802001019200141f8006a2101201041887f6a22100d030c040b2001416c6a2d00004103470d010240200141746a280200450d00200141706a28020010190b2001280200450d012001417c6a2802001019200141f8006a2101201041887f6a22100d020c030b200141706a280200450d002001416c6a28020010190b200141f8006a2101201041887f6a22100d000b0b2011450d00200410190b41fcf9c00041331030000b20014188016a200041f0001095031a20112015470d01201541016a22052015490d0220154101742210200520052010491b2211ad42f8007e2207422088a70d022007a722054100480d02024002402015450d002004201541f8006c2005101a2204450d010c030b2005101b22040d020b20054108101c000b201d4108101c000b2004201541f8006c22106a20014188016a41f000109503220541f4006a200236020020052003360270200141003602900120014201370388012001201541016a22093602f801200141f8016a20014188016a105d02402009450d00201041f8006a211220014190016a21102004210503400240024002400240024002400240024002400240200541f0006a2802004101470d00200141013a00f801200128028c012010280200220f470d01200f41016a220a200f490d0c200f4101742216200a200a2016491b22164100480d0c200f450d03200128028801200f2016101a220a0d040c0d0b200141003a00f801200128028c012010280200220f470d01200f41016a220a200f490d0b200f4101742216200a200a2016491b22164100480d0b200f450d05200128028801200f2016101a220a0d060c0d0b41012116200128028801210a0c030b41002116200128028801210a0c050b2016101b220a450d090b2001201636028c012001200a360288012010280200210f20012d00f80121160b2010200f41016a360200200a200f6a20163a00000c030b2016101b220a450d070b2001201636028c012001200a360288012010280200210f20012d00f80121160b2010200f41016a360200200a200f6a20163a0000200541f4006a28020021160240024002400240200128028c01220a2010280200220f6b41044f0d00200f41046a2217200f490d07200a410174220f20172017200f491b220f4100480d07200a450d01200128028801200a200f101a220a0d020c0a0b200128028801210a0c020b200f101b220a450d080b2001200f36028c012001200a360288012010280200210f0b2010200f41046a360200200a200f6a20163600000b200520014188016a106a200541f8006a2105201241887f6a22120d000b0b20014188016a41086a2210280200210f200128028c0121122001280288012105200141f8016a41086a220a4200370300200142003703f80141ed82c000410d200141f8016a10012010200a290300370300200120012903f8013703880120014188016a41102005200f100302402012450d00200510190b02402009450d00201541f8006c41f8006a211241002105034002400240200420056a22102d0000220f4109460d000240200f4106460d00200f4105470d02201041086a2d00004101470d02201041146a280200450d02201041106a28020010192012200541f8006a2205470d030c040b201041046a2d00004103470d0102402010410c6a280200450d00201041086a28020010190b201041186a280200450d01201041146a28020010192012200541f8006a2205470d020c030b201041086a280200450d00201041046a28020010190b2012200541f8006a2205470d000b0b02402011450d00200410190b200141d0026a24000f0b101d000b20164101101c000b20164101101c000b200f4101101c000bc4510d017f017e017f047e027f017e0b7f027e047f057e027f017e127f230041a0046b220224000240024002400240024002400240024002400240024002400240024002402001450d00200241f0036a41086a22014200370300200242003703f00341a099c1004115200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003200241e0036a411041d889c200410041001000417f460d01200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0320022903f00221030c020b200241e0036a21040c050b420521030b200241f0036a41086a22014200370300200242003703f00341d1fbc0004115200241f0036a1001200241f0026a41086a2001290300370300200220022903f0033703f00202400240200241f0026a411041d889c200410041001000417f460d00200242003703f003200241f0026a4110200241f0036a41084100100041016a41084d0d034200210520022903f00320037e22034200510d010c060b4200210542e80720037e22034200520d050b200241f0036a41086a22012005370300200220053703f00341e3dac000411c200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e0030240200241e0036a411041d889c200410041001000417f460d00200242003703f802200242003703f002200241e0036a4110200241f0026a4110410010002201417f460d032001410f4d0d03200241f8026a290300210720022903f00221050c060b420021070c050b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b410121010c070b2000200320032000541b22062005510d0242002100200241f0036a41086a22014200370300200242003703f00341e3dac000411c200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e0032003421086200680210302400240200241e0036a411041d889c200410041001000417f460d00200242003703f802200242003703f002200241e0036a4110200241f0026a4110410010002201417f460d032001410f4d0d03200241f8026a290300210620022903f00221000c010b420021060b200241e0026a200020062003420010990320022903e002421088200241e8026a2903002200423086842105200042108821070b42002108200241f0036a41086a22014200370300200242003703f0034181fcc0004112200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e00302400240200241e0036a411041d889c200410041001000417f460d00200242103702f4032002200241e0036a3602f003200241f0026a200241f0036a103a20022802f0022209450d0420022902f40221080c010b410121090b4105210a2008422088220ba74105742201450d03200920016a210c4120210d411c210e4118210f410021104110211141082112413c211341342114412c2115412421164201211742002118416021192009211a4100211b0c040b41fcf9c00041331030000b41b8e3c2001029000b41fcf9c00041331030000b410021010c010b410221010b02400240024002400240024002400240024002400340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e03000107070b20024190016a20052007200b420010990320024188036a2007370300200241f0026a41106a2005370300200241f0026a41086a41003a0000200241043a00f002200241f0026a103d200241f0036a41086a22014200370300200242003703f00341ffdac0004112200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003200241e0036a411041d889c200410041001000210120024190016a41086a29030021002002290390012103024002402001417f460d00200242003703f802200242003703f002200241e0036a4110200241f0026a4110410010002201417f460d0320014110490d03200242003703f802200242003703f002200241e0036a4110200241f0026a4110411010002201417f460d032001410f4d0d03200241f8026a290300210620022903f002211d0c010b4200211d420021060b20024180016a201d2006200b420010990302402003200084500d00200229038001220620024180016a41086a290300222484500d004200211d200241f0036a41086a22014200370300200242003703f00341a7fbc0004116200241f0036a1001200241e0036a41086a221c2001290300370300200220022903f0033703e00302400240200241e0036a411041d889c200410041001000417f460d00200242003703f802200242003703f002200241e0036a4110200241f0026a4110410010002223417f460d072023410f4d0d07200241f8026a290300212120022903f002211f0c010b4200211f420021210b200241f0006a201f20067d202120247d201f200654ad7d20062024109803200241e0006a2002290370200241f0006a41086a2903002003200010990320014200370300200242003703f00341aee8c000410c200241f0036a1001201c2001290300370300200220022903f0033703e003200241e0036a411041d889c2004100410010002101200241e0006a41086a290300210320022903602106024002402001417f460d00200242003703f802200242003703f002200241e0036a4110200241f0026a4110410010002201417f460d082001410f4d0d08200241f8026a290300210020022903f002211d0c010b420021000b2002201d20067c22063703f0022002200020037c2006201d54ad7c3703f802200241f0036a41086a22014200370300200242003703f00341aee8c000410c200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003200241e0036a4110200241f0026a411010030b200241e0036a21042008a7450d1120091019410121010c150b200241f0036a41086a22014200370300200242003703f00341bdfbc0004114200241f0036a1001200241e0036a41086a22252001290300370300200220022903f0033703e00342002100024002400240024002400240024002402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0120022903f00221000b20014200370300200242003703f00341accbc0004115200241f0036a100120252001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200241f0036a41086a22014200370300200242003703f00341accbc0004115200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003200241e0036a411010020c010b200241f0036a41086a22014200370300200242003703f0034191dbc000411b200241f0036a1001200241e0036a41086a22252001290300370300200220022903f0033703e0034200210302402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0620022903f00221030b20014200370300200242003703f00341acdbc0004116200241f0036a100120252001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0820022903f00222064200520d0141d0e3c2001029000b42e80721060b200020037d2006824200520d1f0b200241f0036a41086a22014200370300200242003703f00341c2dbc0004112200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0320022903f00242017c21000c010b420121000b200220003703f002200241f0036a41086a22014200370300200242003703f00341c2dbc0004112200241f0036a1001200241e0036a41086a22252001290300370300200220022903f0033703e00320044110200241f0026a4108100320014200370300200242003703f00341d4dbc000411a200241f0036a100120252001290300370300200220022903f0033703e00302402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d03200220022903f002220037039004200241f0036a41086a22014200370300200242003703f00341acdbc0004116200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d06200020022903f002520d010c020b200042e807510d010b200220003703f002200241f0036a41086a22014200370300200242003703f00341acdbc0004116200241f0036a1001200241e0036a41086a22252001290300370300200220022903f0033703e00320044110200241f0026a4108100320014200370300200242003703f00341bdfbc0004114200241f0036a100120252001290300370300200220022903f0033703e0034200210002402004411041d889c200410041001000417f460d00200242003703f002200241e0036a4110200241f0026a41084100100041016a41084d0d0820022903f00221000b200220003703f00220014200370300200242003703f0034191dbc000411b200241f0036a100120252001290300370300200220022903f0033703e00320044110200241f0026a410810030b200241f0036a41086a22014200370300200242003703f00341e2c9c0004112200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e00302400240024002402004411041d889c200410041001000417f460d00200242103702f4032002200241e0036a3602f003200241f0026a200241f0036a103a20022802f0022226450d0c20022802f40221274105212541002128200241f8026a2802004105742201450d020c010b4101212641002127410521254100212841004105742201450d010b20012025752229ad42307e2200422088a70d212000a722254100480d212025101b222a450d0b202620016a222b2026470d010c0f0b4108212a41002129202620016a222b2026460d0e0b410021284118212c4110212d410821254120212e4128212f41012130413021314105213241602133202a2134202621354101211b0c190b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b20254108101c000b41fcf9c00041331030000b41fcf9c00041331030000b02400240201b0e020001010b201a450d0a200e101b2201450d022001200f6a20102800a9ca40360000200120116a20102900a1ca40370000200120126a2010290099ca4037000020012010290091ca403700002001200e2013101a2201450d032001201a29000037001c200120146a201a200f6a290000370000200120156a201a20116a290000370000200120166a201a20126a290000370000200241f0026a2001201310ba01200241f0026a20126a221c2903002103200241f0026a20116a290300210620022903f002211d20011019420021000240024002400240200520034200201d20175122011b2203200520032005542006420020011b220320075420032007511b22011b221e7d221f20072003200720011b22207d2005201e54ad7d222184500d00200241f0026a201a10ae01201c280200210120022802f0022122200241d0026a201a1045200241d0026a20126a290300210020022903d0022103200241c0026a201a10442000200241c0026a20126a2903007c200320022903c00222007c2206200054ad7c21032001450d012001200a74221c2123202221010340200241b0026a20011045200241b0026a20126a290300211d20022903b0022100200241a0026a20011044201d20037c200020067c2203200054ad7c200241a0026a20126a2903007c200320022903a0027c2206200354ad7c21032001200d6a2101202320196a22230d000b20032018200620175620032018522003501b22011b211d2006201720011b212420222101034020024190026a2001104520024190026a20126a2903002100200229039002210320024180026a20011044200241f0016a200320022903800222067c2203200020024180026a20126a2903007c2003200654ad7c201f2021109903200241e0016a20022903f001200241f0016a20126a2903002024201d109803200120022903e001200241e0016a20126a29030010bb012001200d6a2101201c20196a221c0d000c030b0b420021060c020b20032018200620175620032018522003501b22011b211d2006201720011b21240b200241d0016a201a1045200241d0016a20126a290300210020022903d0012103200241c0016a201a10442024201d842018510d05200241b0016a20022903c001220620037c2203200241c0016a20126a29030020007c2003200654ad7c201f2021109903200241a0016a20022903b001200241b0016a20126a2903002024201d109803200241a0016a20126a290300210620022903a001210020022802f402450d00202210190b201a2000201e7c2203200620207c2003200054ad7c10bb01201a200d6a2201211a2001200c470d08410021010c0f0b200241f0026a202c6a221b2035202c6a290000370300200241f0026a202d6a22222035202d6a290000370300200241f0026a20256a2236203520256a290000370300200220352900003703f002200241e0036a200241f0026a10ac01200241e0036a20256a280200210120022802e0032123200241d0006a200241f0026a1045200241d0006a20256a290300210020022903502103200241c0006a200241f0026a10442000200241c0006a20256a2903007c2003200229034022007c2206200054ad7c210302402001450d002001203274211c202321010340200241306a20011045200241306a20256a290300211d20022903302100200241206a20011044201d20037c200020067c2203200054ad7c200241206a20256a2903007c200320022903207c2206200354ad7c21032001202e6a2101201c20336a221c0d000b0b2035202e6a2135024020022802e403450d00202310190b200241f0036a202c6a2201201b290300370300200241f0036a202d6a221c2022290300370300200241f0036a20256a22232036290300370300200220022903f0023703f00320342003370308203420063703002034202f6a20012903003703002034202e6a201c2903003703002034202c6a2023290300370300203420022903f003370310202820306a2128203420316a21342035202b470d080b02402027450d00202610190b200241f0036a41086a22014200370300200242003703f00341f4c9c000411d200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200241003602f002200241e0036a4110200241f0026a41044100100041016a41044d0d05202820022802f0024f0d010c110b20284104490d100b4100211c202a2028410041202028676b10bc01200241f0036a41086a22014200370300200242003703f00341eedbc0004116200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e00302402004411041d889c200410041001000417f460d00200241003602f002200241e0036a4110200241f0026a41044100100041016a41044d0d0520022802f002211c0b024002402028450d0020282028201c201c20284b1b417f6a22014d0d07202a41086a2903002100202a200141306c6a22012903002106200141086a2903002103202a290300211d411021124110101b2201450d010c100b4200211d420021004200210642002103411021124110101b22010d0f0b20124101101c000b411c4101101c000b413c4101101c000b41b8e3c2001029000b41fcf9c00041331030000b41fcf9c00041331030000b41e8e3c20020012028104a000b4100211b0c030b4101211b0c040b410021010c040b410121010c030b410221010c020b410221010c010b410221010c000b0b2001201d370000200120003700080240024002400240200120124120101a2201450d0020012006370010200141186a2003370000200241f0036a41086a22124200370300200242003703f00341ffdac0004112200241f0036a1001200241e0036a41086a2012290300370300200220022903f0033703e003200441102001412010032001101902400240201c450d0041002134201c202a202841306c6a2212202a6b41306d22012001201c4b1b2226450d012026ad4205862200422088a70d082000a722014100480d082001101b2235450d03201c450d050c040b4100212641012135410021340c040b4101213541002126201c0d020c030b41204101101c000b20014101101c000b2012202a460d00202841306c2133200241f0026a41106a21254101210d20352112202a21010340200241f0026a41286a200141286a290300370300200241f0026a41206a200141206a290300370300200241f0026a41186a200141186a2903003703002025200141106a290300370300200241f0026a41086a200141086a290300370300200241f0036a41086a2219202541086a290300370300200241f0036a41106a2223202541106a290300370300200241f0036a41186a222e202541186a290300370300200220012903003703f002200220252903003703f003201241186a202e290300370000201241106a2023290300370000201241086a2019290300370000201220022903f003370000201c200d2234460d01200141306a2101203441016a210d201241206a2112203341506a22330d000b0b02402029450d00202a10190b4200211d200241f0036a41086a22014200370300200242003703f0034181fcc0004112200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e0030240024002402004411041d889c200410041001000417f460d00200242103702f4032002200241e0036a3602f003200241f0026a200241f0036a103a20022802f0022228450d0220022902f402211d0c010b410121280b02400240024002400240201d422088a7410574222e450d0020282112034002400240024002400240411c101b2201450d00200141186a41002800fdcb40360000200141106a41002900f5cb40370000200141086a41002900edcb40370000200141002900e5cb403700002001411c413c101a2201450d012001201229000037001c200141346a201241186a220d2900003700002001412c6a201241106a2219290000370000200141246a201241086a2223290000370000200241f0036a41086a221c4200370300200242003703f0032001413c200241f0036a1001200241e0036a41086a2225201c290300370300200220022903f0033703e003200241e0036a41101002200110194112101b2201450d02200141106a41002f0082c94022333b0000200141086a41002900fac8402200370000200141002900f2c8402203370000200141124132101a2201450d03200120122900003700122001412a6a200d290000370000200141226a20192900003700002001411a6a202329000037000020254200370300200242003703e00320014132200241e0036a1001200241f0026a41086a2025290300370300200220022903e0033703f002024002400240200241f0026a411041d889c200410041001000417f460d00200241003602f003200241f0026a4110200241f0036a41044100100041016a41044d0d0220022802f003211a20254200370300200242003703e00320014132200241e0036a1001201c2025290300370300200220022903e0033703f003200241f0036a4110100220011019201a410041011b221a4102490d010c070b200110194100410041001b221a41024f0d060b201241206a2112202e41606a222e0d060c070b41fcf9c00041331030000b411c4101101c000b413c4101101c000b41124101101c000b41324101101c000b4112101b2201450d02200141106a20333b0000200141086a200037000020012003370000200141124132101a2201450d03200120122900003700122001412a6a200d290000370000200141226a20192900003700002001411a6a20232900003700002002201a417f6a3602f002201c4200370300200242003703f00320014132200241f0036a10012025201c290300370300200220022903f0033703e00320044110200241f0026a4104100320011019201241206a2112202e41606a222e0d000b0b0240201da7450d00202810190b02400240024002402034450d0020344105742125203521010340200241f0026a200110ac01411c101b2212450d03201241186a41002800fdcb40360000201241106a41002900f5cb40370000201241086a41002900edcb40370000201241002900e5cb403700002012411c413c101a2212450d042012200129000037001c201241346a200141186a2900003700002012412c6a200141106a290000370000201241246a200141086a2900003700002002413c3602f403200220123602f003200241f0026a200241f0036a10980120121019024020022802f402450d0020022802f00210190b200141206a2101202541606a22250d000b2035203410bd010c010b2035410010bd010b200241f0036a41086a22014200370300200242003703f0034184dcc0004114200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200241003602f002200241e0036a4110200241f0026a41044100100041016a41044d0d0620023502f00221000c010b42c0843d21000b200241106a2006420020004200109903200242003703f80220024289f48bdcc4002002290310428094ebdc038020022903184200521b3703f002200241f0036a41086a22014200370300200242003703f00341c7c9c000411b200241f0036a1001200241e0036a41086a22122001290300370300200220022903f0033703e00320044110200241f0026a4110100320014200370300200242003703f0034198dcc0004115200241f0036a100120122001290300370300200220022903f0033703e003024002402004411041d889c200410041001000417f460d00200241003602f002200241e0036a4110200241f0026a41044100100041016a41044d0d0720023502f00221000c010b423c21000b20022006420020004200109903200242003703f80220024289f48bdcc4002002290300428094ebdc038020022903084200521b3703f002200241f0036a41086a22014200370300200242003703f00341e3dac000411c200241f0036a1001200241e0036a41086a2001290300370300200220022903f0033703e00320044110200241f0026a411010032026450d08203510190c080b411c4101101c000b413c4101101c000b41124101101c000b41324101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b2029450d00202a10190b42002100200241e0036a41086a22014200370300200242003703e0034181fcc0004112200241e0036a1001200241f0026a41086a2001290300370300200220022903e0033703f0020240024002400240024002400240200241f0026a411041d889c200410041001000417f460d00200242103702e4032002200241f0026a3602e003200241f0036a200241e0036a103a20022802f0032223450d0220022902f40321000c010b410121230b4100211c024002402000422088a722124105742201450d0020014105752228ad42287e2203422088a70d072003a722254100480d072025101b221a450d032000a7212e202320016a2023460d010c040b4108211a410021282000a7212e202320016a2023470d030b202e450d040c030b41fcf9c00041331030000b20254108101c000b20124105742125201241057441606a4105762104201a2101202321120340200241f0036a41186a201241186a2900002200370300200241f0036a41106a201241106a2900002203370300200241f0036a41086a201241086a2900002206370300200241f0026a41186a221c2000370300200241f0026a41106a220d2003370300200241f0026a41086a221920063703002002201229000022003703f003200220003703f002200141186a201c290300370000200141106a200d290300370000200141086a2019290300370000200120022903f002370000200141206a4201370300200141286a2101201241206a2112202541606a22250d000b200441016a211c202e450d010b202310190b2002410e3602f403200241edd7c1003602f003200241f0026a41fbd7c100200241f0036a103b41002101024020022802f002221220022802f802222541d889c200410041001000417f460d00200241003602f00320122025200241f0036a41044100100041016a41044d0d0220022802f00321010b024020022802f402450d00201210190b20024190046a200110be0120022802900421350240024002400240024002400240201c200228029804470d002035201a460d01417f2125201a2101203521120340202541016a2225201c4f0d022001201241201097030d01201241206a210d200141206a2119200141286a2101201241286a21122019290300200d290300510d000b0b200241f0026a10572002280280032201450d01200228028403450d022001101920280d030c040b0240200228029404450d00203510190b2028450d04201a10190c040b42002100200241e0036a41086a22014200370300200242003703e003419c82c000410d200241e0036a1001200241f0026a41086a2001290300370300200220022903e0033703f0020240200241f0026a411041d889c200410041001000417f460d00200242003703f003200241f0026a4110200241f0036a41084100100041016a41084d0d0920022903f00321000b200241003602f802200242013703f0024108101b2201450d092002428880808080013702f402200220013602f00220012000370000200141084110101a2201450d0a2002429080808080023702f40220014200370008200220013602f0022002201c3602f003200241f0036a200241f0026a105d02400240201c450d00201a201c41286c6a21344160200241f0026a41086a2204280200222e6b210d20022802f4022125410021010340202e20016a211902400240024002402025200d6a221241206a20124f0d00201941206a22122019490d0b2025410174221c20122012201c491b22124100480d0b2025450d0120022802f00220252012101a221c0d020c0d0b20022802f002211c0c020b2012101b221c450d0b0b200220123602f4022002201c3602f002201221250b2004201941206a2233360200201c202e6a20016a222341186a201a20016a221241186a290000370000202341106a201241106a290000370000202341086a201241086a29000037000020232012290000370000201241206a290300210002402025200d6a41074b0d00203341086a22232033490d0820254101742233202320232033491b22234100480d08024002402025450d00201c20252023101a221c0d010c0d0b2023101b221c450d0c0b200220233602f4022002201c3602f002202321250b2004201941286a360200201c202e6a20016a41206a2000370000200d41586a210d200141286a21012034201241286a470d000b202e20016a21010c010b200241f8026a280200210120022802f402212520022802f002211c0b200241e0036a41086a22124200370300200242003703e00341bcdac100411d200241e0036a1001200241f0036a41086a2012290300370300200220022903e0033703f003200241f0036a4110201c200110032025450d00201c10190b2028450d010b201a10190b200228029404450d0020351019200241a0046a24000f0b200241a0046a24000f0b101d000b41fcf9c00041331030000b20124101101c000b20234101101c000b41fcf9c00041331030000b41084101101c000b41104101101c000be10703037f017e067f230041c0006b22012400200141306a41086a220242003703002001420037033041d082c000411d200141306a1001200141106a41086a2002290300370300200120012903303703100240024002400240024002400240200141106a411041d889c200410041001000417f460d00200142103702042001200141106a360200200141306a2001103a20012802302202450d0402402001280234450d00200210190b20002802002202450d01200041046a280200450d0120021019200141c0006a24000f0b0240024020002802002203450d00200029020421040c010b20014106360234200141e481c000360230200141106a41fbd7c100200141306a103b410021050240200128021022002001280218220241d889c200410041001000417f460d002001410036023020002002200141306a41044100100041016a41044d0d06200128023021050b02402001280214450d00200010190b024002402005450d002005ad4205862204422088a70d042004a722004100480d042000101b2203450d0841002102200321000340200141106a20021033200041186a200141106a41186a290000370000200041106a200141106a41106a290000370000200041086a200141106a41086a29000037000020002001290010370000200041206a21002005200241016a2202470d000c020b0b410121030b2005ad220442208620048421040b200141003602182001420137031020012004422088a72200360230200141306a200141106a105d024002402000450d00200041057421064100200141106a41086a28020022026b210720012802102108200128021421092003210003400240200920076a411f4b0d00200241206a22052002490d052009410174220a20052005200a491b22054100480d05024002402009450d00200820092005101a22080d010c080b2005101b2208450d070b200521090b200820026a22052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200741606a2107200241206a2102200041206a2100200641606a22060d000b200141186a200236020020012009360214200120083602100c010b200141186a280200210220012802142109200128021021080b200141306a41086a220042003703002001420037033041d082c000411d200141306a1001200141106a41086a200029030037030020012001290330370310200141106a411020082002100302402009450d00200810190b2004a7450d00200310190b200141c0006a24000f0b101d000b20054101101c000b41fcf9c00041331030000b41fcf9c00041331030000b20004101101c000bb10803027f017e107f230041d0036b22022400200241086a2001106802400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421988a70d032004420786a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0036a24000f0b4108210620030d030b4100210f4100210d0c030b102b000b20054108101c000b200241a0026a4101722107200141086a2108200241306a41186a2109200241306a41106a210a4100210b4100210c410021052003210d0340200141046a220e280200210f20082802002110200241003602f802200841002001280200200f200241f8026a410420101000220f200f417f461b220f4104200f4104491b20082802006a36020002400240200f41034d0d0020022802f8022111200241f8026a2001105520022d00f802410e460d00200241a0026a200241f8026a41d8001095031a20094200370300200a4200370300200241306a41086a2210420037030020024200370330200841002001280200200e280200200241306a412020082802001000220f200f417f461b220f4120200f4120491b20082802006a3602000240200f411f4d0d0020024188016a41186a200929030037030020024188016a41106a200a29030037030020024188016a41086a2010290300370300200220022903303703880120022d00a0022110200241a9016a200741d7001095031a201121120c020b200241a0026a10620b410e21100b200241f8026a200241a9016a41d7001095031a20024180026a41186a220e20024188016a41186a29030037030020024180026a41106a221120024188016a41106a29030037030020024180026a41086a221320024188016a41086a290300370300200220022903880137038002201041ff0171410e460d02200541016a210f200241306a200241f8026a41d7001095031a200241106a41186a2214200e290300370300200241106a41106a220e2011290300370300200241106a41086a22112013290300370300200220022903800237031002402005200d470d00200b200f200f200b491b220dad4207862204422088a70d042004a722134100480d0402402005450d002006200c2013101a22060d010c060b2013101b2206450d050b2006200c6a220520103a0000200541016a200241306a41d7001095031a200541d8006a2012360000200541f4006a2014290300370000200541ec006a200e290300370000200541e4006a2011290300370000200541dc006a2002290310370000200b41026a210b200c4180016a210c200f2105200f2003490d000b0b2000200d36020420002006360200200041086a200f360200200241d0036a24000f0b2000410036020002402005450d002006210503402005104320054180016a2105200c41807f6a220c0d000b0b0240200d450d00200610190b200241d0036a24000f0b101d000b20134108101c000bf00202027f037e230041306b22022400024002404113101b2203450d002003410f6a41002800bf9f41360000200341086a41002900b89f41370000200341002900b09f41370000200341134126101a2203450d0120032001360013200241206a41086a220142003703002002420037032020034117200241206a1001200241086a2001290300370300200220022903203703000240024002402002411041d889c200410041001000417f460d00200220023602102002411036021420024200370328200242003703202002410020024110200241206a41104100100022012001417f461b2201411020014110491b3602182001410f4d0d02200241286a290300210420022903202105200241206a200241106a103a20022802202201450d02200229022421062000200437030820002005370300200020063702140c010b410021010b2000200136021020031019200241306a24000f0b41fcf9c00041331030000b41134101101c000b41264101101c000bfe0401077f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d024002400240024002402000450d0020004107742104200241106a41086a22052802002100200228021421060340200341d8006a28020021070240024002400240200620006b41044f0d00200041046a22082000490d0720064101742200200820082000491b22004100480d072006450d01200228021020062000101a22060d020c080b200228021021060c020b2000101b2206450d060b2002200036021420022006360210200528020021000b2005200041046a360200200620006a20073600002003200241106a1064024002400240024020022802142206200528020022076b41204f0d00200741206a22002007490d0720064101742207200020002007491b22004100480d072006450d01200228021020062000101a22080d020c090b200228021021080c020b2000101b2208450d070b200220003602142002200836021020052802002107200021060b2005200741206a2200360200200820076a220741086a200341e4006a290000370000200741106a200341ec006a290000370000200741186a200341f4006a2900003700002007200341dc006a29000037000020034180016a2103200441807f6a22040d000c020b0b200241186a280200210020022802142106200228021021080b2001280204210320012802002107200241106a41086a220542003703002002420037031020072003200241106a1001200241086a2005290300370300200220022903103703002002411020082000100302402006450d00200810190b200241206a24000f0b101d000b20004101101c000b20004101101c000b920501027f024002400240024002400240024002400240024002400240024002400240024020002d00002201410c4b0d0020010e0d0f010f0f0f0203040506070f080f0b200041046a2802004102470d0e200041086a22002802001043200028020010190f0b200041086a280200220141064b0d0a024020010e070e0e000e0c0e0d0e0b200041106a280200450d0d2000410c6a28020010190f0b200041086a2d0000410c490d0c200041106a280200450d0c2000410c6a28020010190f0b200041086a2d000022014105460d0520014102470d0b2000410c6a22002802001043200028020010190f0b200041086a2802004102470d0a200041106a280200450d0a2000410c6a28020010190f0b200041086a2d00004102470d092000410c6a22002802001043200028020010190f0b200041046a2d00004102470d082000410c6a22002802001043200028020010190f0b200041046a2802004102490d072000410c6a280200450d07200041086a28020010190f0b200041086a2d000022014103490d0620014104460d0120014103470d02200041106a280200450d062000410c6a28020010190f0b2000410c6a22002802001043200028020010190f0b200041346a280200450d04200041306a28020010190f0b200041306a280200450d032000412c6a28020010190f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141186a2101200241686a22020d000b0b200041106a280200450d022000410c6a28020010190f0b200041106a280200450d012000410c6a28020010190f0b200041106a280200450d002000410c6a28020010190f0b0bdc0202027f027e230041206b22022400024002404118101b2203450d00200341106a41002900b7fc40370000200341086a41002900affc40370000200341002900a7fc40370000200341184138101a2203450d0120032001290000370018200341306a200141186a290000370000200341286a200141106a290000370000200341206a200141086a29000037000042002104200241106a41086a220142003703002002420037031020034138200241106a1001200241086a2001290300370300200220022903103703000240024002402002411041d889c200410041001000417f460d00200242003703182002420037031020024110200241106a4110410010002201417f460d022001410f4d0d02200241186a2903002105200229031021040c010b420021050b200310192000200537030820002004370300200241206a24000f0b41fcf9c00041331030000b41184101101c000b41384101101c000bdc0202027f027e230041206b22022400024002404114101b2203450d00200341106a41002800a3fc40360000200341086a410029009bfc4037000020034100290093fc40370000200341144134101a2203450d01200320012900003700142003412c6a200141186a290000370000200341246a200141106a2900003700002003411c6a200141086a29000037000042002104200241106a41086a220142003703002002420037031020034134200241106a1001200241086a2001290300370300200220022903103703000240024002402002411041d889c200410041001000417f460d00200242003703182002420037031020024110200241106a4110410010002201417f460d022001410f4d0d02200241186a2903002105200229031021040c010b420021050b200310192000200537030820002004370300200241206a24000f0b41fcf9c00041331030000b41144101101c000b41344101101c000bed1207017f017e017f017e017f017e047f230041b0016b2203240042002104200341206a41086a220542003703002003420037032041e6fbc000411b200341206a1001200341a0016a41086a2005290300370300200320032903203703a0010240024002400240200341a0016a411041d889c200410041001000417f460d002003420037032820034200370320200341a0016a4110200341206a4110410010002205417f460d022005410f4d0d02200341286a290300210620032903202104411421074114101b2205450d010c030b42002106411421074114101b22050d020b20074101101c000b41fcf9c00041331030000b200541106a41002800a3fc40360000200541086a410029009bfc4037000020054100290093fc403700000240024002400240024002400240024002400240024002400240024002400240200520074134101a2205450d00200520002900003700142005412c6a200041186a290000370000200541246a200041106a2900003700002005411c6a200041086a290000370000200320013703a001200320023703a80142002108200341206a41086a220742003703002003420037032020054134200341206a100120034190016a41086a2007290300370300200320032903203703900120034190016a4110200341a0016a4110100320051019024002402004200158200620025820062002511b0d00200341106a20001045200341106a41086a290300210620032903102101200341206a41086a220542003703002003420037032041a7fbc0004116200341206a1001200341a0016a41086a2005290300370300200320032903203703a00102400240200341a0016a411041d889c200410041001000417f460d002003420037032820034200370320200341a0016a4110200341206a4110410010002205417f460d052005410f4d0d05200341286a2903002102200329032021080c010b420021020b0240200820017d2204200856200220067d2008200154ad7d220120025620012002511b0d00200320043703a001200320013703a801200341206a41086a220542003703002003420037032041a7fbc0004116200341206a100120034190016a41086a2005290300370300200320032903203703900120034190016a4110200341a0016a411010030b4114101b2205450d04200541106a41002800a3fc40360000200541086a410029009bfc4037000020054100290093fc40370000200541144134101a2205450d05200520002900003700142005412c6a200041186a290000370000200541246a200041106a2900003700002005411c6a200041086a290000370000200341206a41086a220742003703002003420037032020054134200341206a1001200341a0016a41086a2007290300370300200320032903203703a001200341a0016a4110100220051019410f101b2205450d06200541076a41002900fdbd40370000200541002900f6bd403700002005410f412f101a2205450d072005200029000037000f200541276a200041186a2900003700002005411f6a200041106a290000370000200541176a200041086a290000370000200341a0016a41086a22074200370300200342003703a0012005412f200341a0016a1001200341206a41086a2007290300370300200320032903a001370320200341206a41101002200510194113101b2205450d082005410f6a41002800f8df41360000200541086a41002900f1df41370000200541002900e9df41370000200541134133101a2205450d09200520002900003700132005412b6a200041186a2207290000370000200541236a200041106a22092900003700002005411b6a200041086a220a290000370000200341a0016a41086a220b4200370300200342003703a00120054133200341a0016a1001200341206a41086a220c200b290300370300200320032903a001370320200341206a4110100220051019200341206a41186a2007290000370300200341206a41106a2009290000370300200c200a290000370300200320002900003703204108101b2207450d0a200742e3deb9d3b38eddb73a3700004120101b2205450d0b20052003290320370000200541186a2209200341206a41186a290300370000200541106a220a200341206a41106a290300370000200541086a220b200341206a41086a220c290300370000200741084128101a2207450d0c20072005290000370008200741206a2009290000370000200741186a200a290000370000200741106a200b29000037000020051019200341a0016a41086a22054200370300200342003703a00120074128200341a0016a1001200c2005290300370300200320032903a0013703204110101b2205450d0d20052003290320370000200541086a200341206a41086a2903003700002007101920054110100d200510194111101b2205450d0e200541106a41002d00eb99413a0000200541086a41002900e39941370000200541002900db9941370000200541114131101a2205450d0f20052000290000370011200541296a200041186a290000370000200541216a200041106a290000370000200541196a200041086a290000370000200341a0016a41086a22074200370300200342003703a00120054131200341a0016a1001200341206a41086a2007290300370300200320032903a001370320200341206a41101002200510192003200010442003290300200341086a290300844200510d010b200341b0016a24000f0b4113101b2205450d0e2005410f6a41002800998340360000200541086a410029009283403700002005410029008a8340370000200541134133101a2205450d0f200520002900003700132005412b6a200041186a2209290000370000200541236a200041106a220a2900003700002005411b6a200041086a220b290000370000200341206a41086a220742003703002003420037032020054133200341206a1001200341a0016a41086a2007290300370300200320032903203703a001200341a0016a4110100220051019200741013a0000200341296a2000290000370000200341316a200b290000370000200341396a200a290000370000200341c1006a2009290000370000200341023a0020200341206a103d200341b0016a24000f0b41344101101c000b41fcf9c00041331030000b41144101101c000b41344101101c000b410f4101101c000b412f4101101c000b41134101101c000b41334101101c000b41084101101c000b41204101101c000b41284101101c000b41104101101c000b41114101101c000b41314101101c000b41134101101c000b41334101101c000bfd0a07017f017e017f017e017f017e047f230041b0016b2203240042002104200341a0016a41086a22054200370300200342003703a00141e6fbc000411b200341a0016a100120034190016a41086a2005290300370300200320032903a00137039001024002400240024020034190016a411041d889c200410041001000417f460d00200342003703282003420037032020034190016a4110200341206a4110410010002205417f460d022005410f4d0d02200341286a290300210620032903202104411821074118101b2205450d010c030b42002106411821074118101b22050d020b20074101101c000b41fcf9c00041331030000b200541106a41002900b7fc40370000200541086a41002900affc40370000200541002900a7fc40370000024002400240024002400240200520074138101a2205450d0020052000290000370018200541306a200041186a290000370000200541286a200041106a290000370000200541206a200041086a290000370000200320013703202003200237032842002108200341a0016a41086a22074200370300200342003703a00120054138200341a0016a100120034190016a41086a2007290300370300200320032903a0013703900120034190016a4110200341206a4110100320051019024002402004200158200620025820062002511b0d00200341106a20001044200341106a41086a290300210620032903102101200341a0016a41086a22054200370300200342003703a00141a7fbc0004116200341a0016a100120034190016a41086a2005290300370300200320032903a001370390010240024020034190016a411041d889c200410041001000417f460d00200342003703282003420037032020034190016a4110200341206a4110410010002205417f460d052005410f4d0d05200341286a2903002102200329032021080c010b420021020b0240200820017d2204200856200220067d2008200154ad7d220120025620012002511b0d002003200437032020032001370328200341a0016a41086a22054200370300200342003703a00141a7fbc0004116200341a0016a100120034190016a41086a2005290300370300200320032903a0013703900120034190016a4110200341206a411010030b4118101b2205450d04200541106a41002900b7fc40370000200541086a41002900affc40370000200541002900a7fc40370000200541184138101a2205450d0520052000290000370018200541306a200041186a290000370000200541286a200041106a290000370000200541206a200041086a290000370000200341a0016a41086a22074200370300200342003703a00120054138200341a0016a1001200341206a41086a2007290300370300200320032903a001370320200341206a41101002200510192003200010452003290300200341086a290300844200510d010b200341b0016a24000f0b4113101b2205450d042005410f6a41002800998340360000200541086a410029009283403700002005410029008a8340370000200541134133101a2205450d05200520002900003700132005412b6a200041186a2207290000370000200541236a200041106a22092900003700002005411b6a200041086a220a290000370000200341a0016a41086a220b4200370300200342003703a00120054133200341a0016a1001200341206a41086a220c200b290300370300200320032903a001370320200341206a4110100220051019200c41013a0000200341296a2000290000370000200341316a200a290000370000200341396a2009290000370000200341c1006a2007290000370000200341023a0020200341206a103d200341b0016a24000f0b41384101101c000b41fcf9c00041331030000b41184101101c000b41384101101c000b41134101101c000b41334101101c000bd60b03027f017e067f230041f0016b22052400200541e0016a41086a22064200370300200542003703e00141eb9fc1004119200541e0016a1001200541f0006a41086a2006290300370300200520052903e00137037041002106024002400240024002400240024002400240024002400240024002400240200541f0006a411041d889c200410041001000417f460d0020054100360200200541f0006a4110200541044100100041016a41044d0d01024020052802002206450d0020052006417f6a104920052d00684103460d01200541f0006a200541f0001095031a20052903702107200541f0006a41086a104320072001580d01200041aea0c10036020420004101360200200041086a41c70036020020021043200541f0016a24000f0b410021060b2005200641016a360200200541e0016a41086a22084200370300200542003703e00141eb9fc1004119200541e0016a1001200541f0006a41086a22092008290300370300200520052903e001370370200541f0006a4110200541041003200520013703702009200241d8001095031a200520043703d001200520033a00d801411a101b2202450d01200241186a41002f00939a413b0000200241106a410029008b9a41370000200241086a41002900839a41370000200241002900fb99413700002002411a4134101a2208450d022008200636001a2005410036020820054201370300200529037021014108101b2202450d0320054108360204200541086a22092009280200220941086a36020020052002360200200220096a2001370000200541f0006a41086a220a2005106402400240024002400240024002400240024002400240200541d8016a2d000022024101460d0020024102470d012005280204200541086a2802002202470d03200241016a22092002490d162002410174220b20092009200b491b220b4100480d162002450d0720052802002002200b101a2209450d080c130b2005280204200541086a2802002202470d01200241016a22092002490d152002410174220b20092009200b491b220b4100480d152002450d0420052802002002200b101a2209450d050c100b2005280204200541086a2802002202470d02200241016a22092002490d142002410174220b20092009200b491b220b4100480d142002450d0720052802002002200b101a2209450d080c0d0b200528020021090c0f0b200528020021090c100b200528020021090c0b0b200b101b22090d0b0b200b4101101c000b200b101b22090d0b0b200b4101101c000b200b101b22090d050b200b4101101c000b41fcf9c00041331030000b411a4101101c000b41344101101c000b41084101101c000b2005200b36020420052009360200200541086a28020021020b200541086a200241016a360200200920026a41003a00000c040b2005200b36020420052009360200200541086a28020021020b200541086a200241016a360200200920026a41013a00000c020b2005200b36020420052009360200200541086a28020021020b200541086a200241016a360200200920026a41023a00000b200541d0016a290300210102400240024020052802042209200541086a28020022026b41084f0d00200241086a220b2002490d0320094101742202200b200b2002491b22024100480d032009450d01200528020020092002101a220b450d020c040b2005280200210b0c040b2002101b220b0d020b20024101101c000b101d000b200520023602042005200b360200200541086a28020021020b200541086a2209200241086a360200200b20026a20013700002009280200210b2005280204210c20052802002102200541e0016a41086a220d4200370300200542003703e0012008411e200541e0016a10012009200d290300370300200520052903e001370300200541102002200b10030240200c450d00200210190b20081019200a1043200541fc006a2006360200200541f9006a20033a0000200541f0006a41086a41023a0000200541053a0070200541f0006a103d2000410036020020002006360204200541f0016a24000bdd0504027f017e037f017e23004180036b220224000240024002400240411a101b2203450d00200341186a41002f00939a413b0000200341106a410029008b9a41370000200341086a41002900839a41370000200341002900fb99413700002003411a4134101a2203450d012003200136001a200241d0016a41086a22014200370300200242003703d0012003411e200241d0016a1001200241086a2001290300370300200220022903d0013703000240024002402002411041d889c200410041001000417f460d002002200236021020024110360214200242003703d0012002410020024110200241d0016a41084100100022012001417f461b2201410820014108491b360218200141074d0d0620022903d0012104200241d0016a200241106a105520022d00d0012101200241a8026a200241d0016a41017241d7001095031a2001410e460d06200241f9006a200241a8026a41d7001095031a200220013a0020200241206a410172200241f9006a41d7001095031a200241003a00d001200241186a2201200128020022012002280210220520022802142206200241d0016a41012001100041016a41014b22076a22013602002007450d0220022d00d001220741034f0d02200242003703d001200241106a41086a410020052006200241d0016a41082001100022052005417f461b2205410820054108491b20016a360200200541074d0d0520022903d0012108200241d0016a200241206a41d8001095031a2002200241236a2800003600ab02200220022800203602a80220002004370300200041086a200241d0016a41d8001095031a20002008370360200220022802a802360220200220022800ab02360023200020073a006820002002280220360069200041ec006a20022800233600000c010b200041033a00680b2003101920024180036a24000f0b200241206a104341fcf9c00041331030000b411a4101101c000b41344101101c000b200241206a10430b41fcf9c00041331030000b6d01017f230041306b2203240020032002360204200320013602002003412c6a41023602002003411c6a4102360200200341023602242003420237020c200341f4d8c300360208200320033602282003200341046a3602202003200341206a360218200341086a200010f201000bd589010b027f027e107f027e047f047e027f027e277f027e247f230041a0036b22012400200141a0016a41086a22024200370300200142003703a001419e95c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a00137039002024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0220012903a00122034200510d044200210420002003824200520d120c010b42002104200042e807824200520d110b200141a0016a41086a22022004370300200120043703a00141b295c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a0013703900220014190026a411041d889c200410041001000417f460d10200141003602a00120014190026a4110200141a0016a41044100100041016a41044d0d0120012802a0012202450d1041082105200141a0016a41086a22064200370300200142003703a001419993c0004115200141a0016a100120014190026a41086a2006290300370300200120012903a00137039002410021060240024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a105620012802a0012205450d06200141a8016a280200210620012802a40121070c010b410021070b200141a0016a109301024020012802ac012208450d0020012802a801220920012903b0012204422088a76b20066a210a20012903a001210302402004a7450d00200810190b200a2002490d070c060b42002103200141a0016a41086a22094200370300200142003703a001419c82c000410d200141a0016a100120014190026a41086a2009290300370300200120012903a0013703900241002109024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0420012903a00121030b200620024f0d050c060b41fcf9c00041331030000b41fcf9c00041331030000b4180b4c2001029000b41fcf9c00041331030000b41fcf9c00041331030000b0240200920024f0d00200920026b220220066a220920024f0d052005200941286c6a29032021030c010b200141a0016a41086a22024200370300200142003703a00141da95c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a00137039002024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0220012903a00120037c21030c010b420520037c21030b200141a0016a41086a22024200370300200142003703a001419e95c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a001370390020240024002400240024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0220012903a00122044200520d0141a8b4c2001029000b42e80721040b200320047c427f7c220320032004827d210402402007450d00200510190b20042000520d0c4108210b200141a0016a41086a22024200370300200142003703a001419993c0004115200141a0016a100120014190026a41086a2002290300370300200120012903a001370390024100210c0240024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a105620012802a001220b450d07200141a8016a280200210c20012802a401210d0c010b4100210d0b200141a0016a41086a22024200370300200142003703a00141b295c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a001370390024100210e024020014190026a411041d889c200410041001000417f460d00200141003602a00120014190026a4110200141a0016a41044100100041016a41044d0d0320012802a001210e0b42002104200141a0016a41086a22024200370300200142003703a001419c82c000410d200141a0016a100120014190026a41086a2002290300370300200120012903a00137039002024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0220012903a00121040b0240024002400240200c41286c2202450d00200b41206a2903002004520d0020014190026a41186a2206200b41186a29000037030020014190026a41106a2205200b41106a29000037030020014190026a41086a2207200b41086a2900003703002001200b290000370390024120101b220f450d0b200f200129039002370000200f41186a2006290300370000200f41106a2005290300370000200f41086a2007290300370000200b20026a200b41286a2202460d02200c41286c41586a21074120210541012106410121100340200241206a2903002004520d04200141c0026a41186a200241186a2209290000370300200141c0026a41106a200241106a2208290000370300200141c0026a41086a200241086a220a290000370300200120022900003703c00220014180036a41186a2211200929000037030020014180036a41106a2209200829000037030020014180036a41086a2208200a290000370300200120022900003703800302400240024020102006470d00200641016a220a2006490d2a20064101742212200a200a2012491b2212ad4205862203422088a70d2a2003a7220a4100480d2a2006450d01200f2006410574200a101a220f0d020c0c0b200621120c010b200a101b220f450d0a0b200241286a2102200f20056a2206200129038003370000200641186a2011290300370000200641106a2009290300370000200641086a2008290300370000200541206a2105201041016a211020122106200741586a22070d000c020b0b4101210f41002110410021120b200e200c20106b22064d0d0a0c0b0b4101211041012112200e200c41016b22064b0d0a0c090b20062112200e200c20106b22064b0d090c080b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b200a4101101c000b41fcf9c00041331030000b4198b4c20020092006104a000b41204101101c000b2012450d01200f10190c010b200141a0016a41086a22024200370300200142003703a00141ee95c000411c200141a0016a100120014190026a41086a2002290300370300200120012903a001370390020240024002400240024002400240024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0220012903a00121030c010b42e80721030b200141003602a801200142013703a0014108101b2202450d012001428880808080013702a401200120023602a0012002200320047c370000200241084110101a2202450d0220014290808080c0013702a4012002200e20066b2213360008200120023602a001200120103602900220014190026a200141a0016a105d0240024002402010450d00201041057421084100200141a0016a41086a28020022066b210720012802a001210a20012802a4012109200f210203400240200920076a411f4b0d00200641206a22052006490d2320094101742211200520052011491b22054100480d23024002402009450d00200a20092005101a220a0d010c060b2005101b220a450d050b200521090b200a20066a22052002290000370000200541186a200241186a290000370000200541106a200241106a290000370000200541086a200241086a290000370000200741606a2107200641206a2106200241206a2102200841606a22080d000b200141a8016a2006360200200120093602a4012001200a3602a0010c010b200141a8016a280200210620012802a401210920012802a001210a0b200141a0016a41086a22024200370300200142003703a00141c695c0004114200141a0016a100120014190026a41086a2002290300370300200120012903a0013703900220014190026a4110200a2006100302402009450d00200a10190b02402012450d00200f10190b200141a0016a41086a22024200370300200142003703a001418a96c000410e200141a0016a100120014190026a41086a2002290300370300200120012903a00137039002410021060240024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a103a20012802a0012211450d0620012802a4012114200141a8016a280200220641ffffff3f712212450d010c070b4101211141002114410041ffffff3f7122120d060b4108210f0c060b20054101101c000b41fcf9c00041331030000b41084101101c000b41104101101c000b41fcf9c00041331030000b20124104742202101b220f0d0020024108101c000b4100210202402011201120064105746a460d002006410574220541606a2107200f2102201121060340200141d0006a20061045200141d0006a41086a290300210420012903502103200141c0006a20061044200141c0006a41086a290300211520022003200129034022167c22033703002002201520047c2003201654ad7c370308200241106a2102200641206a2106200541606a22050d000b200741057641016a21020b200141003602a801200142013703a001200120023602900220014190026a200141a0016a105d0240024020024104742209450d00200141a0016a41086a280200210220012802a001210820012802a4012107200f21060340200641086a2903002104200629030021030240024002400240200720026b41104f0d00200241106a22052002490d1f2007410174220a20052005200a491b220a4100480d1f2007450d0120082007200a101a22080d020c0a0b200241106a21050c020b200a101b2208450d080b200a21070b200641106a2106200820026a220220043700082002200337000020052102200941706a22090d000b200141a8016a2005360200200120073602a401200120083602a0010c010b200141a8016a280200210520012802a401210720012802a00121080b200141a0016a41086a22024200370300200142003703a001419896c0004118200141a0016a100120014190026a41086a2002290300370300200120012903a0013703900220014190026a411020082005100302402007450d00200810190b02402012450d00200f10190b200141a0016a41086a22024200370300200142003703a00141b096c0004112200141a0016a100120014190026a41086a2002290300370300200120012903a001370390020240024020014190026a411041d889c200410041001000417f460d00200141003602a00120014190026a4110200141a0016a41044100100041016a41044d0d0a20012802a00121060c010b410221060b200141b8026a4200370300200141b0026a4200370300200141a8026a4200370300200141a0026a420037030020014198026a42003703002001420037039002200620136a220aad42307e2204422088a70d172004a72202417f4c0d17024002402002450d002002101b220f450d0d200f21020c010b4108210f410821020b200141a0016a41286a220520014190026a41286a290300370300200141a0016a41206a220720014190026a41206a290300370300200141a0016a41186a220920014190026a41186a290300370300200141a0016a41106a220820014190026a41106a290300370300200141a0016a41086a20014190026a41086a29030037030020012001290390023703a001024002400240200a4102490d002010200e6a20066a417f6a200c6b21060340200220012903a001370300200241286a2005290300370300200241206a2007290300370300200241186a2009290300370300200241106a2008290300370300200241086a200141a0016a41086a290300370300200241306a21022006417f6a22060d000b200a417f6a21060c010b41002106200a450d010b200220012903a001370300200241286a200141a0016a41286a290300370300200241206a200141a0016a41206a290300370300200241186a200141a0016a41186a290300370300200241106a200141a0016a41106a290300370300200241086a200141a0016a41086a290300370300200641016a21060b200120063602a8012001200a3602a4012001200f3602a0012001411336029402200141c296c00036029002200141a0016a20014190026a1094010240200a450d00200f10190b200141a8016a2013360200200141023a00a401200141063a00a001200141a0016a103d2014450d0020111019200d0d010c020b200d450d010b200b10190b200141a0016a10930120012802ac012217450d1720012802b001211820012903a0012000520d16200141a0016a41086a22024200370300200142003703a001419896c0004118200141a0016a100120014190026a41086a22062002290300370300200120012903a0013703900220014190026a4110100220064200370300200142003703900241c695c000411420014190026a10012002200629030037030020012001290390023703a0010240024002400240024002400240200141a0016a411041d889c200410041001000417f460d002001200141a0016a360280032001411036028403200142003703900220014100200141a0016a411020014190026a41084100100022022002417f461b2202410820024108491b220636028803200241074d0d052001290390022100200141003602900220014188036a4100200141a0016a411020014190026a41042006100022022002417f461b2202410420024104491b20066a360200200241034d0d05200128029002211920014190026a20014180036a103a200128029002221a450d05200129029402211b410821144200211c20014190026a41086a22024200370300200142003703900241c695c000411420014190026a1001200141a0016a41086a2206200229030037030020012001290390023703a001200141a0016a41101002200120193602e802200120003703e00220064200370300200142003703a00141c296c0004113200141a0016a100120022006290300370300200120012903a00137039002024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a10950120012802a0012214450d0a20012902a401211c200141a0016a41086a22024200370300200142003703a00141c296c0004113200141a0016a100120014190026a41086a2002290300370300200120012903a0013703900220014190026a411010020b200141a0016a41086a22024200370300200142003703a001419c82c000410d200141a0016a100120014190026a41086a22062002290300370300200120012903a001370390024200211d024020014190026a411041d889c200410041001000417f460d00200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0420012903a001211d0b20024200370300200142003703a00141da95c0004114200141a0016a100120062002290300370300200120012903a0013703900220014190026a411041d889c200410041001000417f460d01200142003703a00120014190026a4110200141a0016a41084100100041016a41084d0d0420012903a001211e0c020b02402018450d00201710190b41cce2c000410f100441b997c00041351004200141a0036a24000f0b4205211e0b42002115200141a0016a41086a22024200370300200142003703a00141a497c0004115200141a0016a100120014190026a41086a2002290300370300200120012903a001370390020240024020014190026a411041d889c200410041001000417f460d00200142003703a801200142003703a00120014190026a4110200141a0016a4110410010002202417f460d072002410f4d0d07200141a8016a290300211520012903a00121160c010b420921160b2014201c422088a7221f41306c6a21060240024002402019450d002019417f6a210941002105024020142006460d002014201f41306c6a220241506a2206290300200241586a29030084500d02200141a8026a200241786a290000370300200141a0026a200241706a29000037030020014198026a200241686a2900003703002001200241606a29000037039002410121050b410021080c020b4100210841002109410021050c010b410121080b200141a9016a20014190026a41086a290300370000200141b1016a20014190026a41106a290300370000200141b9016a20014190026a41186a290300370000200120053a00a00120012001290390023700a10141012120200141a0016a4101722102024002402005450d00200141306a20021044200141306a41086a290300210020012903302104200141206a200210452002201620042004201656200020155620002015511b22051b220320012903207c22212015200020051b2222200141206a41086a2903007c2021200354ad7c10462002200420037d200020227d2004200354ad7d104720014180036a41186a200241186a29000037030020014180036a41106a200241106a29000037030020014180036a41086a200241086a29000037030020012002290000370380034120101b2220450d092020200129038003370000202041186a20014180036a41186a2210290300370000202041106a20014180036a41106a2211290300370000202041086a20014180036a41086a220f290300370000200141a0016a410172210241022107412021054101210a4101212302402009417f6a2212417f460d000340200841ff01710d0120142006460d01200641506a220b290300200641586a29030084500d012010200641786a2900003703002011200641706a290000370300200f200641686a2900003703002001200641606a290000370380032002200129038003370000200241086a2206200f290300370000200241106a22082011290300370000200241186a220c2010290300370000200141013a00a001200141106a20021044200141106a41086a2903002100200129031021042001200210452002201620042004201656200020155620002015511b220e1b220320012903007c222120152000200e1b2222200141086a2903007c2021200354ad7c10462002200420037d200020227d2004200354ad7d104720014190026a41186a220e200c29000037030020014190026a41106a220c200829000037030020014190026a41086a220820062900003703002001200229000037039002200141c0026a41186a220d200e290300370300200141c0026a41106a220e200c290300370300200141c0026a41086a220c200829030037030020012001290390023703c0020240200a2023470d00200a41016a2206200a490d1e2007200620062007491b2223ad4205862200422088a70d1e2000a722064100480d1e0240200a450d00202020052006101a22200d010c090b2006101b2220450d080b2009417f6a2109202020056a220620012903c002370000200641186a200d290300370000200641106a200e290300370000200641086a200c290300370000200741026a2107200541206a2105200a41016a210a41002108200b21062012417f6a2212417f470d000b0b20022001290380032200370000200241086a20014180036a41086a2903002204370000200241106a20014180036a41106a2903002203370000200241186a20014180036a41186a290300221537000020014190026a41086a200437030020014190026a41106a200337030020014190026a41186a2015370300200141003a00a00120012000370390020c010b20014180036a41186a200241186a29000037030020014180036a41106a200241106a29000037030020014180036a41086a200241086a29000037030020012002290000370380034100210a410021230b41082124200141a0016a41086a22024200370300200142003703a001419993c0004115200141a0016a100120014190026a41086a2002290300370300200120012903a00137039002410021250240024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a105620012802a0012224450d0a200141a8016a280200210f20012802a40121250c010b4100210f0b200141013602a0012024200f41286c6a210d024002400240024002400240201b422088a72210450d00410021264100212702402010200d20246b41286e2202200220104b1b2202450d00200241057422064100480d202006101b2205450d12200120053602a001200221270b202421022010210520012802a001222821060340200d20026b419f014d0d0220014180036a41186a200241186a220729000037030020014180036a41106a200241106a220929000037030020014180036a41086a200241086a22082900003703002001200229000037038003200829000021002009290000210420022900002103200641186a2007290000370000200641106a2004370000200641086a20003700002006200337000020054101460d03200241306a2900002100200241386a290000210420022900282103200641386a200241c0006a290000370000200641306a2004370000200641286a20003700002006200337002020054102460d04200241d8006a2900002100200241e0006a290000210420022900502103200641d8006a200241e8006a290000370000200641d0006a2004370000200641c8006a20003700002006200337004020054103460d0520024180016a290000210020024188016a290000210420022900782103200641f8006a20024190016a290000370000200641f0006a2004370000200641e8006a200037000020062003370060202641046a212620064180016a2106200241a0016a21022005417c6a22050d000c060b0b4100212720012802a0012128410021260c040b200d2002460d032024200f41286c6a2112410121070240034020014180036a41186a200241186a220929000037030020014180036a41106a200241106a220829000037030020014180036a41086a200241086a22112900003703002001200229000037038003201129000021002008290000210420022900002103200641186a2009290000370000200641106a2004370000200641086a200037000020062003370000200520072209460d01200941016a2107200641206a21062012200241286a2202470d000b0b202620096a21260c030b202641017221260c020b202641027221260c010b202641037221260b201e201d7c21152020200a4105746a21290240024002400240024002402010450d00200d2024460d012010417f732106200f41286c2105202421020340200141c0026a41186a200241186a290300370300200141c0026a41106a200241106a290300370300200141c0026a41086a200241086a290300370300200120022903003703c002200641016a2206450d04200241286a2102200541586a22050d000b200d210220202029470d020c1c0b200d2024460d00200141e0026a41186a202441186a290300370300200141e0026a41106a202441106a290300370300200141e0026a41086a202441086a290300370300200120242903003703e002202441286a2102202429032021000c030b2024210220202029460d1a0b20014180036a41186a202041186a220629000037030020014180036a41106a202041106a220529000037030020014180036a41086a202041086a22072900003703002001202029000037038003200729000021002005290000210420202900002103200141a0016a41186a2006290000370300200141a0016a41106a2004370300200141a0016a41086a2000370300200120033703a001202041206a210541022107201521000c020b200241206a2903002100200141e0026a41186a200141c0026a41186a290300370300200141e0026a41106a200141c0026a41106a290300370300200141e0026a41086a200141c0026a41086a290300370300200120012903c0023703e002200241286a21020b200141a0016a41186a200141e0026a41186a290300370300200141a0016a41106a200141e0026a41106a290300370300200141a0016a41086a200141e0026a41086a290300370300200120012903e0023703a00141002107202021050b417f417f200d20026b41286d2206202920056b4105766a220920092006491b220641016a220920092006491b222aad42287e2204422088a70d182004a72206417f4c0d18024002402006450d002006101b2213450d0c2013212b0c010b410821134108212b0b201320012903a001370300201341186a200141a0016a41186a290300370300201341106a200141a0016a41106a290300370300201341086a200141a0016a41086a290300370300202b2000370320024002402007450d0020052029460d01200541086a2900002100200541106a29000021042005290000210320014190026a41186a200541186a29000037030020014190026a41106a200437030020014190026a41086a20003703002001200337039002200541206a21050c0f0b0240200d2002460d00200141e0026a41186a200241186a2903002204370300200141e0026a41106a200241106a2903002203370300200141e0026a41086a200241086a29030022163703002002290300210020014190026a41086a201637030020014190026a41106a200337030020014190026a41186a2004370300200120003703e0022001200037039002200241286a210620022903202100410021100c100b20052029460d0020014180036a41186a200541186a220629000037030020014180036a41106a200541106a220729000037030020014180036a41086a200541086a2209290000370300200120052900003703800320092900002100200729000021042005290000210320014190026a41186a200629000037030020014190026a41106a200437030020014190026a41086a20003703002001200337039002200541206a21050c0e0b4101210820250d0f0c100b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b20064101101c000b200a4101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41204101101c000b41fcf9c00041331030000b41fcf9c00041331030000b20064108101c000b20064101101c000b20024108101c000b4102211020152100200221060b4102210941022102412821070340200141a0016a41186a221120014190026a41186a220b290300370300200141a0016a41106a220f20014190026a41106a220c290300370300200141a0016a41086a221220014190026a41086a220e29030037030020012001290390023703a001024020022208417f6a2202202a470d002002417f417f200d20066b41286d222b202920056b4105766a222a202a202b491b222b41016a222a202a202b491b6a222b2002490d0c2009202b202b2009491b222aad42287e2204422088a70d0c2004a722024100480d0c0240024020084101470d002002101b22130d010c060b201320072002101a2213450d050b2013212b0b202b20076a220220012903a001370300200241186a2011290300370300200241106a200f290300370300200241086a2012290300370300200241206a20003703000240024002400240201041ff017122024101460d0020024102470d0120052029460d03200541086a2900002100200541106a290000210420052900002103200b200541186a290000370300200c2004370300200e20003703002001200337039002200541206a21054201210441022110201521000c020b200d2006460d02200b200641186a290300370300200c200641106a290300370300200e200641086a2903003703002001200629030037039002200629032021004201210441012110200641286a21060c010b0240200d2006460d00200141e0026a41186a200641186a2903002204370300200141e0026a41106a200641106a2903002203370300200141e0026a41086a200641086a290300221637030020062903002100200e2016370300200c2003370300200b2004370300200120003703e0022001200037039002200629032021004201210441002110200641286a21060c010b0240024020052029460d0020014180036a41186a200541186a220229000037030020014180036a41106a200541106a221029000037030020014180036a41086a200541086a22112900003703002001200529000037038003201129000021002010290000210420052900002103200b2002290000370300200c2004370300200e20003703002001200337039002200541206a210542012104201521000c010b420021040b410221100b200941026a2109200841016a2102200741286a210720044200520d010b0b2025450d010b202410190b0240200841144b0d004101212c200841014d0d03417f212d2008417f6a212e4128212f202b200841286c6a213041022131412021324118213341102134410821354103213641f000213741582138417821394170213a4168213b4160213c41c800213d4100213e0c040b2008410176223fad42287e2200422088a70d072000a72202417f4c0d0741082140024002402002450d002002101b2241450d03204121420c010b41082141410821420b41582143202b41586a2144202b41a87f6a21454100214641042147417f2148410121494203214a4220214b4103214c4102214d417d214e4128214f41782150412021514118215241102153417e2154417421554164215641502157410521584109215941f000215a41c800215b41c000215c4138215d4130215e410a215f410421604100216141002162200821634101213e0c040b20024108101c000b20024108101c000b410021020c030b410121020c020b410121020c010b4100212a4108211302402025450d00202410190b41002108410021020b024003400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e020001010b200120083602a8012001202a3602a401200120133602a00120014115360294022001419993c00036029002200141a0016a20014190026a1096010240202a450d00201310190b200141a0016a41086a22024200370300200142003703a00141eb96c0004112200141a0016a100120014190026a41086a2002290300370300200120012903a001370390024100216902400240024020014190026a411041d889c200410041001000417f460d002001421037028403200120014190026a36028003200141a0016a20014180036a103a20012802a001226a450d02200141a8016a280200216b20012802a40121690c010b4101216a4100216b0b200141a8026a4200370300200141a0026a420037030020014198026a42003703002001420037039002206bad2200421b88a70d1c2000420586a72202417f4c0d1c024002402002450d002002101b226c0d0120024101101c000b4101216c0b200141a0016a41186a220520014190026a41186a290300370300200141a0016a41106a220720014190026a41106a290300370300200141a0016a41086a226d20014190026a41086a29030037030020012001290390023703a001024002400240206b4102490d00206b417f6a2106206c21020340200220012903a001370000200241186a2005290300370000200241106a2007290300370000200241086a206d290300370000200241206a21022006417f6a22060d000b206b417f6a216e0c010b4100216e206c2102206b450d010b200220012903a001370000200241186a200141a0016a41186a290300370000200241106a200141a0016a41106a290300370000200241086a200141a0016a41086a290300370000206e41016a216e0b2014201f41306c6a2102024002402019450d00024020022014460d00201f41306c21062019417f732109200141c0026a41186a2105200141c0026a41106a2107200141c0026a41086a216d0340201420066a220241586a2903002100200241506a29030021042005200241786a2903003703002007200241706a290300370300206d200241686a2903003703002001200241606a2903003703c00220042000844200510d01200141e0026a41186a22102005290300370300200141e0026a41106a22112007290300370300200141e0026a41086a220f206d290300370300200120012903c0023703e00220014180036a41186a201029030037030020014180036a41106a201129030037030020014180036a41086a200f290300370300200120012903e00237038003200941016a2209450d03200641506a22060d000b0b4100216f201ca70d050c060b4100216f20022014460d03200241586a2903002100200241506a226d2903002104200141c0026a41186a2206200241786a290300370300200141c0026a41106a2205200241706a290300370300200141c0026a41086a2207200241686a2903003703002001200241606a2903003703c0022004200084500d03200141a0016a41186a2006290300370300200141a0016a41106a2005290300370300200141a0016a41086a2007290300370300200120012903c0023703a0014100216f0c0e0b200141a0016a41186a20014180036a41186a290300370300200141a0016a41106a20014180036a41106a290300370300200141a0016a41086a20014180036a41086a29030037030020012001290380033703a001200241506a216d4100216f0c0c0b41fcf9c00041331030000b024002400240203e0e03000102020b2008202e2202202d6a222e490d0502402008202e6b22062031490d00202b2002202f6c6a220220326a2207290300202b202e202f6c6a220520326a220929030022005a0d0020014180036a20336a2210200520336a221129030037030020014180036a20346a220f200520346a221229030037030020014180036a20356a220b200520356a220c290300370300200120052903003703800320052002290300370300200c200220356a2903003703002012200220346a2903003703002011200220336a29030037030020092007290300370300024020062036490d00200520376a29030020005a0d00410221052030210703402007220220386a2002290300370300200220396a200220326a2903003703002002203a6a200220336a2903003703002002203b6a200220346a2903003703002002203c6a200220356a2903003703002005202c6a220520064f0d012002202f6a21072002203d6a2903002000540d000b0b200220012903800337030020022000370320200220336a2010290300370300200220346a200f290300370300200220356a200b2903003703000b203020386a2130202e0d0b0c0e0b206321644100216341012165206420486a2211450d12024002400240024002400240202b2011204f6c6a20516a290300202b2064204f6c22026a20576a29030022005a0d002045206420586c204c7422076a2102034020112049460d02201120486a2111200020022903002204542106200220436a21022004210020060d000c030b0b206420546a2107204520026a21064100216341002102034020072002460d05200220496a21022000200629030022045a2105200620436a21062004210020050d000b200220496a2165206420026b20486a2211450d030c020b410021110b20642011490d09206420084b0d0b0240206420116b22652049762205450d00204420076a2102202b2011204f6c6a21060340200141a0016a20516a2207200620516a2209290300370300200141a0016a20526a2210200620526a220f290300370300200141a0016a20536a2212200620536a220b290300370300200141a0016a20406a220c200620406a220e290300370300200120062903003703a001200220406a220d2903002100200220536a22292903002104200220526a22242903002103200229030021152009200220516a2225290300370300200f2003370300200b2004370300200e200037030020062015370300202520072903003703002024201029030037030020292012290300370300200d200c290300370300200220012903a001370300200220436a21022006204f6a2106200520486a22050d000b0b2011450d010b206520594b0d00206420084b0d09202b2011204f6c6a2166410021670c190b2011216320612062460d160c170b2064216520612062460d130c140b0240034020014180016a41186a2202200141a0016a41186a220729030037030020014180016a41106a2206200141a0016a41106a220929030037030020014180016a41086a2205200141a0016a41086a2210290300370300200120012903a0013703800120014190026a41186a200229030037030020014190026a41106a200629030037030020014190026a41086a2005290300370300200120012903800137039002200141e0026a20014190026a10970120072002290300370300200920062903003703002010200529030037030020012001290380013703a00120012802e0024101460d0141000d022014206d460d02206d41586a2903002100206d41506a22022903002104200141c0026a41186a2206206d41786a290300370300200141c0026a41106a2205206d41706a290300370300200141c0026a41086a2211206d41686a2903003703002001206d41606a2903003703c00220042000844200510d02200720062903003703002009200529030037030020102011290300370300200120012903c0023703a0012002216d0c000b0b20014180036a41086a2209200141a0016a41086a220629030037030020014180036a41106a2210200141a0016a41106a220529030037030020014180036a41186a2211200141a0016a41186a2207290300370300200120012903a00137038003200141e0026a41086a2802002102200141e0006a41186a220f2011290300370300200141e0006a41106a22112010290300370300200141e0006a41086a2210200929030037030020012001290380033703602007200f2903003703002005201129030037030020062010290300370300200120012903603703a001206e20024d0d08206c20024105746a220220012903a001370000200241186a2007290300370000200241106a2005290300370000200241086a2006290300370000206f41016a216f41000d002014206d460d00206d41586a2903002100206d41506a22022903002104200141c0026a41186a2206206d41786a290300370300200141c0026a41106a2205206d41706a290300370300200141c0026a41086a2207206d41686a2903003703002001206d41606a2903003703c00220042000844200510d00200141a0016a41186a2006290300370300200141a0016a41106a2005290300370300200141a0016a41086a2007290300370300200120012903c0023703a0012002216d4102213e0c0e0b201ca7450d010b201410190b024002400240206e206b41ffffff3f7122022002206e4b1b226d450d00206a2102206c2106410021070340024020022006460d00200220064120109703450d004116101b2205450d032005410e6a41002900e39640370000200541086a41002900dd9640370000200541002900d59640370000200541164136101a2205450d04200520022900003700162005412e6a200241186a290000370000200541266a200241106a2900003700002005411e6a200241086a290000370000200141a0016a41086a22094200370300200142003703a00120054136200141a0016a100120014190026a41086a2009290300370300200120012903a0013703900220014190026a41101002200510190b200241206a2102200641206a2106200741016a2207206d490d000b0b206c206e4105746a2102206e21090240024002400240024002400240206e4104490d00200141a0016a41206a2108200141e0016a215120014180026a212b200141a0026a2140200141b8016a2105200141b0016a2107200141a8016a216d20022106206e210903402005420037030020074200370300206d4200370300200142003703a001024020082006460d00200641606a200141a0016a41201097030d030b2005420037030020074200370300206d4200370300200142003703a001024020512006460d00200641406a200141a0016a41201097030d040b2005420037030020074200370300206d4200370300200142003703a0010240202b2006460d00200641a07f6a200141a0016a41201097030d050b2005420037030020074200370300206d4200370300200142003703a001200641807f6a2102024020402006460d002002200141a0016a41201097030d060b2009417c6a2109200221062002206c6b41ff004b0d000b0b2002206c460d052009417f6a2106200141a0016a41206a2105200141b8016a2107200141b0016a216d200141a8016a2109034020074200370300206d420037030020094200370300200142003703a001024020052002460d00200241606a200141a0016a41201097030d060b2006417f6a2106206c200241606a2202470d000c060b0b2009417f6a21060c030b2009417e6a21060c020b2009417d6a21060c010b2009417c6a21060b200641016a2202206e206e20024b1b216e0b200141bc016a2026360200200141b8016a2027360200200141b4016a2028360200200141a0016a41106a200a360200200141ac016a2023360200200141a0016a41086a22022020360200200141033a00a401200141063a00a001200141a0016a103d2001206e3602a8012001206b3602a4012001206c3602a0012001411236029402200141eb96c00036029002200141a0016a20014190026a1098010240206b450d00206c10190b2001206f3602800320024200370300200142003703a00141fd96c0004116200141a0016a100120014190026a41086a22062002290300370300200120012903a0013703900220014190026a411020014180036a4104100320024200370300200142003703a001419397c0004111200141a0016a100120062002290300370300200120012903a001370390020240024020014190026a411041d889c200410041001000417f460d00200141003602a00120014190026a4110200141a0016a41044100100041016a41044d0d0520012802a00141016a21020c010b410121020b2001200236028003200141a0016a41086a22024200370300200142003703a001419397c0004111200141a0016a100120014190026a41086a2002290300370300200120012903a0013703900220014190026a411020014180036a4104100302402069450d00206a10190b201ba7450d1b201a10190c1b0b41164101101c000b41364101101c000b202e20081027000b41fcf9c00041331030000b201120641027000b20642011417f6a2263490d120b206420081028000b41c0b4c2002002206e104a000b4100213e0c030b4102213e0c040b4102213e0c040b410021020c0b0b410121020c0a0b410121020c090b410121020c080b410121020c070b410021020c050b410121020c040b410221020c030b410121020c020b410221020c010b410321020b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e0400010204040b20612062470d13410121020c170b206120496a22022061490d1a20612049742206200220022006491b2202ad204a862200204b88a70d1a2000a722062046480d1a024002402061450d0020602061204c742006101a22600d010c030b2006101b2260450d020b20022161410221020c160b20602062204c746a2202206536020420022063360200206220496a226821622068204d490d02410121670c140b20064104101c000b0240024020670e020001010b2064201120486a2263490d160240206420636b2265204d490d00202b2011204f6c6a220220516a2205290300202b2063204f6c6a220620516a220729030022005a0d0020014180036a20526a2209200620526a221029030037030020014180036a20536a220f200620536a221229030037030020014180036a20406a220b200620406a220c290300370300200120062903003703800320062002290300370300200c200220406a2903003703002012200220536a2903003703002010200220526a2903003703002007200529030037030002402065204c490d002006205a6a29030020005a0d004102210620662105024003402005220220516a2002205b6a290300370300200220526a2002205c6a290300370300200220536a2002205d6a290300370300200220406a2002205e6a29030037030020022002204f6a2205290300370300200620496a220620654f0d012002205a6a2903002000540d000b0b2002204f6a21020b200220012903800337030020022000370320200220526a2009290300370300200220536a200f290300370300200220406a200b2903003703000b2063450d0f206620436a2166206321112065205f490d0d410021020c140b024002400240024020602068220b20486a2268204c746a2202280200450d002060200b204c746a220920556a2802002207200228020422064d0d0041022162200b41024d0d042060200b204e6a2202204c746a2802042205200620076a4d0d0141032162200b41034d0d04200920566a280200200520076a4d0d010c050b200b204c490d01200228020421062060200b204e6a2202204c746a28020421050b20052006490d010b200b20546a21020b200b200220496a22624d0d03200b20024d0d0420602002204c746a220e2802042224200e2802006a220220602062204c746a220d2802002229490d05200220084b0d06200e20476a2125202b2029204f6c6a2212200d280204220c204f6c22066a21092002204f6c210502400240024002400240200220296b2210200c6b2202200c4f0d00204120092002204f6c22061095031a204220066a2107200c2049480d0120022049480d01204420056a21052009210203402005200220436a2210200720436a220f200720506a290300200220506a2903005422091b2206290300370300200520516a200620516a290300370300200520526a200620526a290300370300200520536a200620536a290300370300200520406a200620406a2903003703002007200f20091b210720122010200220091b22024f0d04200520436a21052042210620422007490d000c050b0b2041201220061095031a204220066a2107200c2049480d012010200c4c0d01202b20056a210f20422106201221020340200220092006200920516a290300200620516a2903005422101b2205290300370300200220516a200520516a290300370300200220526a200520526a290300370300200220536a200520536a290300370300200220406a200520406a29030037030020062006204f6a20101b21062002204f6a21022009204f6a200920101b2209200f4f0d04200720064b0d000c040b0b200921020c010b201221020b204221060b20022006200720066b22052005204f706b1095031a20252024200c6a360200200e2029360200200d200d20406a2062204873200b6a204c741096031a20682162206820494b0d0d0b20630d060c010b200b216220630d060b02402061450d00206010190b203f450d0620411019410021020c110b41c4edc2002062200b104a000b41c4edc2002002200b104a000b202920021027000b200220081028000b4101213e0c020b4101213e0c020b410021020c0a0b410121020c090b410121020c080b410021670c030b410121670c030b410021020c040b410221020c030b410321020c020b410321020c010b410321020c000b0b0b206320641027000b102b000b101d000b2018450d00201710190b200141a0036a24000b980201027f230041306b220224000240024002404113101b2203450d002003410f6a41002800aaa041360000200341086a41002900a3a0413700002003410029009ba041370000200341134126101a2203450d0120032001360013200241206a41086a220142003703002002420037032020034117200241206a1001200241086a200129030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a103a20022802202201450d0420002002290224370204200020013602000c010b20004100360208200042013702000b20031019200241306a24000f0b41134101101c000b41264101101c000b41fcf9c00041331030000b900408017f017e017f017e017f017e017f017e230041e0006b22032400200020022900002204370000200341186a2205200241186a2900002206370300200341106a2207200241106a2900002208370300200341086a2209200241086a290000220a370300200041086a200a370000200041106a2008370000200041186a200637000020032004370300200341206a41186a2005290300370300200341206a41106a2007290300370300200341206a41086a20092903003703002003200329030037032002400240024002404110101b2202450d00200241086a41002900d39941370000200241002900cb9941370000200241104120101a2202450d01200220013600102002412041c000101a2202450d02200220032903203700142002412c6a200341386a290300370000200241246a200341206a41106a2903003700002002411c6a200341206a41086a290300370000200341d0006a41086a220142003703002003420037035020024134200341d0006a1001200341c0006a41086a200129030037030020032003290350370340410021010240200341c0006a411041d889c200410041001000417f460d00200341003a0050200341c0006a4110200341d0006a41014100100041016a41014d0d0420032d005021010b20021019200020013a0020200341e0006a24000f0b41104101101c000b41204101101c000b41c0004101101c000b41fcf9c00041331030000bd50501097f230041c0006b220124000240024002400240411a101b2202450d00200241186a41002f00939a413b0000200241106a410029008b9a41370000200241086a41002900839a41370000200241002900fb99413700002002411a4134101a2202450d012002200036001a200141306a41086a22034200370300200142003703302002411e200141306a1001200141206a41086a200329030037030020012001290330370320200141206a41101002200210194113101b2202450d022002410f6a41002800aaa041360000200241086a41002900a3a0413700002002410029009ba041370000200241134126101a2202450d0320022000360013200141306a41086a220342003703002001420037033020024117200141306a1001200141206a41086a200329030037030020012001290330370320200141206a411010022002101920012000104c2001280204210420012802002105024002400240024020012802082202450d0020024105742106200521030340200141186a2207200341186a290000370300200141106a2208200341106a290000370300200141086a2209200341086a290000370300200120032900003703004110101b2202450d02200241086a41002900d39941370000200241002900cb9941370000200241104120101a2202450d03200220003600102002412041c000101a2202450d04200341206a2103200220012903003700142002412c6a2007290300370000200241246a20082903003700002002411c6a2009290300370000200141306a41086a220742003703002001420037033020024134200141306a1001200141206a41086a200729030037030020012001290330370320200141206a4110100220021019200641606a22060d000b0b02402004450d00200510190b200141c0006a24000f0b41104101101c000b41204101101c000b41c0004101101c000b411a4101101c000b41344101101c000b41134101101c000b41264101101c000b980201037f230041306b220224000240024002404117101b2203450d002003410f6a4100290093a041370000200341086a410029008ca04137000020034100290084a04137000020034117412e101a2203450d0120032001370017200241206a41086a22044200370300200242003703202003411f200241206a1001200241086a200429030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a105220022802202204450d0420002002290224370204200020043602000c010b20004100360208200042083702000b20031019200241306a24000f0b41174101101c000b412e4101101c000b41fcf9c00041331030000bcd90020a027f017e097f027e027f037e017f057e177f087e230041800a6b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2204410c4b0d000240024020040e0d00800105080c0b0607040a030901000b20034190096a41086a200141106a2903003703002003200141086a2903002205370390092005a7417e6a220441054b0d8301200241056a280000210620022d0001210720022d00002102024020040e06001d1a1c1920000b4101210820034198096a2802002109200328029409210a200241ff017145200741ff01714101467122024101470d3202402009450d00200a10190b4100210741012106410121090c3f0b200141206a280200210b2001411c6a280200210c200141146a2902002105200141106a280200210d2001410c6a280200210e200141086a2802002107200141046a2802002104200141246a350200210f200141286a3100002110200341f0066a41086a22062002410a6a290100370300200341f0066a41106a2208200241126a290100370300200341f0066a41186a22092002411a6a2901003703002003200241026a2901003703f00620022d0001210a20022d0000210220044102460d0b20044103470d8301200341d0076a41186a200341f0066a41186a290300370300200341d0076a41106a200341f0066a41106a290300370300200341d0076a41086a200341f0066a41086a290300370300200320032903f0063703d007200241ff0171450d15412a2111418d81c00021040cc6010b200141086a2903004202520d830141b781c0002104412d21114101211220022d00000df70120022d000141ff01714102470df701200141106a2903002105200341e0046a41086a22024200370300200342003703e004418698c1004113200341e0046a1001200341d0076a41086a2002290300370300200320032903e0043703d007200341d0076a4110100c0d8a0120024200370300200342003703e004419399c100410d200341e0046a100120034190096a41086a2002290300370300200320032903e0043703900920034190096a411041d889c200410041001000417f460df601200342003703b00520034190096a4110200341b0056a41084100100041016a41084d0d7e20032903b005500df601200341e0046a41086a22024200370300200342003703e004419399c100410d200341e0046a100120034190096a41086a22042002290300370300200320032903e004370390094200210f024020034190096a411041d889c200410041001000417f460d00200342003703b00520034190096a4110200341b0056a41084100100041016a41084d0d800120032903b005210f0b20024200370300200342003703e00441a099c1004115200341e0046a100120042002290300370300200320032903e0043703900920034190096a411041d889c200410041001000417f460d32200342003703b00520034190096a4110200341b0056a41084100100041016a41084d0d800120032903b005200f7c2005560d330cf6010b200341f0046a41086a200141186a290300370300200341f0046a41106a200141206a2903003703002003200141106a2903003703f004200141386a2903002110200141306a290300210f2001410c6a2802002108200141286a2903002105200141086a2802002104200341d8046a41046a200241086a2d00003a00002003200241046a2802003602d8042004417e6a220441044b0d830120022d0001210620022d00002107024020040e05001210110f000b200241096a280000412a200741ff0171220745200641ff017122064101467122041b211120032800d904418d81c00020041b210420070dec0120064101470dec01200241196a2800002106200241156a28000021092002410d6a2900002113200241026a2f0100210a200328028405210e200328028005210b20032903f804211420032802f404210c20032802f004210720032002411d6a350000200241216a3100004220868422153e00cb05200341cf056a20154220883c0000200320032d00d8043a00b2052003200a3b01b005200320063600c705200320093600c305200320133700bb05200320113600b705200320043600b305200841ff01714101470d4620034190096a200741067610612003280298092007413f7122024d0d5420032802900920024105746a220235001b2002411f6a31000042208684210520022f0000200241026a2d00004110747221062002280017210e2002280013210b200229000b21142002280007210c2002280003210741012102200328029409450de8010ce7010b20034190096a41206a200141246a29020037030020034190096a41186a2001411c6a29020037030020034190096a41106a200141146a29020037030020034190096a41086a2001410c6a2902003703002003200141046a29020037039009200341b0056a41206a200241206a280200360200200341b0056a41186a200241186a290200370300200341b0056a41106a200241106a290200370300200341b0056a41086a200241086a290200370300200320022902003703b005200341f8036a20034190096a200341b0056a10b50220032802fc03211120032802f80321044100210b410121124101210741012106410121084101210c0cfa010b200141286a3502002001412c6a3100004220868421052001410d6a2f00002001410f6a2d0000411074722108200141386a290300210f200141306a2903002113200141246a2802002109200141206a280200210a200141186a2902002110200141146a280200210e200141106a28020021062001410c6a2d0000210c20022d0001210420022d00002107200141086a280200220b4102460d08200b4103470d8201200420077241ff01710d10200141c8006a2903002115200141c0006a290300211441012112200c41ff01714101470de201200341b0056a2006410676106120032802b8052006413f7122024d0d4520032802b00520024105746a220235001b2002411f6a31000042208684210520022f0000200241026a2d0000411074722108200228001721092002280013210a200229000b21102002280007210e200228000321064101210220032802b405450de1010ce0010b20034190096a41386a200141c0006a29030037030020034190096a41306a200141386a29030037030020034190096a41286a200141306a29030037030020034190096a41206a200141286a29030037030020034190096a41186a200141206a29030037030020034190096a41106a200141186a29030037030020034190096a41086a200141106a2903003703002003200141086a29030037039009200341b0056a41206a200241206a280200360200200341b0056a41186a200241186a290200370300200341b0056a41106a200241106a290200370300200341b0056a41086a200241086a290200370300200320022902003703b005200341e8036a20034190096a200341b0056a10a40120032802ec03211120032802e8032104410021084101211241012107410121060cf6010b20034190096a41206a200141286a29030037030020034190096a41186a200141206a29030037030020034190096a41106a200141186a29030037030020034190096a41086a200141106a2903003703002003200141086a29030037039009200341b0056a41206a200241206a280200360200200341b0056a41186a200241186a290200370300200341b0056a41106a200241106a290200370300200341b0056a41086a200241086a290200370300200320022902003703b005200341f0036a20034190096a200341b0056a10cb0120032802f403211120032802f00321044100210c410121124101210741012106410121080cf6010b200341b0086a41046a22092001410e6a2f01003b0100200341b0056a41086a220a200141206a290300370300200341b0056a41106a220e200141286a29030037030020032001410a6a2801003602b0082003200141186a2903003703b005200141106a2903002105200141096a2d0000210820022d0001210420022d00002107200141086a2d000022064102460d0820064103460d0720064104470d8001200420077241ff01710d0d200320083a009009200341a0056a41086a22024200370300200342003703a00541e3f9c0004119200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411020034190096a410110030cb9010b20034190096a200141086a41d0001095031a200341b0056a41206a200241206a280200360200200341b0056a41186a200241186a290200370300200341b0056a41106a200241106a290200370300200341b0056a41086a200241086a290200370300200320022902003703b005200341c8046a20034190096a200341b0056a10dd0220032802cc04211120032802c80421044100210a410121124101210741012106410121084101210c4101210b410121090cf7010b200141046a2802004102470d7f200141086a2802002106410121122001410c6a280200210720022d00014101470d0420022d000041ff01710d04200241096a280000211102402007450d00200610190b410021094101210741012106410121084101210c4101210b4101210a4101210e0cd4010b200141086a2d0000220d417e6a220441054b0d7f2002411d6a350000200241216a310000422086842105200241026a2f0100200241046a2d0000411074722108200141106a290300210f200241196a280000210e200241156a280000210b2002410d6a2900002110200241096a2800002109200241056a280000210a2001410c6a2802002107200141096a2d0000210c20022d0001210620022d00002102024020040e06001713141019000b200a418d81c000200241ff0171220245200641ff0171220c4101467122061b21042009412a20061b211120020d38200c4101470d38200141186a2903002113200320053e00cb05200341cf056a20054220883c00002003200e3600c7052003200b3600c305200320103700bb05200320113600b705200320043600b305200320083b01b005200320084110763a00b20520034190056a41086a22024200370300200342003703900541bcb7c100411820034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411041d889c200410041001000417f460d3720034200370398092003420037039009200341e0046a411020034190096a4110410010002202417f460d8a012002410f4d0d8a01200329039009200f5620034198096a290300220520135620052013511b450d3741d4b7c1002104410d21110c380b200141086a2d0000220c417e6a2207410a4b0d7f2002411d6a350000200241216a310000422086842105200241026a2f0100200241046a2d0000411074722106200141186a2903002113200241196a280000210e200241156a280000210b2002410d6a290000210f200241096a2800002108200241056a2800002109200141206a28020021162001410c6a280200210a200141106a2903002210a7210d20022d0001210420022d00002102024020070e0b001f1c1d1a21221e241b23000b410121122009418d81c000200241ff0171220245200441ff017122164101467122071b21042008412a20071b211120020d1f20164101470d1f200320053e00cb05200341cf056a20054220883c00002003200e3600c7052003200b3600c3052003200f3700bb05200320113600b705200320043600b305200320063b01b005200320064110763a00b20520034190096a200341b0056a10bf0120032d0090094101470d5241d9ddc0002104412321110cc5010b200341d0076a41186a2009290300370300200341d0076a41106a2008290300370300200341d0076a41086a2006290300370300200320032903f0063703d007200241ff0171450d0a412a2111418d81c00021040c450b41012112200241056a280000418d81c000200741ff0171220745200441ff0171220d41014671220b1b2104200241096a280000412a200b1b211120070deb01200d4101470deb01200241046a2d00002107200241026a2f0100210b200241196a280000210d200241156a28000021162002410d6a290000211520032002411d6a350000200241216a3100004220868422143e00cb08200341b0086a411f6a20144220883c00002003200d3600c708200320163600c308200320153700bb08200320113600b708200320043600b3082003200b20074110747222023b01b008200320024110763a00b208200c41ff01714101470dd60120034190096a200641067610612003280298092006413f7122024d0d2c20032802900920024105746a220235001b2002411f6a31000042208684210520022f0000200241026a2d0000411074722108200228001721092002280013210a200229000b21102002280007210e2002280003210641012102200328029409450dd5010cd4010b418d81c0002104412a21114100210902402007450d00200610190b4101210741012106410121084101210c4101210b0cf0010b200420077241ff01710d052003200537039009200341a0056a41086a22024200370300200342003703a00541ff80c1004119200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411020034190096a410810030cb1010b200241216a310000210f2002411d6a3500002110200241046a2d0000210b200241026a2f0100210c200241196a280000210d200241156a28000021162002410d6a2900002113200241056a2800002106200241096a2800002102200341e7076a200a290300370000200341ef076a200e2d00003a0000200320083a00d007200320053700d707200320032802b0083600d107200320092f01003b00d507200320032903b0053700df072002412a200741ff0171220745200441ff017122084101467122041b21112006418d81c00020041b210420070dde0120084101470dde0120034190096a41186a200341d0076a41186a29030037030020034190096a41106a200341d0076a41106a29030037030020034190096a41086a200341d0076a41086a290300370300200320032903d007370390094112101b2202450d7e200241106a41002f00a881413b0000200241086a41002900a08141370000200241002900988141370000200241124132101a2202450d7f20022010200f4220868422053e002d2002200c200b4110747222073b00122002200d360029200220163600252002201337001d2002201136001920022004360015200241316a20054220883c0000200241146a20074110763a00004120101b2204450d80012004200329039009370000200441186a20034190096a41186a290300370000200441106a20034190096a41106a290300370000200441086a20034190096a41086a290300370000200341a0056a41086a22074200370300200342003703a00520024132200341a0056a100120034190056a41086a2007290300370300200320032903a0053703900520034190056a411020044120100320041019200210194100210441012112410121070ce9010b41f3bbc100210441c0002111200741ff0171450ddd0120032802d8044104490ddd014112101b2202450d8401200241106a41002f00cae8403b0000200241086a41002900c2e840370000200241002900bae840370000200241124124101a2202450d85012002200836001220034190056a41086a2204420037030020034200370390052002411620034190056a1001200341a0056a41086a200429030037030020032003290390053703a005200341a0056a4110100c2104200210192004450d3b20034190056a41086a2202420037030020034200370390054186ecc000411220034190056a1001200341e0046a41086a200229030037030020032003290390053703e00441002102200341e0046a411041d889c200410041001000417f460d46200342103702b4052003200341e0046a3602b00520034190096a200341b0056a105a2003280290092204450d9101200320032902940922053702940920032004360290092005a72005422088a72202460d470cae010b200620077241ff01710d0220034180056a290300210f20032903f804211020032802f00421064104101b2204450d87012004200836000020034190056a41086a22024200370300200342003703900541b3f8c000411520034190056a1001200341e0046a41086a2207200229030037030020032003290390053703e004200341e0046a4110200441041003200410192003200f3703980920032010370390092002420037030020034200370390054197f8c000411c20034190056a10012007200229030037030020032003290390053703e004200341e0046a411020034190096a41101003200320053703900920024200370300200342003703900541f2ebc000411420034190056a10012007200229030037030020032003290390053703e004200341e0046a411020034190096a410810034104101b2204450d8801200420063600002002420037030020034200370390054198ecc000410d20034190056a10012007200229030037030020032003290390053703e004200341e0046a4110200441041003200410190cae010b41f3bbc100210441c0002111200741ff0171450ddb0120032802d8044102490ddb014112101b2202450d8401200241106a41002f00cae8403b0000200241086a41002900c2e840370000200241002900bae840370000200241124124101a2202450d85012002200836001220034190056a41086a2204420037030020034200370390052002411620034190056a1001200341e0046a41086a200429030037030020032003290390053703e004200341e0046a411041d889c200410041001000417f460d38200342103702a4052003200341e0046a3602a00520034190096a200341a0056a10d0012003290390094201520d88012003280298092104200341b0086a2003419c096a41dc001095031a20034190056a41086a2207420037030020034200370390052002411620034190056a1001200341a0056a41086a200729030037030020032003290390053703a005200341a0056a41101002200341d0076a200341b0086a41dc001095031a200341f0066a200341d0076a41dc001095031a2002101920034190066a200341f0066a41dc001095031a200320043602b005200341b0056a41047220034190066a41dc001095031a200341b0046a200341d0056a20032903c005200341c8056a29030010a8010cad010b200620077241ff0171450d1e0b41e580c00021044128211141012112410121070ce4010b20032800d307418d81c000200a41ff0171220241014622061b210420032800d707412a20061b211120024101470db00120032d00d207210220032f01d007210620032800e707210820032800e307210920032900db072113200320033500eb07200341d0076a411f6a3100004220868422153e00cb05200341b0056a411f6a20154220883c0000200320083600c705200320093600c305200320133700bb05200320113600b705200320043600b3052003200620024110747222023b01b005200320024110763a00b205200341a0056a41086a22024200370300200342003703a00541bcf7c0004108200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411041d889c200410041001000417f460d37200341e8076a4200370300200341d0076a41106a4200370300200341d0076a41086a4200370300200342003703d00720034190056a4110200341d0076a4120410010002202417f460d7c2002411f4d0d7c200341d0076a411f6a310000211320032900d307211520032900db07211420032900e307211720033500eb07211820032f01d0072102200320032d00d2073a009209200320023b01900920034190096a411f6a20133c0000200320183e00ab09200320173700a3092003201437009b0920032015370093090c380b20032800d307418d81c000200a41ff0171220241014622061b210420032800d707412a20061b211120024101470d3a20032d00d207210220032f01d007210620032800e707210820032800e307210920032900db072105200320033500eb07200341d0076a411f6a31000042208684220f3e00cb08200341b0086a411f6a200f4220883c0000200320083600c708200320093600c308200320053700bb08200320113600b708200320043600b3082003200620024110747222023b01b008200320024110763a00b208200341a0056a41086a22024200370300200342003703a00541bcf7c0004108200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411041d889c200410041001000417f460d38200341e8076a4200370300200341d0076a41106a4200370300200341d0076a41086a4200370300200342003703d00720034190056a4110200341d0076a4120410010002202417f460d7c2002411f4d0d7c200341d0076a411f6a310000210520032900d307210f20032900db07211020032900e307211320033500eb07211520032f01d0072102200320032d00d2073a009209200320023b01900920034190096a411f6a20053c0000200320153e00ab09200320133700a3092003201037009b092003200f370093090c390b20034198096a2802002104200328029409210a200220077241ff0171450d1d41002106410121092004450d07200a10190c070b4101210820034198096a280200210a200328029409210e200241ff017145200741ff01714101467122024101470d170240200a450d00200e10190b41002109410121060c240b41012112200620027241ff0171450d1c41e580c0002104412821110c070b4101210941012106200220077241ff01710d0420034190096a41086a29030021054108101b2202450d81012002200537000041e68cc000410a2002410810032002101941002104410121084101210641012109410121070c240b200241ff0171450d1b41b781c0002104412d21110c2b0b410121122009412a200241ff0171220245200641ff017122064101467122041b2111200a418d81c00020041b210420020d0420064101470d04200320053e00cb05200341cf056a20054220883c00002003200e3600c7052003200b3600c305200320103700bb05200320113600b705200320043600b305200320083b01b005200320084110763a00b20520034190056a41086a22024200370300200342003703900541d2b8c100411820034190056a1001200341e0046a41086a200229030037030020032003290390053703e004410021020240200341e0046a411041d889c200410041001000417f460d00200341003a009009200341e0046a411020034190096a41014100100041016a41014d0d830120032d00900921020b200c411874411875410776200c7341187441808080086a41187520024118744118754c0d2d41eab8c1002104411d21110caa010b200620027241ff0171450d1c20071043200710190c050b2003419c096a280200210620034198096a280200210a2003280294092108200220077241ff0171450d1c02402006450d00200641186c21042008210203400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241186a2102200441686a22040d000b0b4101210641002109200a450d00200810190b41e580c000210441282111200328029009417e6a220241054b0d23024020020e06002825242627000b20034198096a280200450d2720032802940910190c270b41012112200a418d81c000200241ff0171220245200641ff0171220c4101467122061b21042009412a20061b211120020d00200c4101470d00200320053e00cb05200341cf056a20054220883c00002003200e3600c7052003200b3600c305200320103700bb05200320113600b705200320043600b305200320083b01b005200320084110763a00b20520034190096a2007104120032802a0092202450d3420032902940921052003419c096a3502002110200341ac096a2802002108200341a8096a280200210420032802a4092106200335029009210f200341b8036a200341b0056a1045024020032903b8032215200f2005422086842213542209200341c0036a290300220f2010422086200542208884220554200f2005511b0d00200341b0056a10a601450d480b41b8b8c1002104411a21112006450da601200210190ca6010b410021060ca6010b200620027241ff0171450d1d0b41e580c0002104412821110ca3010b410121122008412a200241ff0171220245200441ff017122074101467122041b21112009418d81c00020041b210420020d0520074101470d05200320053e00cb05200341cf056a20054220883c00002003200e3600c7052003200b3600c3052003200f3700bb05200320113600b705200320043600b305200320063b01b005200320064110763a00b20520034190056a41086a22024200370300200342003703900541e2c9c000411220034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411041d889c200410041001000417f460db601200342103702b4082003200341e0046a3602b00820034190096a200341b0086a103a2003280290092202450d810120032802940921042002200a4105746a2207450d3f20034198096a280200200a4d0d3f200341b0056a2007460d482007200341b0056a41201097034521072004450db2010cb1010b200420027241ff01710d092003200a3602900920034190056a41086a2202420037030020034200370390054184c9c000411920034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a410410030cb2010b410121122009418d81c000200241ff0171220245200441ff0171221d4101467122071b21042008412a20071b211120020d03201d4101470d032001412c6a3100002115200141286a3502002114200141246a2802002107200320053e00cb08200341cf086a20054220883c00002003200e3600c7082003200b3600c3082003200f3700bb08200320113600b708200320043600b308200320063b01b008200320064110763a00b208200a41ff01714101470d3420034190096a200d4106761061200328029809200d413f7122024d0d3f20032802900920024105746a220435001b2004411f6a31000042208684210520042f0000200441026a2d00004110747221022004280017210720042800132116200429000b2113200428000721062004280003210441012108200328029409450da6010ca5010b410121122008412a200241ff0171220245200441ff017122074101467122041b21112009418d81c00020041b210420020d0220074101470d02200320053e00cb08200341b0086a411f6a20054220883c00002003200e3600c7082003200b3600c3082003200f3700bb08200320113600b708200320043600b308200320063b01b008200320064110763a00b20820034190096a200341b0086a10bf0120032d0090094101470d342003419c096a2902002105200341a4096a290200210f200341ac096a3502002110200329029409211320032f009109210220032d0093092104200341b0056a411f6a200341b0096a3100003c0000200320103e00cb05200320043a00b205200320023b01b0052003200f3700c305200320053700bb05200320133700b305200341d0076a200341b0056a10ac0120032802d0072102024020032802d8072207200a4d0d00200341b0086a2002200a4105746a2204460d452004200341b0086a4120109703450d450b024020032802d407450d00200210190b418fdfc0002104411421110cb8010b200420027241ff01710d062003200a3602900920034190056a41086a22024200370300200342003703900541eedbc000411620034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a410410030caf010b410121122009418d81c000200241ff0171220245200441ff0171220c4101467122071b21042008412a20071b211120020d00200c4101470d00200320053e00ab09200341af096a20054220883c00002003200e3600a7092003200b3600a3092003200f37009b0920032011360097092003200436009309200320063b019009200320064110763a00920920034190056a41086a22024200370300200342003703900541e2c9c000411220034190056a1001200341e0046a41086a200229030037030020032003290390053703e00441002102200341e0046a411041d889c200410041001000417f460d35200342103702b4082003200341e0046a3602b008200341b0056a200341b0086a103a20032802b0052206450d7d200341b8056a280200210220032802b40521040c360b410021070cce010b200420027241ff01710d032003201042808080807083201042ffffffff0f83843703900920034190056a41086a22024200370300200342003703900541d4dbc000411a20034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a410810030cac010b200420027241ff01710d022003201042808080807083201042ffffffff0f83843703900920034190056a41086a22024200370300200342003703900541c1cbc000411720034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a410810030cab010b200420027241ff0171450d2541e580c0002104412821114100210741012112200d0da3010ccb010b200420027241ff0171450d250b41e580c0002104412821110cb0010b2006418d81c00020021b2104412a2111410021090240200a450d00200e10190b410121060c070b2006418d81c00020021b2104412a21114100210702402009450d00200a10190b41012106410121090c0d0b20032903f00421052003200341f0046a41086a29030037039809200320053703900920034190056a41086a22024200370300200342003703900541aee8c000410c20034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a411010030c8d010b4205200f7c2005580dc3010b41d091c3001029000b41f08cc0004105200a2003419c096a28020010034101210802402004450d00200a10190b410021060c060b2007104e0c94010b410041b781c000200741ff01714102461b2104412d21114101210841012106410121090b410121070c060b410021022003280294090da7010ca8010b20034190056a41086a220242003703002003420037039005419c82c000410d20034190056a1001200341e0046a41086a2204200229030037030020032003290390053703e004420021050240200341e0046a411041d889c200410041001000417f460d002003420037039009200341e0046a411020034190096a41084100100041016a41084d0d5220032903900921050b20024200370300200342003703900541b599c100411620034190056a10012004200229030037030020032003290390053703e004200341e0046a411041d889c200410041001000417f460d1e2003420037039009200341e0046a411020034190096a41084100100041016a41084d0d5220032903900921100c1f0b0240200641186c2202450d00200820026a21042008210203402002280200200241086a2802002002410c6a280200200241146a2802001003200241186a22022004470d000b0b02402006450d00200641186c21042008210203400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241186a2102200441686a22040d000b0b410121060240200a450d00200810190b410021080b410121090b410121070b410021040b0240024002400240200328029009417e6a220241054b0d00024020020e06000c02010304000b2007450d0b20034198096a280200450d0b20032802940910190c0b0b20034190096a10650c0a0b2009450d0920034198096a280200450d0920032802940910190c090b2006450d0820034198096a280200450d0820032802940910190c080b2008450d07024020034190096a410c6a2802002207450d002003280294092102200741186c210703400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241186a2102200741686a22070d000b0b20034198096a280200450d0720032802940910190c070b200341b0056a200f104f024020032802b805220420074d0d00024020032802b005200741e0006c6a22022d0000410e460d00200210430b2002410e3a0000200241016a20034190096a41df001095031a0b4117101b2202450d5c2002410f6a4100290093a041370000200241086a410029008ca04137000020024100290084a04137000020024117412e101a2202450d5d2002200f3700172003411f360294092003200236029009200341b0056a20034190096a10512002101920032802b005210602402004450d00200441e0006c2104200621020340024020022d0000410e460d00200210430b200241e0006a2102200441a07f6a22040d000b0b024020032802b405450d00200610190b4101210241012112200d4102460d740c88010b20034198036a200341b0056a104541e1b7c1002104411a21112003290398032210200f542202200341a0036a290300220520135420052013511b0d00200341b0056a10a601450d250b20071043200710190c84010b20034190096a10650c030b20034198096a280200450d0220032802940910190c020b2006450d0120034198096a280200450d0120032802940910190c010b2009450d00024020034190096a410c6a2802002207450d002003280294092102200741186c210703400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241186a2102200741686a22070d000b0b20034198096a280200450d0020032802940910190b41012107410021120cb1010b200841087621060ca3010b4100210220032802b4050d9a010c9b010b411a101b2202450d55200241186a41002f00939a413b0000200241106a410029008b9a41370000200241086a41002900839a41370000200241002900fb99413700002002411a4134101a2202450d562002200736001a20034190056a41086a2204420037030020034200370390052002411e20034190056a1001200341a0056a41086a200429030037030020032003290390053703a005200341a0056a4110100c2104200210192004450d18200341d8036a200341b0056a1045200341d8036a41086a290300210f20032903d8032105200341c8036a200341b0056a104420032903c803420020057d85200341c8036a41086a2903004200200f7d2005420052ad7d858450450d1a41a9b9c1002104413021110c7c0b200341d0076a200341b0086a41dc001095031a200210190b41f8f8c00021044119211141012112410121070cac010b200341a8096a420037030020034190096a41106a420037030020034190096a41086a420037030020034200370390090b0240200341b0056a20034190096a4120109703450d0041e6f7c0002104413121110c780b200741ff01714101470d0f20034190096a200e4106761061200328029809200e413f7122024d0d1a20032802900920024105746a220435001b2004411f6a31000042208684210f20042f0000200441026a2d00004110747221022004280017210b2004280013210c200429000b21052004280007210d2004280003210e41012104200328029409450d730c720b200341a8096a4200370300200341a0096a420037030020034190096a41086a420037030020034200370390090b200341b0086a20034190096a4120109703450d0141c4f7c0002104412221110b20071043200710190c740b20034190096a200741d8001095031a41002104200341003b01b005200341d0046a20034190096a200341b0056a1050200320032802d004453a0092092003410c3b01900920034190096a103d200710190c710b20032010422088a7360298092003200d360294092003200a36029009200341143602b405200341dec8c0003602b00520034190096a200341b0056a109801200d450d8401200a10190c84010b200141096a2d0000210420034190056a41086a22024200370300200342003703900541accbc000411520034190056a1001200341e0046a41086a2206200229030037030020032003290390053703e00441002107200341e0046a411041d889c20041001003200320043a00900920024200370300200342003703900541e3f9c000411920034190056a10012006200229030037030020032003290390053703e00441012112200341e0046a411020034190096a410110030c85010b4194b8c1002104412421110c710b410021022003280294090d92010c93010b20034100360298092003420437039009410421040b200241016a22072002490dad0120024101742206200720072006491b2207ad4202862205422088a70dad012005a722064100480dad012002450d08200420024102742006101a2204450d090c650b42e80721100b20034190096a200741d8001095031a200341b0056a201020057c20034190096a200c200f1048200341b8056a280200211120032802b405210220032802b00521042007101941012112410021062002410020044101461b21040c6d0b20142015422086842105200a41087621022010422088a72106200d21040c720b411a211141f5dec00021040c83010b20034190056a41086a22024200370300200342003703900541e2c9c000411220034190056a1001200341e0046a41086a200229030037030020032003290390053703e00441002108200341e0046a411041d889c200410041001000417f460d0c200342103702b4082003200341e0046a3602b00820034190096a200341b0086a103a2003280290092206450d4a20034198096a280200210820032802940921090c0d0b200f201042208684210f200741087621020c640b41012106410021040b20034190056a41086a22074200370300200342003703900541f4c9c000411d20034190056a1001200341e0046a41086a200729030037030020032003290390053703e0040240200341e0046a411041d889c200410041001000417f460d00200341003602b005200341e0046a4110200341b0056a41044100100041016a41044d0d3120032802b00521072004450d5d0c5c0b4104210720040d5b0c5c0b2006101b22040d5c0b20064104101c000b4187b9c1002104412221110c630b2004450d76200210190c760b20034190096a41186a200341b0056a41186a29030037030020034190096a41106a200341b0056a41106a29030037030020034190096a41086a200341b0056a41086a290300370300200320032903b005370390094110101b2202450d43200241086a41002900d39941370000200241002900cb9941370000200241104120101a2202450d44200220073600102002412041c000101a2202450d4520022003290390093700142002412c6a20034190096a41186a2204290300370000200241246a20034190096a41106a22062903003700002002411c6a20034190096a41086a220829030037000020034190056a41086a2209420037030020034200370390052002413420034190056a1001200341a0056a41086a200929030037030020032003290390053703a005200341a0056a4110100c21092002101920090d53200341b0086a2007104c2004200341b0056a41186a2903003703002006200341b0056a41106a2903003703002008200341b0056a41086a290300370300200320032903b0053703900920032802b408220a20032802b8082202470d0f200241016a22092002490da0012002410174220a20092009200a491b220aad4205862205422088a70da0012005a7220e4100480da0012002450d1420032802b0082002410574200e101a2209450d150c510b410021082003280294090d650c660b20034188036a200341b0056a1044200341b0056a2003290388032215200f7c221420034188036a41086a29030020137c2014201554ad7c1047200341b0056a2010200f7d200520137d2002ad7d104620034190056a41086a22024200370300200342003703900541fbb7c100411920034190056a1001200341e0046a41086a200229030037030020032003290390053703e004410021060240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d3e20032802900921060b2003200641016a3602900920034190056a41086a22044200370300200342003703900541fbb7c100411920034190056a1001200341e0046a41086a2208200429030037030020032003290390053703e004200341e0046a411020034190096a410410034120101b2202450d44200220032903b005370000200341a4096a428180808010370200200241186a200341b0056a41186a290300370000200241106a200341b0056a41106a290300370000200241086a200341b0056a41086a2903003700002003200f37039009200320023602a0092003201337039809200620034190096a108c02200442003703002003420037039005419b9fc100411520034190056a10012008200429030037030020032003290390053703e00441002102200341e0046a411041d889c200410041001000417f460d07200342103702b4082003200341e0046a3602b00820034190096a200341b0086a10402003280290092208450d4720034198096a280200210220032802940921090c080b200341a8036a200341b0056a1044200341b0056a20032903a803221020137c2214200341a8036a41086a29030020057c2014201054ad7c1047200341b0056a201520137d200f20057d2009ad7d1046200341d0076a41186a2209200341b0056a41186a290300370300200341d0076a41106a220a200341b0056a41106a290300370300200341d0076a41086a220e200341b0056a41086a290300370300200320032903b0053703d00720062004470d05200641016a220b2006490d9d012006410174220c200b200b200c491b220bad420586220f422088a70d9d01200fa7220c4100480d9d012006450d0f20022006410574200c101a22020d100c470b410021042003280294090d570c580b41012106410021090b200620084105746a2107200621020340200720026b41ff004d0d06200341b0056a2002460d072002200341b0056a4120109703450d07200241206a2204200341b0056a460d072004200341b0056a4120109703450d07200241c0006a2204200341b0056a460d072004200341b0056a4120109703450d07200241e0006a2204200341b0056a460d0720024180016a21022004200341b0056a41201097030d000c070b0b200341d0076a41086a22062007417f6a2207360200200220074105746a220229000021052002290008210f20022900102110200441186a200241186a290000370000200420103700102004200f3700082004200537000020034190096a41086a2006280200360200200320032903d00737039009200341b0056a20034190096a10c0014112101b2202450d40200241106a41002f00f3de403b0000200241086a41002900ebde40370000200241002900e3de40370000200241124132101a2202450d41200220032903b0083700122002412a6a200341b0086a41186a2207290300370000200241226a200341b0086a41106a22062903003700002002411a6a200341b0086a41086a220829030037000020034190056a41086a2204420037030020034200370390052002413220034190056a1001200341a0056a41086a200429030037030020032003290390053703a005200341a0056a411010022002101920034190096a41186a200729030037030020034190096a41106a200629030037030020034190096a41086a2008290300370300200320032903b00837039009200442003703002003420037039005419c82c000410d20034190056a1001200341e0046a41086a2202200429030037030020032003290390053703e004420021050240200341e0046a411041d889c200410041001000417f460d00200342003703f006200341e0046a4110200341f0066a41084100100041016a41084d0d3720032903f00621050b20044200370300200342003703900541c1cbc000411720034190056a10012002200429030037030020032003290390053703e004200341e0046a411041d889c200410041001000417f460d06200342003703f006200341e0046a4110200341f0066a41084100100041016a41084d0d3720032903f006210f410f2104410f101b2202450d070c490b4101210720040d680c690b2006210b0c0a0b41082108410021090b20034190096a2007108b02200341d0076a41186a220a200341b0056a41186a290300370300200341d0076a41106a220e200341b0056a41106a290300370300200341d0076a41086a220b200341b0056a41086a290300370300200320032903b0053703d00720092002470d43200241016a22042002490d950120024101742209200420042009491b2209ad4207862205422088a70d95012005a722044100480d95012002450d05200820024107742004101a2208450d060c430b024020022007460d000340200341b0056a2002460d022002200341b0056a4120109703450d022007200241206a2202470d000b0b410f101b2202450d3f200241076a41002900fdbd40370000200241002900f6bd403700002002410f412f101a2202450d40200220032903b00537000f200241276a200341b0056a41186a22042903003700002002411f6a200341b0056a41106a2207290300370000200241176a200341b0056a41086a220e2903003700002003427f3703900920034190056a41086a220b420037030020034200370390052002412f20034190056a1001200341e0046a41086a200b29030037030020032003290390053703e004200341e0046a411020034190096a4108100320021019200341d0076a41186a220b2004290300370300200341d0076a41106a22042007290300370300200341d0076a41086a2207200e290300370300200320032903b0053703d00720092008470d41200841016a22022008490d940120084101742209200220022009491b2209ad4205862205422088a70d94012005a722024100480d94012008450d0a200620084105742002101a2206450d0b0c410b41fcddc0002104411f21112009450d5d200610190c5d0b42e807210f410f2104410f101b22020d420b20044101101c000b20032802b00821090c420b2004101b22080d3d0b20044108101c000b200c101b2202450d370b200220044105746a220620032903d007370000200641186a2009290300370000200641106a200a290300370000200641086a200e2903003700004101211220034190096a41186a200441016a360200200341a4096a200b36020020032005370398092003201337039009200320083602ac09200320023602a009200720034190096a108c020c510b200e101b22090d3c0b200e4101101c000b2002101b22060d360b20024101101c000b419096c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41d8b1c2001029000b4188fdc2001029000b41a896c3001029000b41a0fdc2001029000b418891c3001029000b41f090c3001029000b418cc2c3001029000b4184abc3001029000b41f8e3c2001029000b41b891c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41124101101c000b41324101101c000b41204101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41124101101c000b41244101101c000b41124101101c000b41244101101c000b41044101101c000b41044101101c000b41fcf9c00041331030000b41084101101c000b41174101101c000b412e4101101c000b41fcf9c00041331030000b411a4101101c000b41344101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41104101101c000b41204101101c000b41c0004101101c000b41204101101c000b41124101101c000b41324101101c000b41fcf9c00041331030000b200c4101101c000b410f4101101c000b412f4101101c000b200620084105746a220220032903d007370000200241186a200b290300370000200241106a2004290300370000200241086a20072903003700002003200841016a3602980920032009360294092003200636029009200341123602b408200341e2c9c0003602b00820034190096a200341b0086a10980102402009450d00200610190b410021040c1b0b20082002410774220c6a20034190096a41d80010950322042006360258200441f4006a200a290300370200200441ec006a200e290300370200200441e4006a200b290300370200200420032903d00737025c2003200241016a22023602980920032009360294092003200836029009200341153602b4082003419b9fc1003602b00820034190096a200341b0086a104202402002450d00200c4180016a21042008210203402002104320024180016a2102200441807f6a22040d000b0b02402009450d00200810190b200341a8096a2013370300200341a0096a200f3703002003419c096a20063602004100210220034198096a41003a0000200341053a00900920034190096a103d200710432007101941012112200d4102470d140b2002450d150c140b41002107200241076a41002900fdbd40370000200241002900f6bd40370000024020022004412f101a2202450d00200220032903900937000f200241276a200341a8096a2903003700002002411f6a20034190096a41106a290300370000200241176a20034190096a41086a2903003700002003200f20057c3703f00620034190056a41086a2204420037030020034200370390052002412f20034190056a1001200341e0046a41086a200429030037030020032003290390053703e004200341e0046a4110200341f0066a41081003200210190c230b412f4101101c000b2003200a3602b408200320093602b0080b200341b0086a41086a200241016a360200200920024105746a2202200329039009370000200241186a20034190096a41186a290300370000200241106a20034190096a41106a290300370000200241086a20034190096a41086a2903003700004113101b2202450d012002410f6a41002800aaa041360000200241086a41002900a3a0413700002002410029009ba041370000200241134126101a2202450d022002200736001320034117360294092003200236029009200341b0086a20034190096a10980120021019200a450d00200910190b2004200341b0056a41186a2903003703002006200341b0056a41106a2903003703002008200341b0056a41086a290300370300200320032903b0053703900902400240024002404110101b2202450d00200241086a41002900d39941370000200241002900cb9941370000200241104120101a2202450d01200220073600102002412041c000101a2202450d0220022003290390093700142002412c6a200341a8096a290300370000200241246a20034190096a41106a2903003700002002411c6a20034190096a41086a290300370000410121124101101b2204450d032004200c3a000020034190056a41086a2207420037030020034200370390052002413420034190056a1001200341e0046a41086a200729030037030020032003290390053703e004200341e0046a411020044101100320041019200210190c150b41104101101c000b41204101101c000b41c0004101101c000b41014101101c000b41134101101c000b41264101101c000b200610190b0240200220074d0d0020034190096a200a10af012104410d21110c230b41a3dfc0002104413921110c220b2003200736029409200320043602900920034198096a28020021020b20034198096a200241016a360200200420024102746a2008360200200341123602b40520034186ecc0003602b00520034190096a200341b0056a105b200328029409450d00200410190b410021040c2c0b20032802900910190b20040d004115211141bde3c10021040c030b42002113200341a0056a41086a22044200370300200342003703a00541bcf7c0004108200341a0056a100120034190056a41086a2004290300370300200320032903a00537039005410021070240024020034190056a411041d889c200410041001000417f460d00200341e8076a4200370300200341d0076a41106a4200370300200341d0076a41086a4200370300200342003703d00720034190056a4110200341d0076a4120410010002204417f460d032004411f4d0d0320032f01d00720032d00d20741107472210420033500eb07200341d0076a411f6a31000042208684211020032800e707210620032800e307210720032900db07211320032800d707210820032800d30721090c010b41002104410021064200211041002109410021080b200341b1096a20104220883c0000200341ad096a20103e0000200341a9096a2006360000200341a5096a20073600002003419d096a201337000020034199096a200836000020032009360095092003418c023b019009200320043b019209200320044110763a00940920034190096a103d2003200f3e00ab09200341af096a200f4220883c00002003200b3600a7092003200c3600a3092003200537009b092003200d360097092003200e36009309200320023b019009200320024110763a009209200341a0056a41086a22024200370300200342003703a00541bcf7c0004108200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411020034190096a41201003410021040b0c010b41fcf9c00041331030000b4100210e410121124101210741012106410121084101210c4101210b410121094101210a20012d00002202410c4d0d390c400b41002106410121120b410121070c310b200d4105470d010b20071043200710190b41002106410121070c100b20032802900910190b20080d004115211141bde3c10021040c020b200320053e00cb05200341cf056a20054220883c0000200320073600c705200320163600c305200320133700bb05200320063600b705200320043600b305200320023b01b005200320024110763a00b20520034190096a200341b0086a10bf01024020032d0090094101470d00419bdec0002104412621110c020b20034190056a41086a22024200370300200342003703900541e2c9c000411220034190056a1001200341e0046a41086a200229030037030020032003290390053703e0044100210202400240024002400240200341e0046a411041d889c200410041001000417f460d00200342103702d4072003200341e0046a3602d00720034190096a200341d0076a103a2003280290092206450d0220034198096a280200210220032802940921080c010b41012106410021080b200620024105746a2107200621020240024002400240024002400240024002400340200720026b41ff004d0d01200341b0086a2002460d082002200341b0086a4120109703450d08200241206a2204200341b0086a460d022004200341b0086a4120109703450d03200241c0006a2204200341b0086a460d042004200341b0086a4120109703450d05200241e0006a2204200341b0086a460d0620024180016a21022004200341b0086a41201097030d000c070b0b024020022007460d000340200341b0086a2002460d092002200341b0086a4120109703450d082007200241206a2202470d000b0b4100210220080d090c0a0b200341b0086a21040b2004210220080d070c080b200341b0086a21040b2004210220080d050c060b200341b0086a21040b200421020b2008450d030c020b200341b0086a210220080d010c020b41fcf9c00041331030000b200610190b02402002450d0041c1dec0002104412221110c020b200341d0076a200341b0056a10ac0120034190096a41186a200341b0086a41186a29030037030020034190096a41106a200341b0086a41106a29030037030020034190096a41086a200341b0086a41086a290300370300200320032903b008370390090240024002400240024020032802d40720032802d8072202470d00200241016a22042002490d3c20024101742207200420042007491b2207ad4205862205422088a70d3c2005a722064100480d3c2002450d0120032802d00720024105742006101a2204450d020c030b20032802d00721040c030b2006101b22040d010b20064101101c000b200320073602d407200320043602d0070b200341d0076a41086a2207200241016a360200200420024105746a2202200329039009370000200241186a20034190096a41186a290300370000200241106a20034190096a41106a290300370000200241086a20034190096a41086a220229030037000020022007280200360200200320032903d00737039009200341b0056a20034190096a10c0014112101b2202450d03200241106a41002f00f3de403b0000200241086a41002900ebde40370000200241002900e3de40370000200241124132101a2202450d04200220032903b0083700122002412a6a200341c8086a290300370000200241226a200341b0086a41106a2903003700002002411a6a200341b0086a41086a29030037000020034190056a41086a2204420037030020034200370390052002413220034190056a1001200341e0046a41086a200429030037030020032003290390053703e004200341e0046a4110200341b0056a4120100320021019410f101b2202450d0541002104200241076a41002900fdbd40370000200241002900f6bd403700002002410f412f101a2202450d06200220032903b00837000f200241276a200341c8086a2903003700002002411f6a200341b0086a41106a290300370000200241176a200341b0086a41086a2903003700002003427f3703900920034190056a41086a2207420037030020034200370390052002412f20034190056a1001200341e0046a41086a200729030037030020032003290390053703e004200341e0046a411020034190096a41081003200210190b0b4100210741012112200c4104460d28200c4106460d2802400240200c410c470d00410021074100450d010c2a0b200c410c490d290b200d450d280b200a10190c270b41124101101c000b41324101101c000b410f4101101c000b412f4101101c000b200210190b2007450d0320034190096a41186a200341b0056a41186a29030037030020034190096a41106a200341b0056a41106a29030037030020034190096a41086a200341b0056a41086a290300370300200320032903b00537039009200320133703b8082003201042808080807083201042ffffffff0f83843703b008200320163602c008411c101b2202450d06200241186a41002800a9ca40360000200241106a41002900a1ca40370000200241086a4100290099ca4037000020024100290091ca403700002002411c413c101a2202450d07200220032903900937001c200241346a200341a8096a2903003700002002412c6a20034190096a41106a290300370000200241246a20034190096a41086a290300370000200341003602d807200342013703d007200341b0086a41106a200341d0076a105d2003200341b0086a3602f006200341f0066a200341d0076a10b40120032802d407210720032802d807210620032802d007210420034190056a41086a2208420037030020034200370390052002413c20034190056a1001200341e0046a41086a200829030037030020032003290390053703e004200341e0046a411020042006100302402007450d00200410190b200210190b410021070b410121120b410121060c010b41d8cbc0002104410d21110c040b410121084101210c4101210b410121094101210a4101210e0b4100210420012d00002202410c4d0d220c290b411c4101101c000b413c4101101c000b41002107410121120c180b20032802900910190b2002450d080b200320053e00cb05200341b0056a411f6a20054220883c0000200320093600c7052003200a3600c305200320103700bb052003200e3600b705200320063600b305200320083b01b005200320084110763a00b205200341f8026a200341b0086a1045200341f8026a41086a290300211020032903f8022115200341e8026a200341b0056a1045200341e8026a41086a290300211720032903e802211842002105200341a0056a41086a22024200370300200342003703a00502400240024002400240024002400240024002400240201820178422194200510d004193fbc0004114200341a0056a1001200341d0076a41086a2002290300370300200320032903a0053703d007200341d0076a411041d889c200410041001000417f460d0320034200370398092003420037039009200341d0076a411020034190096a4110410010002202417f460d052002410f4d0d0520034198096a290300211a0c010b41fffac0004114200341a0056a1001200341d0076a41086a2002290300370300200320032903a0053703d007200341d0076a411041d889c200410041001000417f460d0120034200370398092003420037039009200341d0076a411020034190096a4110410010002202417f460d072002410f4d0d0720034198096a290300211a0b20032903900921050c020b420021050b4200211a0b0240201320057c221b2013542202200f201a7c2002ad7c2214200f542014200f511b450d004128211141de97c100210441012112410121070c1c0b4110101b2202450d01200241086a41002900b09741370000200241002900a89741370000200241104130101a2202450d02200220032903b008370010200241286a200341b0086a41186a290300370000200241206a200341b0086a41106a290300370000200241186a200341b0086a41086a29030037000042002133200341a0056a41086a22044200370300200342003703a00520024130200341a0056a1001200341d0076a41086a2004290300370300200320032903a0053703d0070240024002400240200341d0076a411041d889c200410041001000417f460d0020034200370398092003420037039009200341d0076a411020034190096a4110410010002204417f460d032004410f4d0d0320034198096a2903002134200329039009213520034200370398092003420037039009200341d0076a411020034190096a4110411010002204417f460d032004410f4d0d0320034190096a41086a2903002136200329039009213720021019200341d8026a200341b0086a1045200341d8026a41086a290300213820032903d80221394200213a200341a0056a41086a22024200370300200342003703a005419c82c000410d200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900542002133024020034190056a411041d889c200410041001000417f460d00200342003703900920034190056a411020034190096a41084100100041016a41084d0d0320032903900921330b200341b8026a2036420020334200109903200341c8026a2033420020374200109903200341a8026a420042002037420010990342002133024020032903b00220032903c00284420052200341c8026a41086a290300223620032903a80220032903b8027c7c2237203654720d002034203720032903c802223a203554203720345420372034511b22021b20377d2035203a20021b2237203a54ad7d21332037203a7d213a0b203320382039203a56203820335620382033511b22021b2138203a203920021b21330c010b20021019420021380b02402015201b7d223a201556201020147d2015201b54ad7d221520105620152010511b450d00411d211141dfcec100210441012112410121070c1e0b0240203a203354201520385420152038511b450d004126211141b897c100210441012112410121070c1e0b201950450d07200341a0056a41086a22024200370300200342003703a00541e6fbc000411b200341a0056a1001200341d0076a41086a2002290300370300200320032903a0053703d007200341d0076a411041d889c200410041001000417f460d0720034200370398092003420037039009200341d0076a411020034190096a4110410010002202417f460d062002410f4d0d0620032903900920135620034198096a2903002210200f562010200f511b450d07411f211141fccec100210441012112410121070c1d0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41104101101c000b41304101101c000b41fcf9c00041331030000b41fcf9c00041331030000b411e2111200341b0086a10a60122040d0a0240201820137c221420185422022017200f7c2002ad7c221020175420102017511b450d00412d2111419bcfc100210441012112410121070c160b02400240200341b0086a200341b0056a4120109703450d00200341b0086a203a2015104642002115200341a0056a41086a22024200370300200342003703a00541a7fbc0004116200341a0056a1001200341e0046a41086a2002290300370300200320032903a0053703e00402400240200341e0046a411041d889c200410041001000417f460d0020034200370398092003420037039009200341e0046a411020034190096a4110410010002202417f460d032002410f4d0d0320034198096a290300211720032903900921150c010b420021170b0240201520057d22182015562017201a7d2015200554ad7d221520175620152017511b0d0020032018370390092003201537039809200341a0056a41086a22024200370300200342003703a00541a7fbc0004116200341a0056a100120034190056a41086a2002290300370300200320032903a0053703900520034190056a411020034190096a411010030b200341b0056a2014201010591a200341d0076a41186a200341b0086a41186a2202290300370300200341d0076a41106a200341b0086a41106a2204290300370300200341d0076a41086a200341b0086a41086a2207290300370300200320032903b0083703d00720034190096a41086a41023a000020034199096a20032903b008370000200341a1096a2007290300370000200341a9096a2004290300370000200341b1096a2002290300370000200341b9096a20032903b005370000200341c1096a200341b0056a41086a290300370000200341c9096a200341b0056a41106a290300370000200341d1096a200341b0056a41186a290300370000200341023a009009200341f8096a201a370300200341f0096a2005370300200341e8096a200f370300200341e0096a201337030020034190096a103d0b41002104410121120c040b41fcf9c00041331030000b20032802b00510190b2002450d020b200320053e00ab09200341af096a20054220883c0000200320093600a7092003200a3600a3092003201037009b092003200e360097092003200636009309200320083b019009200320084110763a00920920034190096a2013200f104620034190096a201420151047410021040b4101210741012106410121084101210c4101210b410121094101210a4101210e20012d00002202410c4d0d180c1f0b4115211141bde3c10021040c0f0b20032802900910190b20020d010b41bde3c1002104411521110c020b20034190056a41086a2202420037030020034200370390054197f8c000411c20034190056a1001200341e0046a41086a2204200229030037030020032003290390053703e00402400240200341e0046a411041d889c200410041001000417f460d0020034200370398092003420037039009200341e0046a411020034190096a4110410010002208417f460d052008410f4d0d0520034198096a290300211320032903900921150c010b42002115420021130b20024200370300200342003703900541b3f8c000411520034190056a10012004200229030037030020032003290390053703e00402400240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d0420033502900921170c010b420021170b20034190046a200f42002017420010990320032903980421172003290390042118200341a0046a200341b0056a104541c8f8c0002104411a211120032903a004221a201542edeb82bdef9804201842c0843d8020174200521b2217201720155420134200522013501b22021b2217542208200341a8046a29030022152013420020021b22135420152013511b0d01200341b0056a10a6010d0120034180046a200341b0056a1044200341b0056a200329038004221820177c221b20034180046a41086a29030020137c201b201854ad7c1047200341b0056a201a20177d201520137d2008ad7d104620034190056a41086a22024200370300200342003703900541e2f8c000411620034190056a1001200341e0046a41086a200229030037030020032003290390053703e004410021040240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d0520032802900921040b2003200441016a3602900920034190056a41086a22024200370300200342003703900541e2f8c000411620034190056a1001200341e0046a41086a200229030037030020032003290390053703e004200341e0046a411020034190096a4104100320034190096a41186a200341b0056a41186a29030037030020034190096a41106a200341b0056a41106a29030037030020034190096a41086a200341b0056a41086a290300370300200320032903b005370390094112101b2202450d05200241106a41002f00cae8403b0000200241086a41002900c2e840370000200241002900bae840370000200241124124101a2208450d06200820043600124120101b2202450d072002200329039009370000200241186a20034190096a41186a290300370000200241106a20034190096a41106a290300370000200241086a20034190096a41086a2903003700002002412041c000101a2202450d082002200f370020200241286a2010370000200241c000418001101a2202450d09200220053e004b200220063b0030200220173700502002200e3600472002200b3600432002201437003b2002200c36003720022007360033200241cf006a20054220883c0000200241326a20064110763a0000200241d8006a201337000020034190056a41086a2207420037030020034200370390052008411620034190056a1001200341a0056a41086a200729030037030020032003290390053703a005200341a0056a4110200241e000100320021019200810192003419c096a20043602004100210420034190096a41086a41003a00002003410a3a00900920034190096a103d0b41012112410121070c0b0b41012112410121070c0a0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41124101101c000b41244101101c000b41204101101c000b41c0004101101c000b4180014101101c000b200320053703b005200341e0046a41086a22024200370300200342003703e004419399c100410d200341e0046a100120034190096a41086a22042002290300370300200320032903e0043703900920034190096a4110200341b0056a41081003200341013a00b00520024200370300200342003703e004418698c1004113200341e0046a100120042002290300370300200320032903e0043703900920034190096a4110200341b0056a41011003200341d0076a41086a22024200370300200342003703d00741a099c1004115200341d0076a1001200341a0056a41086a2002290300370300200320032903d0073703a00502400240200341a0056a411041d889c200410041001000417f460d002003420037039009200341a0056a411020034190096a41084100100041016a41084d0d0f200329039009210f0c010b4205210f0b200341d0076a41086a22024200370300200342003703d00741be82c0004112200341d0076a100120034190056a41086a22072002290300370300200320032903d0073703900541002104410121120240024020034190056a411041d889c200410041001000417f460d00200342003703900920034190056a411020034190096a41084100100041016a41084d0d0e2003290390092110410021060c010b410121060b200320053703900920024200370300200342003703d00741be82c0004112200341d0076a100120072002290300370300200320032903d0073703900520034190056a411020034190096a410810032010500d0020060d00427f200f200f7c22132013200f541b220f4200510d0b2005200f8022052010200f80220f580d0a2005200f42017c2210510d004200211b200341d0076a41086a22024200370300200342003703d0074181fcc0004112200341d0076a100120034190056a41086a2002290300370300200320032903d007370390050240024020034190056a411041d889c200410041001000417f460d00200342103702b405200320034190056a3602b00520034190096a200341b0056a103a200328029009221c450d0b200329029409211b0c010b4101211c0b02402005200f427f857ca7221e450d00201b422088a7221f201e4d0d002010a7212020034199096a2121200341c8096a2122410021230340201c202320206a201f704105746a22022900002105200241086a290000210f200241106a2900002110200341f0046a41186a2224200241186a290000370300200341f0046a41106a22252010370300200341f0046a41086a2226200f370300200320053703f004200341a0056a41086a22274200370300200342003703a00541dec8c0004114200341a0056a1001200341e0046a41086a22282027290300370300200320032903a0053703e004024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200341e0046a411041d889c200410041001000417f460d00200342103702b4052003200341e0046a3602b00520034190096a200341b0056a103a2003280290092202450d022003280294092104200220034190096a41086a280200200341f0046a108a02210702402004450d00200210190b2007450d010c230b41014100200341f0046a108a020d220b4112101b2202450d02200241106a41002f0082c94022293b0000200241086a41002900fac8402217370000200241002900f2c8402218370000200241124132101a2202450d03200220032903f0043700122002412a6a2024290300370000200241226a20252903003700002002411a6a202629030037000020274200370300200342003703a00520024132200341a0056a100120282027290300370300200320032903a0053703e0040240024002400240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d02200328029009212a200210194112101b22020d010c080b4100212a200210194112101b2202450d070b200241106a20293b0000200241086a201737000020022018370000200241124132101a2202450d07200220032903f0043700122002412a6a2024290300370000200241226a20252903003700002002411a6a20262903003700002003202a41016a222b3602900920274200370300200342003703a00520024132200341a0056a100120282027290300370300200320032903a0053703e004200341e0046a411020034190096a410410032002101920274200370300200342003703a0054184c9c0004119200341a0056a100120282027290300370300200320032903a0053703e00402400240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d03200328029009212c0c010b4100212c0b20034190066a41186a2202202429030037030020034190066a41106a2204202529030037030020034190066a41086a22072026290300370300200320032903f004370390064200211020274200370300200342003703a005419c82c000410d200341a0056a100120282027290300370300200320032903a0053703e00402400240200341e0046a411041d889c200410041001000417f460d002003420037039009200341e0046a411020034190096a41084100100041016a41084d0d0120032903900921100b200341b0086a41186a222d2002290300370300200341b0086a41106a222e2004290300370300200341b0086a41086a222f200729030037030020032003290390063703b00820274200370300200342003703a005419dc9c0004117200341a0056a100120282027290300370300200320032903a0053703e004024002400240200341e0046a411041d889c200410041001000417f460d00200342103702b4052003200341e0046a3602b005200341a0026a200341b0056a106820032802a002450d1520032802a4022230ad42307e2205422088a70d072005a72202417f4c0d072002450d012002101b220d450d0c2030450d020c0d0b200341b0056a41186a2202202d290300370300200341b0056a41106a2204202e2903003703004108210d200341b0056a41086a2207200341b0086a41086a290300370300200320032903b0083703b00520034190096a41186a200229030037030020034190096a41106a200429030037030020034190096a41086a2007290300370300200320032903b005370390094100210e4200210f0c0e0b4108210d20300d0b0b41002104410021310c0b0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b102b000b41124101101c000b41324101101c000b41124101101c000b41324101101c000b20024108101c000b200341b0056a41086a220628020021084100210920032802b405210a20032802b005210e4100210741002102203021310340200341d0076a41186a220b4200370300200341d0076a41106a220c4200370300200341d0076a41086a22164200370300200342003703d00720064100200e200a200341d0076a41202008100022042004417f461b2204412020044120491b20086a22083602002004411f4d0d07200341f0066a41186a221d200b290300370300200341f0066a41106a220b200c290300370300200341f0066a41086a220c2016290300370300200320032903d0073703f006200342003703900920064100200e200a20034190096a41082008100022042004417f461b2204410820044108491b20086a2208360200200441074d0d072003290390092105200341003602900920064100200e200a20034190096a41042008100022042004417f461b2204410420044104491b20086a2208360200200441034d0d07200241016a2104200328029009211620034190096a41186a2232201d29030037030020034190096a41106a221d200b29030037030020034190096a41086a220b200c290300370300200320032903f00637039009024020022031470d002009200420042009491b2231ad42307e220f422088a70d2c200fa7220c4100480d2c02402002450d00200d2007200c101a220d0d010c0e0b200c101b220d450d0d0b200d20076a22022005370300200241206a2032290300370300200241186a201d290300370300200241106a200b290300370300200241086a200329039009370300200241286a2016360200200941026a2109200741306a21072004210220042030490d000b0b200d450d06200341b0056a41186a220b202d290300370300200341b0056a41106a220c202e290300370300200341b0056a41086a2216202f290300370300200320032903b0083703b00502402004ad4220862031ad84220f422088a7220e4120490d00200e41306c22044130460d03200d41306a2102200441506a210a4100210841012107200d2109200d2104034020022004200429030020022903005622061b21042007200820061b21082002200920061b2109200741016a2107200241306a2102200a41506a220a0d000b2004450d0f2009450d0f20034190096a41186a200b29030037030020034190096a41106a200c29030037030020034190096a41086a2016290300370300200320032903b00537039009200e20084b0d040c120b20034190096a41186a200b29030037030020034190096a41106a200c29030037030020034190096a41086a2016290300370300200320032903b00537039009200fa7200e470d010b200e4101742202200e41016a220420042002491bad220542307e2213422088a70d282013a722024100480d2802400240200e450d00200d200e41306c2002101a220d0d010c0e0b2002101b220d450d0d0b200f422088a7210e2005210f0b200d200e41306c6a22022010370300200241206a20034190096a41186a290300370300200241186a20034190096a41106a290300370300200241106a20034190096a41086a290300370300200220032903900937030820024101360228200f42ffffffff0f83200e41016aad42208684210f0c020b20034190096a41186a200b29030037030020034190096a41106a200c29030037030020034190096a41086a2016290300370300200320032903b00537039009410021080b200d200841306c6a22022010370300200241206a20034190096a41186a290300370300200241186a20034190096a41106a290300370300200241106a20034190096a41086a2903003703002002200329039009370308200241013602280b20034190096a41086a220a410036020020034201370390092003200f422088a722023602b005200341b0056a20034190096a105d024002402002450d00200241306c210e4158200a28020022026b21082002412c6a21022003280294092107200d210403400240024002400240200720086a41286a41204f0d00200241546a220941206a22062009490d2b20074101742209200620062009491b22094100480d2b2007450d0120032802900920072009101a22060d020c090b20032802900921060c020b2009101b2206450d070b20032009360294092003200636029009200921070b200a200241746a220b360200200620026a2209416c6a200441206a290000370000200941646a200441186a2900003700002009415c6a200441106a290000370000200941546a200441086a290000370000200429030021050240024002400240200720086a220941086a20094f0d00200b41086a2209200b490d2b2007410174220b20092009200b491b22094100480d2b2007450d01200620072009101a22060d020c0a0b200721090c020b2009101b2206450d080b200320093602940920032006360290090b200a2002417c6a2207360200200620026a41746a2005370000200441286a280200210b0240024002400240200920086a41034b0d00200741046a220c2007490d2b20094101742207200c200c2007491b22074100480d2b2009450d01200620092007101a22060d020c0b0b200921070c020b2007101b2206450d090b200320073602940920032006360290090b200441306a2104200a2002360200200620026a417c6a200b360000200841546a21082002412c6a2102200e41506a220e0d000c020b0b200328029409210720032802900921060b200a280200210220274200370300200342003703a005419dc9c0004117200341a0056a1001200341d0076a41086a2027290300370300200320032903a0053703d007200341d0076a411020062002100302402007450d00200610190b0240200fa7450d00200d10190b024002400240202b202c4d0d004200210f20274200370300200342003703a00541c7c9c000411b200341a0056a100120282027290300370300200320032903a0053703e004200341e0046a411041d889c200410041001000417f460d0120034200370398092003420037039009200341e0046a411020034190096a4110410010002202417f460d0a2002410f4d0d0a200a290300211520032903900921140c020b200341b0056a41186a2024290300370300200341b0056a41106a2025290300370300200341b0056a41086a2026290300370300200320032903f0043703b005410121020c120b42002114420021150b202a410174202c6b2104202a202c6b220241016a210e4200210502400340200421072002200e4f0d010240200241ff004b0d0020034190026a20142015200241ff0071109a03200520034190026a41086a2903007c200f2003290390027c2213200f542206ad7c2210200551210820102005542109200741016a2104200241016a21022013210f201021052006200920081b450d010b0b20034190096a41186a2204202429030037030020034190096a41106a22062025290300370300200a2026290300370300200320032903f004370390094112101b2202450d0b200241106a20293b0000200241086a201737000020022018370000200241124132101a2202450d0c20022003290390093700122002412a6a2004290300370000200241226a20062903003700002002411a6a200a290300370000200320073602b00520274200370300200342003703a00520024132200341a0056a100120282027290300370300200320032903a0053703e004200341e0046a4110200341b0056a410410032002101920034190096a200341f0046a10ac01200a2802002102200328029009210720034180026a200341f0046a104520034180026a41086a2903002105200329038002210f200341f0016a200341f0046a10442005200341f0016a41086a2903007c200f20032903f00122057c220f200554ad7c210502402002450d0020024105742104200721020340200341e0016a20021045200341e0016a41086a290300211320032903e0012110200341d0016a20021044201320057c2010200f7c2205201054ad7c200341d0016a41086a2903007c200520032903d0017c220f200554ad7c2105200241206a2102200441606a22040d000b0b200328029409450d00200710190b20274200370300200342003703a00541e2c9c0004112200341a0056a100120282027290300370300200320032903a0053703e00402400240200341e0046a411041d889c200410041001000417f460d00200342103702b4052003200341e0046a3602b00520034190096a200341b0056a103a2003280290092206450d0f200a280200210220032802940921040c010b4100210441012106410021020b20274200370300200342003703a00541f4c9c000411d200341a0056a100120282027290300370300200320032903a0053703e0040240200341e0046a411041d889c200410041001000417f460d002003410036029009200341e0046a411020034190096a41044100100041016a41044d0d0720032802900921072004450d100c0f0b4104210720040d0e0c0f0b2031450d00200d10190b41fcf9c00041331030000b20094101101c000b20094101101c000b20074101101c000b200c4108101c000b41fcf9c00041331030000b41fcf9c00041331030000b20024108101c000b41b4c9c00041131030000b41124101101c000b41324101101c000b41dcd2c2002008200e104a000b41fcf9c00041331030000b200610190b0240200220074d0d00200341b8016a200341f0046a200f200510a90120032903b801a74101470d00200341b8016a41106a290300211820032903c001211a20034190096a200341f0046a10ae0120032802900921060240200a2802002202450d004200211520024105742207210442002113200621020340200341a8016a20021045200341a8016a41086a290300211420032903a801211020034198016a20021044201420137c201020157c2213201054ad7c20034198016a41086a2903007c20132003290398017c2215201354ad7c2113200241206a2102200441606a22040d000b2015201384500d0020062102034020034188016a2002104520034188016a41086a29030021102003290388012114200341f8006a20021044200341d0006a2014200329037822177c22142010200341f8006a41086a2903007c2014201754ad7c201a2018109903200341c0006a2003290350200341d0006a41086a29030020152013109803200341e0006a20022003290340200341c0006a41086a29030010a901200241206a2102200741606a22070d000b0b200328029409450d00200610190b0240024002400240411c101b2202450d00200241186a41002800a9ca40360000200241106a41002900a1ca40370000200241086a4100290099ca4037000020024100290091ca403700002002411c413c101a2202450d01200220032903f00437001c200241346a20242903003700002002412c6a2025290300370000200241246a202629030037000020034190096a2002413c10ba0120034190096a41186a22082802002104200329039009211020021019202b202c6b2004410320104201511b4b0d02200f423f8821172005420186211820034190096a200341f0046a10ac01200a28020021022003280290092107200341306a200341f0046a1045200341306a41086a290300211020032903302113200341206a200341f0046a10442010200341206a41086a2903007c2013200329032022107c2215201054ad7c211302402002450d0020024105742104200721020340200341106a20021045200341106a41086a290300211420032903102110200320021044201420137c201020157c2213201054ad7c200341086a2903007c201320032903007c2215201354ad7c2113200241206a2102200441606a22040d000b0b20182017842110200f42018621140240200328029409450d00200710190b2014200f58201020055820102005511b0d02201520145a201320105a20132010511b0d030c020b411c4101101c000b413c4101101c000b20274200370300200342003703a00541e2c9c0004112200341a0056a100120282027290300370300200320032903a0053703e0040240200341e0046a411041d889c200410041001000417f460d00200342103702b4052003200341e0046a3602b00520034190096a200341b0056a103a2003280290092209450d03200328029409210e0240200a2802002202450d00200241057421064100210420092102024003402008200241186a29000037030020034190096a41106a200241106a290000370300200a200241086a2900003703002003200229000037039009200420034190096a200341f0046a412010970322074100476a21042007450d01200241206a2102200641606a22060d000c020b0b200341f0046a200410af0122020d050b200e450d00200910190b20274200370300200342003703a00541accbc0004115200341a0056a100120282027290300370300200320032903a0053703e004200341e0046a411041d889c20041001003200341003a00900920274200370300200342003703a00541e3f9c0004119200341a0056a100120282027290300370300200320032903a0053703e004200341e0046a411020034190096a410110030b200341b0056a41186a2024290300370300200341b0056a41106a2025290300370300200341b0056a41086a2026290300370300200320032903f0043703b005410221020b2022200537030020034190096a41306a200f370300200a20023a0000202120032903b00537000020034190096a412c6a202a360200202141086a200341b0056a41086a290300370000202141106a200341b0056a41106a290300370000202141186a200341b0056a41186a290300370000200341043a00900920034190096a103d202341016a2223201e470d030c040b41fcf9c00041331030000b41adcac00041ff002002410d10f301000b202341016a2223201e470d000b0b41002104201ba7450d00201c10190b410121070b410121060b410121080b4101210c0b4101210b0b410121090b4101210a0b4101210e20012d00002202410c4b0d070b0240024002400240024002400240024002400240024020020e0d12021212120005070406011203120b2007450d11200141086a2d0000410c490d11200141106a280200450d112001410c6a28020010190c110b2009450d10200141046a2802004102490d102001410c6a280200450d10200141086a28020010190c100b2012450d0f200141086a10650c0f0b200a450d0e200141086a2d000022024103490d0e20024104460d0520024103470d06200141106a280200450d0e2001410c6a28020010190c0e0b200c450d0d200141086a2d00004102470d0d2001410c6a22022802001062200228020010190c0d0b2006450d0c200141086a2d000022024105460d0220024102470d0c2001410c6a22022802001062200228020010190c0c0b200b450d0b200141046a2d00004102470d0b2001410c6a22022802001062200228020010190c0b0b2008450d0a200141086a2802004102470d0a200141106a280200450d0a2001410c6a28020010190c0a0b2001410c6a22022802001062200228020010190c090b200141346a280200450d08200141306a28020010190c080b200141306a280200450d072001412c6a28020010190c070b41fcf9c00041331030000b41c0a5c2001029000b41a8a5c2001029000b41fcf9c00041331030000b41fcf9c00041331030000b101d000b200e450d00200141046a2802004102470d00200141086a22022802001062200228020010190b2000201136020420002004360200200341800a6a24000be20501077f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d024002400240024002402000450d00200041e0006c2104200241186a21050340200528020021002002280214210602400240024002400240024002400240024020032d0000410e470d0020062000470d01200041016a22062000490d0b20004101742207200620062007491b22074100480d0b2000450d03200228021020002007101a22060d040c0c0b20062000470d01200041016a22062000490d0a20004101742207200620062007491b22074100480d0a2000450d05200228021020002007101a22060d060c0c0b200228021021060c030b200228021021060c050b2007101b2206450d080b2002200736021420022006360210200528020021000b2005200041016a360200200620006a41003a0000200341e0006a2103200441a07f6a22040d030c040b2007101b2206450d060b2002200736021420022006360210200528020021000b2005200041016a360200200620006a41013a00002003200241106a1064200341d8006a2802002107024002400240024020022802142206200528020022006b41044f0d00200041046a22082000490d0620064101742200200820082000491b22004100480d062006450d01200228021020062000101a22060d020c090b200228021021060c020b2000101b2206450d070b2002200036021420022006360210200528020021000b2005200041046a360200200620006a2007360000200341e0006a2103200441a07f6a22040d000b0b200241106a41086a2200280200210520022802142104200228021021032001280204210620012802002107200042003703002002420037031020072006200241106a1001200241086a2000290300370300200220022903103703002002411020032005100302402004450d00200310190b200241206a24000f0b101d000b20074101101c000b20074101101c000b20004101101c000beb0603027f017e0c7f230041f0026b2202240020022001106802400240024002400240024002400240024002400240024002402002280200450d0020022802042203ad42e0007e2204422088a70d032004a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241f0026a24000f0b4108210620030d030b4100210d4100210c0c030b102b000b20054108101c000b200241b8016a4101722107200141046a2108200141086a2105410021094100210a4100210b2003210c0340200241003a0090022001280200200828020020024190026a410120052802001000210d20052005280200200d41016a220d41014b6a360200200d4102490d040240024020022d009002220d450d00200d4101470d0620024190026a2001105520022d009002410e460d05200241b8016a20024190026a41d8001095031a2008280200210d2005280200210e200241003602ec02200541002001280200200d200241ec026a4104200e1000220d200d417f461b220d4104200d4104491b20052802006a360200200d41034d0d0420022802ec02210f20022d00b801210e200241e1006a200741d7001095031a20024190026a200241e1006a41d7001095031a200e410e460d062002410a6a20024190026a41d7001095031a20024190026a2002410a6a41d7001095031a200e410f470d010c070b20024190026a2002410a6a41d7001095031a410e210e0b200b41016a210d200241b8016a20024190026a41d7001095031a0240200b200c470d002009200d200d2009491b220cad42e0007e2204422088a70d072004a722104100480d070240200b450d002006200a2010101a22060d010c090b2010101b2206450d080b2006200a6a220b200e3a0000200b41016a200241b8016a41d7001095031a200b41d8006a200f360000200941026a2109200a41e0006a210a200d210b200d2003490d000b0b2000200c36020420002006360200200041086a200d360200200241f0026a24000f0b200241b8016a10620b20024190026a200241e1006a41d7001095031a0b20024190026a2002410a6a41d7001095031a0b200041003602000240200b450d00200621050340024020052d0000410e460d00200510430b200541e0006a2105200a41a07f6a220a0d000b0b0240200c450d00200610190b200241f0026a24000f0b101d000b20104108101c000bb50504027f017e0e7f017e230041d0006b22022400200241086a200110680240024002400240024002400240024002402002280208450d00200228020c2203ad42287e2204422088a70d032004a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0006a24000f0b4108210620030d030b4100210e4100210d0c030b102b000b20054108101c000b200141046a2107200241306a41186a2108200241306a41106a21094100210a4100210b4100210c2003210d0240034020024200370330200141086a2205410020012802002007280200200241306a410820052802001000220e200e417f461b220e4108200e4108491b20052802006a220f360200200e41074d0d01200229033021042008420037030020094200370300200241306a41086a22104200370300200242003703302005410020012802002007280200200241306a4120200f1000220e200e417f461b220e4120200e4120491b20052802006a360200200e411f4d0d01200c41016a210e200241106a41186a220f2008290300370300200241106a41106a22112009290300370300200241106a41086a22122010290300370300200220022903303703100240200c200d470d00200a200e200e200a491b220dad42287e2213422088a70d042013a722054100480d040240200c450d002006200b2005101a22060d010c060b2005101b2206450d050b2006200b6a22052004370300200541206a200f290300370300200541186a2011290300370300200541106a2012290300370300200541086a2002290310370300200a41026a210a200b41286a210b200e210c200e2003490d000c020b0b200041003602000240200d450d00200610190b200241d0006a24000f0b2000200d36020420002006360200200041086a200e360200200241d0006a24000f0b101d000b20054108101c000bd60403057f017e037f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d024002400240024002402000450d002003200041286c6a2104200241106a41086a22052802002100200228021421060340200329030021070240024002400240200620006b41084f0d00200041086a22082000490d0720064101742209200820082009491b220a4100480d072006450d0120022802102006200a101a22090d020c080b200041086a2108200228021021090c020b200a101b2209450d060b2002200a36021420022009360210200a21060b20052008360200200920006a20073700000240024002400240200620086b41204f0d00200841206a22002008490d072006410174220a20002000200a491b220a4100480d072006450d0120092006200a101a22090d020c090b200841206a21000c020b200a101b2209450d070b2002200a36021420022009360210200a21060b20052000360200200920086a220841086a200341106a290000370000200841106a200341186a290000370000200841186a200341206a2900003700002008200341086a290000370000200341286a22032004470d000c020b0b200241186a280200210020022802142106200228021021090b2001280204210320012802002108200241106a41086a220542003703002002420037031020082003200241106a1001200241086a2005290300370300200220022903103703002002411020092000100302402006450d00200910190b200241206a24000f0b101d000b200a4101101c000b200a4101101c000bf05e05037f057e077f017e057f230041a0086b22022400200241003a00c80720012802002001280204200241c8076a410120012802081000210320012001280208200341016a220341014b6a220436020802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d00c8072203410d4b0d0e024020030e0e00090607030a0c080e050d02040b000b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a41014b22036a3602002003450d9b0120022d00c807450d100c9b010b2000410e3a0000200241a0086a24000f0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d2720022d00c807220341044b0d27024020030e050025222321000b20024180046a200110f601200229038004a7450d2720024190046a29030021052002290388042106200241c8076a200110ce014102210120022d00c80722034102460d2720022902cc072107200241e8076a2802002104200241e4076a3502002108200241dc076a290200210920022f00c907210a20022d00cb07210b2002200241d4076a2902003703f806200220073703f0062002200937038007200a200b41107472210a0c260b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d1b20022d00c8072203450d1920034101460d1820034102470d1b200241003a00c807410421032001280200200141046a280200200241c8076a4101200410002104200141086a22012001280200200441016a220141014b6a36020020014102490d1b20022d00c80721010c1a0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d0b4106210320022d00c807220441034b0d9201024020040e04001e1c1d000b200241c8076a200110c802200241f0066a41086a2201200241f8076a290300370300200241f0066a41106a220420024180086a290300370300200241f0066a41186a220b20024188086a2903003703002002200241f0076a2903003703f006200241ec076a280200210a200241e8076a280200210c200241e4076a280200210d200241c8076a41186a280200210e200241c8076a41106a290300210520022903d0072106024020022903c8074201520d0020024198066a41186a200b29030037030020024198066a41106a200429030037030020024198066a41086a2001290300370300200220022903f00637039806410221030b0c93010b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d0e20022d00c8072203450d0d20034101470d0e200241e0076a4200370300200241d8076a4200370300200241c8076a41086a4200370300200242003703c80741042103200141086a220a41002001280200200141046a280200200241c8076a41202004100022042004417f461b22044120200441204922041b200a2802006a36020020040d14200220022f00c9073b01940620022d00c807210a20022800cb07210420022900d707210520022800df07210b20022800e307210c20022d00e707210d20022900cf072106200220022f0194063b01f006200241f0036a2001106820022802f003450d1420022802f403210e200241003a00c807410421032001280200200141046a280200200241c8076a4101200141086a22012802001000210f20012001280200200f41016a220f41014b6a360200200f4102490d142006422088a7210f2006a7210120022d00c8072110200220022f01f0063b01f005410321030c150b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22012001280200200341016a41014b6a3602002000410e3a0000200241a0086a24000f0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d0f20022d00c8072203450d0d20034101470d0f200241c8076a200110ce0120022d00c80722034102460d0f20022d00cb07210420022f00c907210e200241d4076a2902002106200241e8076a280200210a200241e4076a280200210b200241e0076a280200210c200241dc076a280200210d20022902cc072105200241f8006a200110f6012002290378a7450d0f200241f8006a41106a29030021082002290380012107200241e0006a200110f6012002290360a7450d0f200e2004411074722101200241f0006a290300210920022903682111200642808080807083200642ffffffff0f83842106410321040c0e0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d6820022d00c807220341084b0d68024020030e09003c393a383d3f3b41000b200241c8076a200110aa0120022802c8072203450d6820022902cc072105200241d0026a200110682005a7210420022802d002450d6720022802d4022101200441087621102003410876211220054220882105410221130c3f0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a220a36020020034102490d6c20022d00c807220341054b0d6c4103210b024020030e060092012b2d2a30000b200241186a200110682002280218450d6c200228021c2203417f4c0d722003450d60200310df012204450d7d200141086a220a200341002001280200200141046a28020020042003200a280200100022012001417f461b2201200120034b1b2201200a2802006a36020020012003470d610c90010b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a220a3602004102210420034102490d5320022d00c8072214410a4b0d53024020140e0b5300494a474d4e4b524850530b200241a0016a2001106820022802a001450d5320022802a4012203410876210d410321040c4b0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d0d20022d00c8072203450d0c20034101470d0d200241c8076a200110ce0120022d00c80722014102460d0d200241d4076a290200210520022902cc07210620022f00c90720022d00cb07411074722103200241dc076a2802002104200241e0076a280200210a200241e8076a280200210b200241e4076a280200210c4103210d0c210b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d4120022d00c807220341054b0d41024020030e06002e2b2c292f000b200241c8076a2001105520022d00c8072104200241f0066a200241c8076a41017241d7001095031a2004410e460d4120024198066a200241f0066a41d7001095031a41d800101b2203450d78200320043a0000200341016a20024198066a41d7001095031a20024188026a200110f601200229038802a7450d4020024198026a29030021062002290390022105410221040c2f0b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d8b0120022d00c807450d040c8b010b200241003a00c8072001280200200141046a280200200241c8076a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d5120022d00c807220341044b0d51024020030e05002420211d000b200241c8076a2001105520022d00c8072101200241f0066a200241c8076a41017241d7001095031a2001410e460d5120024198066a200241f0066a41d7001095031a41d800101b2204450d75200420013a0000200441016a20024198066a41d7001095031a410221030c220b2000410e3a0000200241a0086a24000f0b410621030c86010b200241086a200110b3022002290308a7450d8a0120022903102105200041003a0000200041106a2005370300200041086a4202370300200241a0086a24000f0b200241f8036a2001106820022802f803450d860120022802fc032203417f4c0d692003450d3c200310df012204450d6f200141086a220a200341002001280200200141046a28020020042003200a280200100022012001417f461b2201200120034b1b2201200a2802006a36020020012003470d3d0c83010b200241e8036a2001106820022802e803450d0020022802ec032104200241c8076a2001105520022d00c8072103200241f0066a200241c8076a41017241d7001095031a2003410e470d2a0b200220022f01f0053b01c8070c80010b200241c8076a200110ce014102210420022d00c80722034102460d0120022d00cb07210e20022f00c907210f200241d4076a2902002106200241e8076a280200210a200241e4076a280200210b200241e0076a280200210c200241dc076a280200210d20022902cc072105200241c8006a200110f6012002280248450d01200f200e411074722101200241c8006a41106a2903002108200229035021070b200041033a00002000410f6a20014110763a00002000410d6a20013b0000200041c8006a2009370000200041c0006a2011370000200041386a2008370000200041306a2007370000200041186a2006370000200041106a20053700002000412c6a200a360000200041286a200b360000200041246a200c360000200041206a200d3600002000410c6a20033a0000200041086a2004360000200241a0086a24000f0b2000410e3a0000200241a0086a24000f0b200241c8076a2001105520022d00c8072103200241f0066a200241c8076a41017241d7001095031a2003410e470d130b2000410e3a0000200241a0086a24000f0b0b200220022f01f0053b01c80720034104460d790c230b20024190016a200110b302200229039001a7450d022002290398012205422088a7210c2005a7210d410321030c010b200241e0076a4200370300200241d8076a4200370300200241c8076a41086a4200370300200242003703c807200141086a220341002001280200200141046a280200200241c8076a41202004100022012001417f461b22014120200141204922011b20032802006a36020020010d01200220022f00c9073b01960620022d00c807210120022800cb07210e20022900d707210520022800df07210b20022800e307210420022d00e707210a20022900cf072106200220022f01960622033b019406200220033b01f0062006422088a7210c2006a7210d410221030b200220022f01f006220f3b01c8072002200f3b019806200041096a20013a0000200041086a20033a0000200041043a0000200041286a200a3a0000200041246a2004360000200041206a200b360000200041186a2005370000200041146a200c360000200041106a200d3600002000410c6a200e3600002000410a6a20022f0198063b0000200241a0086a24000f0b200220022f01f0063b01c8072000410e3a0000200241a0086a24000f0b200241c8076a200110ce0120022d00c80722044102460d7620022d00cb07210f20022f00c9072110200241d4076a2902002105200241e8076a280200210a200241e4076a280200210c200241e0076a280200210d200241dc076a280200210e20022902cc072106200241a8056a200110f60120022903a805a7450d58200241a8056a41106a290300210720022903b005210920024198056a200110b302200229039805a7450d5820022903a005210820024190056a20011068200228029005450d58200228029405220b417f4c0d5b200b450d56200b10df012215450d6a200141086a2212200b41002001280200200141046a2802002015200b2012280200100022012001417f461b22012001200b4b1b220120122802006a3602002001200b470d570c730b200241d8056a200110f60120022903d805a7450d75200241e8056a290300210820022903e0052107200241c8056a200110b30220022903c805a7450d7520022903d0052109200241e0076a4200370300200241d8076a4200370300200241c8076a41086a4200370300200242003703c807200141086a220341002001280200200141046a280200200241c8076a41202003280200100022042004417f461b22044120200441204922041b20032802006a36020020040d43200220022f00c9073b01940620022d00c807210b20022800cb07210420022900cf07210620022900d707210520022800df07210e20022800e307210d20022d00e707210c200220022f0194063b01f006200241c0056a200110684106210320022802c005450d6b20022802c405220f417f4c0d5a200f450d58200f10df01220a450d6a200141086a2210200f41002001280200200141046a280200200a200f2010280200100022012001417f461b22012001200f4b1b220120102802006a3602002001200f470d590c710b20024180056a200110b302200229038005a7450d742002290388052105200241f8046a2001106820022802f804450d7420022802fc04220a417f4c0d59200a450d4b200a10df012204450d67200141086a220b200a41002001280200200141046a2802002004200a200b280200100022012001417f461b22012001200a4b1b2201200b2802006a3602002001200a470d4c0c6f0b200241f0046a2001106820022802f004450d0620022802f4042203410876210a410621010c020b200241e0046a2001106820022802e004450d0520022802e4042103200241c8046a200110f60120022903c804a7450d05200241d8046a290300210520022903d0042106200241b8046a200110b30220022903b804a7450d0520022903c0042108200241b0046a2001106820022802b004450d0520022802b404210120024180076a2005370300200220063703f806200220013602f0062003410876210a2008422088a72104410421010c030b200241e8046a2001106820022802e804450d0420022802ec042203410876210a410521010b420021080c010b20024198046a200110f601200229039804a7450d02200241a8046a2903002105200220022903a0043703f006200220053703f80641032101420021080b0b200241c8076a41106a200241f0066a41106a2903002207370300200241c8076a41086a200241f0066a41086a290300220937030020024198066a41086a220b200937030020024198066a41106a220c2007370300200220022903f006220737039806200220073703c807200041386a2005370000200041306a20063700002000410c6a200a410874200341ff017172360000200041086a20013600002000410b3a0000200041286a2004ad422086200842ffffffff0f8384370000200041106a200229039806370000200041186a200b290300370000200041206a200c290300370000200241a0086a24000f0b200241c8076a41106a200241f0066a41106a290300370300200241c8076a41086a200241f0066a41086a290300370300200220022903f0063703c8072000410e3a0000200241a0086a24000f0b200241d8036a200110b30220022903d803a7450d3420022903e0032205422088a721012005a7210e410621030c040b20024198066a200241f0066a41d7001095031a41d800101b2201450d53200120033a0000200141016a20024198066a41d7001095031a200141087621034102210d0b2000410d3a0000200041146a20053700002000410c6a2006370000200041286a200b360000200041246a200c360000200041206a200a3600002000411c6a2004360000200041046a200d360000200041086a2003410874200141ff017172360000200241a0086a24000f0b200241e0076a4200370300200241d8076a4200370300200241c8076a41086a4200370300200242003703c80741042103200141086a220a41002001280200200141046a280200200241c8076a41202004100022012001417f461b22014120200141204922011b200a2802006a36020020010d30200220022f00c9073b01960620022d00c807210c20022800cb07210420022900d707210520022800df07210d20022800e307210a20022d00e707210b20022900cf072106200220022f0196063b01f006200220022f01f00622013b019406200220013b01f0052006422088a721012006a7210e0c020b200241c8036a200110b30220022903c803a7450d3020022903d0032205422088a721012005a7210e410521030b0b200220022f01f0053b01c8070c5f0b200241e0076a4200370300200241d8076a4200370300200241c8076a41086a4200370300200242003703c807200141086a220341002001280200200141046a220e280200200241c8076a41202004100022042004417f461b22044120200441204922041b20032802006a220f36020020040d2e200220022f00c9073b01960620022d00c807210c20022800cb07210420022900cf07210620022900d707210520022800df07210d20022800e307210a20022d00e707210b200220022f0196063b01f006200220022f01f00622103b019406200220103b01c807200241003a00f0062001280200200e280200200241f0066a4101200f1000210120032003280200200141016a41014b22016a3602002001450d2f20022d00f006210f200220022f01c8073b01f0052006422088a721012006a7210e410321030c310b200241286a200110682002280228450d42200228022c2203417f4c0d482003450d32200310df012204450d54200141086a220a200341002001280200200141046a28020020042003200a280200100022012001417f461b2201200120034b1b2201200a2802006a36020020012003470d330c5c0b200241206a200110682002280220450d4120022802242203417f4c0d472003450d33200310df012204450d54200141086a220a200341002001280200200141046a28020020042003200a280200100022012001417f461b2201200120034b1b2201200a2802006a36020020012003470d340c5a0b200241b0026a2001106820022802b002450d184106210420022802b40221030c060b200242003703c807200141086a220341002001280200200141046a280200200241c8076a4108200a100022012001417f461b2201410820014108491b20032802006a360200200141074d0d3f20022903c80721054105210b0c640b200241a8026a2001106820022802a802450d1620022802ac022103200241003a00c807410421042001280200200141046a280200200241c8076a4101200141086a22012802001000210a20012001280200200a41016a41014b220a6a360200200a450d1620022d00c807210a0c050b200241c8076a2001105520022d00c8072104200241f0066a200241c8076a41017241d7001095031a2004410e460d1520024198066a200241f0066a41d7001095031a41d800101b2203450d4d200320043a0000200341016a20024198066a41d7001095031a200241003a00c8072001280200200141046a280200200241c8076a4101200141086a22042802001000210a20042004280200200a41016a41014b220a6a220b360200200a450d1420022d00c807220a41024b0d1442002106200242003703c807200141086a220441002001280200200141046a280200200241c8076a4108200b100022012001417f461b2201410820014108491b20042802006a360200200141074d0d1420022903c8072105410521040c040b200241c0006a200110682002280240450d3c20022802442216ad42187e2205422088a70d422005a72203417f4c0d422003450d322003101b22040d3320034104101c000b200241a0026a2001106820022802a002450d134103210420022802a40221030c010b200241c0026a200110b30220022903c002a7450d1220022903c8022105200241b8026a2001106820022802b802450d1220022802bc02210342002106410721040b0b200220022f01f00522013b01c807200220013b019606200041186a2006370000200041106a2005370000200041096a200a3a0000200041086a20043a0000200041063a00002000410c6a20033600002000410a6a20022f0196063b0000200241a0086a24000f0b20024198066a200241f0066a41d7001095031a41d800101b2201450d44200120033a0000200141016a20024198066a41d7001095031a200220022f01f0053b01c807410221030b200220022f01c8073b019206200041056a200a3a0000200041046a20033a0000200041093a0000200041286a200e360000200041256a20103a0000200041246a200d3a0000200041206a200c3600002000411c6a200b360000200041146a2005370000200041106a200f3600002000410c6a2001360000200041086a2004360000200041066a20022f0192063b0000200241a0086a24000f0b200241c8076a200110ce0120022d00c80722034102460d3020022d00cb07210420022f00c907210e200241d4076a2902002105200241e8076a280200210c200241e4076a280200210b200241e0076a280200210a200241dc076a280200210d20022902cc07210720024188036a200110f601200229038803a7450d3020024188036a41106a2903002106200229039003210820024180036a20011068200228028003450d30200e20044110747221122005422088a721152005a72101200228028403210e200742208821052007a722044108762110410621130c0b0b200241f0026a2001106820022802f002450d2f20022802f40222034108762112410421130c040b200241f8026a2001106820022802f802450d2e20022802fc0222034108762112410521130c030b200241a8036a200110b30220022903a803a7450d2d20022903b003220642208821052006a722044108762110410921130c060b200241e8026a2001106820022802e802450d2c20022802ec022103200241c8076a200110ce0120022d00c80722044102460d2c20022d00cb07210d20022f00c9072110200241d4076a2902002106200241e8076a280200210e200241e4076a280200210c200241e0076a280200210b200241dc076a280200210a20022902cc072105200241e0026a2001106820022802e002450d2c20022802e402210f200241d8026a2001106820022802d802450d2c2010200d4110747221102005422088a721012006422088a7210d2006a721152003410876211220022802dc02ad210842002106410321130c070b200241a0036a2001106820022802a003450d2b20022802a40322034108762112410721130b420021050c040b200241c8076a200110ce0120022d00c80722034102460d2920022902cc0722064220882105410821132006a72204410876211020022f00c90720022d00cb07411074722112200241d4076a2902002206422088a72115200241dc076a280200210d200241e0076a280200210a200241e8076a280200210c200241e4076a280200210b2006a721010b0c030b200241b8036a200110b30220022903b803a7450d2720022903c003220642208821052006a722044108762110410a21130b0b0b200041073a0000200041c0006a2006370000200041386a2008370000200041346a200f360000200041306a200e3600002000412c6a200c360000200041286a200b360000200041246a200a360000200041206a200d3600002000411c6a2015360000200041186a2001360000200041086a20133600002000410c6a2012410874200341ff017172360000200041106a20054220862010ad42ffffff07834208862004ad42ff01838484370000200241a0086a24000f0b20031043200310190b200220022f01f0053b01c8072000410e3a0000200241a0086a24000f0b410121042001280200200141046a28020041014100200141086a28020010001a41002003460d460b2003450d48200410190c480b200241d0016a2001106820022802d001450d0c20022802d4012103200241c8016a2001106820022802c801450d0c20022802cc01210c200241b0016a200110f60120022903b001a7450d0c200241c0016a290300210520022903b80121062003410876210d410621040c090b20024180026a20011068200228028002450d0b2002280284022203410876210d410b21040c030b200241c8076a200110ce0120022d00c80722034102460d0a200241d4076a290200210520022902cc072106200241e4076a280200220b4110762110200b410876211220022f00c90720022d00cb0741107472210d200241dc076a280200210c200241e0076a280200210f200241e8076a2802002115410421040c070b200241a8016a2001106820022802a801450d0920022802ac012203410876210d410521040c010b200241f8016a2001106820022802f801450d0820022802fc012203410876210d410921040b0c060b200241d8016a200110b30220022903d801a7450d0620022903e0012205422088a721132005a72116410721040c010b200241e8016a200110b30220022903e801a7450d0520022903f0012205422088a721132005a72116410821040b0c030b200241c8076a2001103a20022802c8072203450d032003410876210d20022902cc072106410c21040b2006422088a721132006a721160c010b200241003a00c8072001280200200141046a280200200241c8076a4101200a10002103200141086a22012001280200200341016a220141014b6a36020020014102490d0120022d00c807210e410a21040b200220022f01f00622013b01c807200220013b019806200041096a200e3a0000200041086a20043a0000200041053a00002000412c6a20153600002000412a6a20103b0000200041296a20123a0000200041286a200b3a0000200041246a200f360000200041206a200c360000200041186a2005370000200041146a2013360000200041106a20163600002000410c6a200d410874200341ff0171723600002000410a6a20022f0198063b0000200241a0086a24000f0b200220022f01f0063b01c8072000410e3a0000200241a0086a24000f0b200220022f01f0063b0194060b200220022f01f0053b01c8070c2d0b200220022f01f0063b019406410721030c010b410721030b0b200220022f01f0053b01c80720034107470d2c0c290b410621030c270b410121042001280200200141046a28020041014100200141086a28020010001a41002003460d290b20030d0d0c0e0b410121042001280200200141046a28020041014100200141086a28020010001a41002003460d260b20030d0b0c0c0b410121042001280200200141046a28020041014100200141086a28020010001a41002003460d2f0b20030d090c0a0b410421040b024002402016450d0042002105200141086a210d200141046a21124100210f410021034100210c201621130340200241386a200110682002280238450d09200228023c220b417f4c0d1102400240200b450d00200b10df012210450d18200d200b4100200128020020122802002010200b200d2802001000220a200a417f461b220a200a200b4b1b220a200d2802006a360200200a200b460d010c0a0b410121102001280200201228020041014100200d28020010001a4100200b470d090b200241306a200110682002280230450d082002280234220a417f4c0d1102400240200a450d00200a10df012215450d16200d200a4100200128020020122802002015200a200d2802001000220e200e417f461b220e200e200a4b1b220e200d2802006a360200200e200a460d010c090b410121152001280200201228020041014100200d28020010001a4100200a470d080b200c41016a210e0240200c2013470d00200f200e200e200f491b2213ad42187e2206422088a70d132006a722144100480d130240200c450d00200420032014101a22040d010c150b2014101b2204450d140b200420036a220c2010360200200c41146a200a360200200c41106a200a360200200c410c6a2015360200200c41046a200bad220642208620068437020020054280808080107c2105200f41026a210f200341186a2103200e210c200e2016490d000c020b0b41002113420021050b2004450d0820052013ad8421054107210b0c2d0b410121042001280200200141046a28020041014100200141086a28020010001a4100200a460d230b200a450d27200410190c270b2004450d00200310190b2000410e3a0000200241a0086a24000f0b200a450d00201510190b200b450d00201010190b0240200c450d002004210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141186a2101200341686a22030d000b0b2013450d010b200410190b2000410e3a0000200241a0086a24000f0b410121152001280200200141046a28020041014100200141086a28020010001a4100200b460d1c0b200b450d00201510190b0c1e0b4101210a2001280200200141046a28020041014100200141086a28020010001a4100200f460d180b200f450d11200a10190c110b102b000b101d000b20144104101c000b200a4101101c000b41d8004108101c000b200b4101101c000b20034101101c000b41d8004108101c000b41d8004108101c000b41d8004108101c000b41d8004108101c000b20034101101c000b20034101101c000b20034101101c000b200a4101101c000b200b4101101c000b200f4101101c000b0c0a0b2000410e3a0000200241a0086a24000f0b2003ad220542208620058421054104210b0c0b0b2003ad220542208620058421054106210b0c0a0b200220022f01c8073b019206200041096a200c3a0000200041086a20033a0000200041083a0000200041296a200f3a0000200041286a200b3a0000200041246a200a360000200041206a200d360000200041186a2005370000200041146a2001360000200041106a200e3600002000410c6a20043600002000410a6a20022f0192063b0000200241a0086a24000f0b200aad22064220862006842106410321030c050b200241a8066a2008370300200220073703a006200220022f01f0063b019206200220093703b0062002200fad220842208620088437039806410521030c040b200241b0066a2007370300200220093703a80620022015360298062002200bad220742208620078437029c06200542808080807083200542ffffffff0f838421052010200f411074724108742004722104410421030c030b2000410e3a0000200241a0086a24000f0b2000410a3a0000200041086a2004360000200041046a41023600002000410c6a2003ad2205422086200584370000200241a0086a24000f0b0b200241c8076a41086a220120024198066a41086a290300370300200241c8076a41106a220f20024198066a41106a290300370300200241c8076a41186a221020024198066a41186a290300370300200220022f0192063b01f00620022002290398063703c807024020034106470d002000410e3a0000200241a0086a24000f0b200241f0056a41086a22152001290300370300200241f0056a41106a2201200f290300370300200241f0056a41186a220f2010290300370300200220022f01f0063b019006200220022903c8073703f005200041096a200b3a0000200041086a20033a00002000410c3a00002000412c6a200a360000200041286a200c360000200041246a200d360000200041206a200e360000200041186a2005370000200041106a20063700002000410c6a20043600002000410a6a20022f0190063b0000200041306a20022903f005370000200041386a2015290300370000200041c0006a2001290300370000200041c8006a200f290300370000200041d0006a2008370000200241a0086a24000f0b2000410e3a0000200241a0086a24000f0b2003ad220542208620058421054102210b0b200041013a0000200041106a20053700002000410c6a2004360000200041086a200b360000200241a0086a24000f0b2000410e3a0000200241a0086a24000bdd0504027f017e0f7f017e230041d0006b22022400200241086a200110680240024002400240024002400240024002402002280208450d00200228020c2203ad42287e2204422088a70d032004a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0006a24000f0b4108210620030d030b4100210f4100210d0c030b102b000b20054108101c000b200241306a41186a2107200241306a41106a2108200141046a21094100210a4100210b4100210c2003210d024003402007420037030020084200370300200241306a41086a220e420037030020024200370330200141086a2205410020012802002009280200200241306a412020052802001000220f200f417f461b220f4120200f4120491b20052802006a2210360200200f411f4d0d01200241106a41186a22112007290300370300200241106a41106a22122008290300370300200241106a41086a2213200e29030037030020022002290330370310200242003703302005410020012802002009280200200241306a410820101000220f200f417f461b220f4108200f4108491b20052802006a360200200f41074d0d01200c41016a210f200229033021042007201129030037030020082012290300370300200e2013290300370300200220022903103703300240200c200d470d00200a200f200f200a491b220dad42287e2214422088a70d042014a722054100480d040240200c450d002006200b2005101a22060d010c060b2005101b2206450d050b2006200b6a22052002290330370300200541186a2007290300370300200541106a2008290300370300200541086a200e290300370300200541206a2004370300200a41026a210a200b41286a210b200f210c200f2003490d000c020b0b200041003602000240200d450d00200610190b200241d0006a24000f0b2000200d36020420002006360200200041086a200f360200200241d0006a24000f0b101d000b20054108101c000bcd0202037f027e230041306b22012400200141206a41086a220242003703002001420037032041bcdac100411d200141206a1001200141086a200229030037030020012001290320370300024002402001411041d889c200410041001000417f460d002001200136021020014110360214200142003703202001410020014110200141206a41084100100022022002417f461b2202410820024108491b2203360218200241074d0d012001290320210420014200370320200141106a41086a410020014110200141206a41082003100022022002417f461b2202410820024108491b20036a360200200241074d0d0120012903202105200141206a200141106a105620012802202202450d0120002001290224370214200020023602102000200537030820002004370300200141306a24000f0b20004100360210200141306a24000f0b41fcf9c00041331030000bc30201027f230041f0016b220224000240024002404112101b2203450d00200341106a41002f00cae8403b0000200341086a41002900c2e840370000200341002900bae840370000200341124124101a2203450d012003200136001220024188016a41086a2201420037030020024200370388012003411620024188016a1001200241e8006a41086a2001290300370300200220022903880137036802400240200241e8006a411041d889c200410041001000417f460d002002421037027c2002200241e8006a36027820024188016a200241f8006a10d0012002290388014201520d04200241086a20024188016a41086a41e0001095031a20004201370300200041086a200241086a41e0001095031a0c010b200042003703000b20031019200241f0016a24000f0b41124101101c000b41244101101c000b41fcf9c00041331030000b980c05027f017e027f017e067f230041b0016b22032400200341306a41086a220442003703002003420037033041e6fbc000411b200341306a1001200341206a41086a200429030037030020032003290330370320024002400240024002400240024002400240200341206a411041d889c200410041001000417f460d002003420037034820034200370340200341206a4110200341c0006a4110410010002204417f460d012004410f4d0d012003290340200158200341c8006a290300220520025820052002511b0d002000200120021046200341b0016a240041010f0b4114101b2204450d02200441106a41002800a3fc40360000200441086a410029009bfc4037000020044100290093fc40370000200441144134101a2204450d03200420002900003700142004412c6a200041186a290000370000200441246a200041106a2900003700002004411c6a200041086a290000370000200341306a41086a220642003703002003420037033020044134200341306a1001200341c0006a41086a200629030037030020032003290330370340200341c0006a4110100c21062004101920060d07200341306a41086a220442003703002003420037033041f29ec1004113200341306a1001200341c0006a41086a200429030037030020032003290330370340410021040240200341c0006a411041d889c200410041001000417f460d0020034100360230200341c0006a4110200341306a41044100100041016a41044d0d02200328023021040b200341306a200041016a2d000041087420002d00002206724106762207106102402006413f71220620032802384f0d00200341106a200328023020064105746a22061045200341106a41086a2903002108200329031021052003200610442003290300420020057d85200341086a290300420020087d2005420052ad7d85844200520d0020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200341c0006a41086a200341306a41086a280200360200200320032903303703402007200341c0006a10e2010c070b02402003280234450d00200328023010190b200341c0006a20041061024020032802482206413f4d0d00200341c8006a21070340200441016a210402402003280244450d00200328024010190b200341c0006a200410612007280200220641c0004f0d000b0b200328024021092003280244210a200341c0006a41186a220b200041186a290000370300200341c0006a41106a220c200041106a290000370300200341c0006a41086a220d200041086a29000037030020032000290000370340200641016a2107200a2006470d052006410174220a20072007200a491b220aad4205862205422088a70d042005a7220e4100480d04024002402006450d0020092006410574200e101a2209450d010c070b200e101b22090d060b200e4101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41144101101c000b41344101101c000b101d000b200441067420066a210e200920064105746a22062003290340370000200641186a200b290300370000200641106a200c290300370000200641086a200d2903003700000240200741c000470d002003200441016a360220200341306a41086a220642003703002003420037033041f29ec1004113200341306a1001200341c0006a41086a200629030037030020032003290330370340200341c0006a4110200341206a410410030b200320073602482003200a360244200320093602402004200341c0006a10e201200341c0006a41086a2000290000370300200341c0006a41106a200041086a290000370300200341c0006a41186a200041106a290000370300200341e0006a200041186a2900003703002003200e360244200341013a0040200341c0006a103d0b200341f8006a2002370300200341f0006a2001370300200341c0006a41086a41003a0000200341c9006a2000290000370000200341d1006a200041086a290000370000200341d9006a200041106a290000370000200341e1006a200041186a290000370000200341023a0040200341c0006a103d0b2000200120021046200341b0016a240041000bc40303027f017e097f230041106b2202240020022001106802400240024002400240024002400240024002402002280200450d0020022802042203ad2204421e88a70d032004420286a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241106a24000f0b4104210620030d030b410021054100210b0c030b102b000b20054104101c000b200141086a210741002108410021094100210a2003210b0340200141046a28020021052007280200210c2002410036020c20074100200128020020052002410c6a4104200c100022052005417f461b22054104200541044922051b20072802006a36020020050d02200a41016a2105200228020c210c0240200a200b470d002008200520052008491b220bad4202862204422088a70d042004a7220d4100480d040240200a450d0020062009200d101a22060d010c060b200d101b2206450d050b200620096a200c360200200841026a2108200941046a21092005210a20052003490d000b0b2000200b36020420002006360200200041086a2005360200200241106a24000f0b200041003602000240200b450d00200610190b200241106a24000f0b101d000b200d4104101c000b920301097f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d02400240024002402000450d0020004102742104200241186a22052802002100200228021421060340200328020021070240024002400240200620006b41044f0d00200041046a22082000490d0720064101742209200820082009491b220a4100480d072006450d0120022802102006200a101a22090d020c080b200041046a2108200228021021090c020b200a101b2209450d060b2002200a36021420022009360210200a21060b200341046a210320052008360200200920006a2007360000200821002004417c6a22040d000c020b0b200241186a280200210820022802142106200228021021090b2001280204210020012802002103200241106a41086a220442003703002002420037031020032000200241106a1001200241086a2004290300370300200220022903103703002002411020092008100302402006450d00200910190b200241206a24000f0b101d000b200a4101101c000bcc1605027f017e137f017e0b7f23004190026b22022400200241086a2001106802400240024002400240024002400240024002400240024002402002280208450d00200228020c2203ad42287e2204422088a70d0a2004a72205417f4c0d0a2005450d012005101b2206450d032003450d020c040b2000410036020020024190026a24000f0b4108210620030d020b41002115410021130c020b20054108101c000b200241b8016a41106a2105200241b8016a4101722107200241f8006a41116a2108200241c7016a2109200241106a410172210a200141046a210b200141086a210c2002418c026a41026a210d20024180026a210e200241f0016a210f410021104100211141002112200321130340200241003a00b8012001280200200b280200200241b8016a4101200c28020010002114200c200c280200201441016a41014b22146a22153602002014450d0320022d00b801221441034b0d030240024002400240024002400240024020140e0400030102000b2002200110682002280200450d0a20022802042214417f4c0d0d2014450d03201410df012215450d0f200c201441002001280200200b28020020152014200c280200100022162016417f461b2216201620144b1b2216200c2802006a36020020162014460d040c090b200241b8016a41186a2216420037030020054200370300200241b8016a41086a22174200370300200242003703b801200c41002001280200200b280200200241b8016a41202015100022142014417f461b2214412020144120491b200c2802006a3602002014411f4d0d09200241f8006a41086a200941086a290000370300200241f8006a41106a200941106a2d00003a0000200220022d00ba013a00b201200220022f01b8013b01b0012002200929000037037820022800bb01211520022900bf0121182008411f6a200241b8016a411f6a290000370000200841186a2016290000370000200841106a2005290000370000200841086a2017290000370000200820022900b801370000410121170c040b200242003703b801200c41002001280200200b280200200241b8016a41082015100022142014417f461b2214410820144108491b200c2802006a2215360200201441074d0d0820022903b8012104200f4200370300200241b8016a41306a4200370300200241b8016a41286a4200370300200241b8016a41206a4200370300200241b8016a41186a420037030020054200370300200241b8016a41086a4200370300200242003703b801200c41002001280200200b280200200241b8016a41c0002015100022142014417f461b221441c000201441c000491b200c2802006a3602002014413f4d0d08200241f8006a41086a200941086a290000370300200241f8006a41106a200941106a290000370300200241f8006a41186a200941186a290000370300200241f8006a41206a200941206a290000370300200241f8006a41286a200941286a290000370300200241f8006a41306a200941306a2d00003a0000200220022d00ba013a00b201200220022f01b8013b01b0012002200929000037037820022800bb01211520022900bf012118410221170c040b200241b8016a2001103a20022802b8012215450d0720022902bc012118200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2005290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a2903003703002002200d2d00003a00b201200220022f008c023b01b001200220022903b801370378410021170c020b410121152001280200200b28020041014100200c28020010001a41002014470d050b200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2005290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a290300370300200220022f008c023b01b001200220022903b8013703782002200d2d00003a00b2012014ad22044220862004842118410321170b0b200d20022d00b2013a0000200241b8016a41086a2214200241f8006a41086a22192903003703002005200241f8006a41106a221a290300370300200241b8016a41186a2216200241f8006a41186a221b290300370300200241b8016a41206a221c200241f8006a41206a290300370300200241b8016a41286a221d200241f8006a41286a290300370300200241b8016a41306a221e200241f8006a41306a290300370300200220022f01b0013b018c02200220022903783703b801200241f4006a41026a221f200d2d00003a0000200241386a41086a22202014290300370300200241386a41106a22212005290300370300200241386a41186a22222016290300370300200241386a41206a2223201c290300370300200241386a41286a221c201d290300370300200241386a41306a221d201e290300370300200220022f018c023b0174200220022903b80137033820142018370300200720022f01743b0000200741026a201f2d00003a000020052002290338370000200541086a2020290300370000200541106a2021290300370000200541186a2022290300370000200541206a2023290300370000200541286a201c290300370000200541306a201d290300370000200220173a00b801200220153602bc01200e2004370300200241106a200241b8016a10e10120022d00102117200241b8016a411f6a221c200a411f6a2900003700002016200a41186a2900003703002005200a41106a2900003703002014200a41086a2900003703002002200a2900003703b80120174103460d04201241016a2115200241f8006a411f6a221d201c290000370000201b2016290300370300201a200529030037030020192014290300370300200220022903b801370378024020122013470d002010201520152010491b2213ad42287e2204422088a70d062004a722144100480d0602402012450d00200620112014101a22060d010c090b2014101b2206450d080b200620116a221420173a0000201441206a201d290000370000201441196a201b290300370000201441116a201a290300370000201441096a2019290300370000201441016a2002290378370000201041026a2110201141286a21112015211220152003490d000b0b2000201336020420002006360200200041086a201536020020024190026a24000f0b2014450d00201510190b2002418e026a20022d00b2013a0000200241b8016a41086a2205200241f8006a41086a290300370300200241b8016a41106a2214200241f8006a41106a290300370300200241b8016a41186a220c200241f8006a41186a290300370300200241b8016a41206a200241f8006a41206a290300370300200241b8016a41286a200241f8006a41286a290300370300200241b8016a41306a200241f8006a41306a290300370300200220022f01b0013b018c02200220022903783703b801200241033a0010200241b8016a411f6a200a411f6a290000370000200c200a41186a2900003703002014200a41106a2900003703002005200a41086a2900003703002002200a2900003703b8010b2000410036020002402012450d00200621050340024020052d00002214450d00024020144101470d00200541086a280200450d01200541046a2802001019200541286a2105201141586a22110d020c030b200541146a280200450d00200541106a28020010190b200541286a2105201141586a22110d000b0b02402013450d00200610190b20024190026a24000f0b101d000b102b000b20144108101c000b20144101101c000b9d0701037f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002802002202413f4b0d00200141046a280200200141086a2802002200470d01200041016a22032000490d1120004101742204200320032004491b22044100480d112000450d05200128020020002004101a2203450d060c170b2002418080014f0d01200141046a2802002203200141086a28020022006b41024f0d02200041026a22042000490d1020034101742200200420042000491b22004100480d102003450d08200128020020032000101a2203450d090c140b200128020021030c160b20024180808080044f0d01200141046a2802002203200141086a28020022006b41044f0d04200041046a22042000490d0e20034101742200200420042000491b22004100480d0e2003450d08200128020020032000101a22030d090c0f0b200128020021030c120b200141046a280200200141086a2802002202470d03200241016a22032002490d0c20024101742204200320032004491b22044100480d0c2002450d09200128020020022004101a22030d0a0c0e0b2004101b22030d110b20044101101c000b200128020021030c050b200128020021030c070b2000101b22030d0b0b20004101101c000b2000101b2203450d060b20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b2004101b2203450d040b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a0000200028020021030240024002400240200141046a2802002202200428020022006b41044f0d00200041046a22042000490d0420024101742200200420042000491b22004100480d042002450d01200128020020022000101a22020d020c070b200128020021020c020b2000101b2202450d050b20012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b101d000b20004101101c000b20044101101c000b20004101101c000b20012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000bfa0603037f017e057f230041e0006b22022400024002400240024020012d000022034101460d0020030d0241012103200141016a21010c010b2001410c6a2802002104200141046a2802002101410021030b200241086a20043602002002200136020420022003360200200020021091010c010b20024100360208200242013703000240024002404101101b2203450d00200242818080801037020420022003360200200341023a0000200341014102101a2203450d01200242828080802037020420022003360200200341003a0001200141086a290300210520034102410a101a2203450d022002428a808080a0013702042002200336020020032005370002200141106a28020021032002200141186a2802002201360250200241d0006a2002105d02400240024002402001450d002003200141286c6a2106200241086a220728020021082002280204210403400240024002400240200420086b41204f0d00200841206a22012008490d0620044101742209200120012009491b220a4100480d062004450d0120022802002004200a101a22090d020c070b200841206a2101200228020021090c020b200a101b2209450d050b2002200a36020420022009360200200a21040b20072001360200200920086a220841186a200341186a290000370000200841106a200341106a290000370000200841086a200341086a29000037000020082003290000370000200341206a29030021050240200420016b41074b0d00200141086a22082001490d032004410174220a20082008200a491b22084100480d03024002402004450d00200920042008101a22090d010c070b2008101b2209450d060b2002200836020420022009360200200821040b2007200141086a2208360200200920016a20053700002006200341286a2203470d000b0b200241d0006a41086a2203200241086a280200360200200220022903003703502002410c6a2003280200360200200241033a00002002200229035037020420024103360250200220024104723602542000200241d0006a10910120022d00002203417f6a4102490d06024020030d00200241086a280200450d0720022802041019200241e0006a24000f0b200241086a280200450d0620022802041019200241e0006a24000f0b101d000b200a4101101c000b20084101101c000b41014101101c000b41024101101c000b410a4101101c000b200241e0006a24000bc51505017f037e017f037e077f230041d0036b2202240002400240200129037022034202520d00200241086a20014188016a41d8001095031a420021030c010b20024198016a200141e4006a29000037030020024190016a200141dc006a29000037030020024188016a200141d4006a29000037030020024180016a200141cc006a290000370300200241f8006a200141c4006a290000370300200241e0006a41106a2001413c6a290000370300200241e0006a41086a200141346a2900003703002002200129002c37036020012903002105200241a0016a41106a200141f0006a220641106a290300370300200241a0016a41086a200641086a290300370300200220062903003703a00120014180016a2903002107200129037821084200210920024180026a41086a220642003703002002420037038002419c82c000410d20024180026a1001200241086a41086a2006290300370300200220022903800237030842002104024002400240024002400240024002400240200241086a411041d889c200410041001000417f460d002002420037038002200241086a411020024180026a41084100100041016a41084d0d0120022903800221040b024020034201520d002008500d032004200720072004541b2203200320077d2008827d21090b20024180026a20091060200241d4016a41026a20022d0082023a0000200241086a41086a220620024193026a290000370300200241086a410d6a220a20024198026a290000370000200220022f0180023b01d4012002200229008b02370308200228008302210b200228008702210c200241b8016a410d6a200a290000370000200241b8016a41086a2006290300370300200220022903083703b8012001410c6a2802002106200141086a2d0000210d2001280210210a200241bc036a41026a220e2001410b6a2d00003a000020024180026a41086a220f2001411c6a29020037030020024180026a410d6a2210200141216a290000370000200220012f00093b01bc0320022001290214370380020240024002400240024002400240200d4101470d00200241c0036a2006410676106120022802c8032006413f7122064d0d01200241b8036a41026a20022802c00320064105746a220641026a2d00003a0000200241a0036a200641136a290000370300200241a5036a200641186a290000370000200220062f00003b01b8032002200629000b370398032006280007210a200628000321064101210d20022802c4030d020c030b200241b8036a41026a200e2d00003a000020024198036a41086a200f29030037030020024198036a410d6a2010290000370000200220022f01bc033b01b8032002200229038002370398030c030b4100210d20022802c403450d010b20022802c00310190b200d450d010b200241c0036a41026a200241b8036a41026a2d00003a000020024180026a41086a20024198036a41086a29030037030020024180026a410d6a20024198036a410d6a290000370000200220022f01b8033b01c0032002200229039803370380024100210d0c010b4101210d4115210a41bde3c10021060b200241fc016a41026a220e200241c0036a41026a2d00003a0000200241086a41086a220f20024180026a41086a2210290300370300200241086a41106a20024180026a41106a290300370300200220022f01c0033b01fc0120022002290380023703080240200d450d002000200636020420004101360200200041086a200a36020020014188016a1062200241d0036a24000f0b200241eb016a200f290300370000200241f0016a200241086a410d6a290000370000200220022f01fc013b01d8012002200a3600df01200220063600db01200220022903083700e3012002200e2d00003a00da012002200537038002201020014188016a41d800109503210e200241ff026a200c360000200241fb026a200b360000200241f0026a200241a0016a41106a290300370300200241e8026a2201200241a0016a41086a290300370300200241fa026a200241d4016a41026a2d00003a000020024183036a20022903b8013700002002418b036a200241b8016a41086a29030037000020024190036a200241b8016a410d6a290000370000200220022903a0013703e002200220022f01d4013b01f802200241003602102002420137030820024180026a200241086a1063200e200241086a106402400240024002400240024002400240024020022903e0024201520d0020012903002203420c882204420120044201561b22044200510d0c200241f0026a2903002004802104200228020c2206200241106a28020022016b41024f0d01200141026a220a2001490d0a20064101742201200a200a2001491b22014100480d0a2006450d05200228020820062001101a22060d060c0e0b0240200228020c200241106a2802002201470d00200141016a22062001490d0a2001410174220a20062006200a491b220a4100480d0a2001450d0220022802082001200a101a22060d030c0d0b200228020821060c030b200228020821060c050b200a101b2206450d0a0b2002200a36020c20022006360208200241106a28020021010b200241106a200141016a360200200620016a41003a00000c030b2001101b2206450d080b2002200136020c20022006360208200241106a28020021010b200241106a200141026a360200200620016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b024002400240200228020c220b200241106a28020022016b41204f0d00200141206a22062001490d04200b4101742201200620062001491b220a4100480d04200b450d012002280208200b200a101a2206450d020c090b200228020821060c090b200a101b22060d070b200a4101101c000b41fcf9c00041331030000b101d000b41e4d7c3001029000b4188b2c2001029000b200a4101101c000b20014101101c000b2002200a36020c20022006360208200241106a2802002101200a210b0b200620016a220a200241f8026a220d290000370000200a41186a200d41186a290000370000200a41106a200d41106a290000370000200a41086a200d41086a290000370000024002400240200141206a2201418102490d00200241086a41186a220a4200370300200241086a41106a220d4200370300200241086a41086a220c42003703002002420037030820062001200241086a100520024198036a41186a200a29030037030020024198036a41106a200d29030037030020024198036a41086a200c290300370300200220022903083703980320024198036a4120200241e0006a200241d8016a10062101200b0d010c020b20062001200241e0006a200241d8016a10062101200b450d010b200610190b02402001450d00200041d2e3c10036020420004101360200200041086a411a360200200e1062200241d0036a24000f0b20024198036a41186a200241d8016a41186a29030037030020024198036a41106a200241d8016a41106a29030037030020024198036a41086a200241d8016a41086a290300370300200220022903d801370398032002290380022104200241086a200e41d8001095031a420121030b200041086a2003370300200041306a2004370300200041106a200229039803370300200041186a20024198036a41086a290300370300200041206a20024198036a41106a290300370300200041286a20024198036a41186a290300370300200041386a200241086a41d8001095031a20004100360200200241d0036a24000bf60201037f230041306b22022400024002404110101b2203450d00200341086a41002900828340370000200341002900fa8240370000200341104120101a2203450d0120032001370010200241106a41086a220442003703002002420037031020034118200241106a1001200241086a2004290300370300200220022903103703000240024002402002411041d889c200410041001000417f460d00200241106a41186a4200370300200241106a41106a4200370300200241186a42003703002002420037031020024110200241106a4120410010002204417f460d022004411f4d0d0220002002290310370000200041186a200241106a41186a290300370000200041106a200241106a41106a290300370000200041086a200241106a41086a2903003700000c010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000b20031019200241306a24000f0b41fcf9c00041331030000b41104101101c000b41204101101c000b890201027f230041306b22022400024002400240410f101b2203450d00200341076a41002900f39941370000200341002900ec99413700002003410f411e101a2203450d012003200136000f200241206a41086a220142003703002002420037032020034113200241206a1001200241086a200129030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a103a20022802202201450d0420002002290224370204200020013602000c010b20004100360208200042013702000b20031019200241306a24000f0b410f4101101c000b411e4101101c000b41fcf9c00041331030000bba0301017f024002400240024002400240024002400240024002400240024020002d00002201410c4b0d0020010e0d0c010c0c0c0203040506070c080c0b200041046a2802004102470d0b200041086a22002802001062200028020010190f0b200041086a10650f0b200041086a2d0000410c490d09200041106a280200450d092000410c6a28020010190f0b200041086a2d000022014105460d0520014102470d082000410c6a22002802001062200028020010190f0b200041086a2802004102470d07200041106a280200450d072000410c6a28020010190f0b200041086a2d00004102470d062000410c6a22002802001062200028020010190f0b200041046a2d00004102470d052000410c6a22002802001062200028020010190f0b200041046a2802004102490d042000410c6a280200450d04200041086a28020010190f0b200041086a2d000022014103490d0320014104460d0120014103470d02200041106a280200450d032000410c6a28020010190f0b2000410c6a22002802001062200028020010190f0b200041346a280200450d01200041306a28020010190f0b200041306a280200450d002000412c6a28020010190f0b0bbf0903017f017e057f230041e0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002903002203423f560d00200141046a280200200141086a2802002200470d01200041016a22042000490d1120004101742205200420042005491b22054100480d112000450d05200128020020002005101a2204450d060c190b2003428080015a0d01200141046a2802002204200141086a28020022006b41024f0d02200041026a22052000490d1020044101742200200520052000491b22004100480d102004450d08200128020020042000101a2204450d090c160b200128020021040c180b20034280808080045a0d01200141046a2802002204200141086a28020022006b41044f0d04200041046a22052000490d0e20044101742200200520052000491b22004100480d0e2004450d08200128020020042000101a22040d090c120b200128020021040c140b4108200379a74103766b22064104490d0e200141046a280200200141086a2802002205470d03200541016a22042005490d0c20054101742207200420042007491b22044100480d0c2005450d09200128020020052004101a22070d0a0c110b2005101b22040d130b20054101101c000b200128020021040c050b200128020021070c070b2000101b22040d0d0b20004101101c000b2000101b2204450d090b20012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a2003a7410274410272360000200241e0006a24000f0b2004101b2207450d070b20012007360200200141046a2004360200200141086a28020021050b200141086a2204200541016a360200200720056a200641027441736a3a0000200220002903002203370308200141046a210703400240024002400240200728020020042802002200470d00200041016a22052000490d0520004101742208200520052008491b22084100480d052000450d01200128020020002008101a22050d020c060b200128020021050c020b2008101b2205450d040b2001200536020020072008360200200428020021000b2004200041016a360200200520006a2003a73a0000200342088821032006417f6a22060d000b200220033703082002200241086a360210200241a0c0c100360214200350450d03200241e0006a24000f0b101d000b20084101101c000b41e8aec3001029000b200241c8006a41146a4100360200200241306a41146a41043602002002413c6a4105360200200241186a41146a4103360200200241d889c2003602582002420137024c20024180afc300360248200241053602342002420337021c200241fcd7c3003602182002200241c8006a3602402002200241146a3602382002200241106a3602302002200241306a360228200241186a4188afc30010f201000b20004101101c000b20044101101c000b20012004360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200420006a2003a74102744101723b0000200241e0006a24000f0b20012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a2003a74102743a0000200241e0006a24000beea70103047f017e067f230041106b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d000022030d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2b20034101742205200420042005491b22054100480d2b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00000240200041086a29030022064202520d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d2c20034101742205200420042005491b22054100480d2c2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a20011063200041086a29030021060b2006a722034101460d012003450d0220002d000021030b200341ff01714101470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2820034101742205200420042005491b22054100480d282003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41f895c3001029000b41f895c3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a00000240200041086a28020022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41003a00002000410c6a28020021082002200041146a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d2720054101742204200720072004491b22044100480d272005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a28020021030b024020034103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a28020021030b024020034104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41023a00002000410c6a28020021082002200041146a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d2720054101742204200720072004491b22044100480d272005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a28020021030b024020034105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041106a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d2720044101742203200520052003491b22034100480d272004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200420036a2006370000200041086a28020021030b024020034106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41043a00002000410c6a28020021082002200041146a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d2720054101742204200720072004491b22044100480d272005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a28020021030b024020034107470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2720034101742205200420042005491b22044100480d272003450d01200128020020032004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41053a00002000410c6a28020021032002200041146a280200220536020c2002410c6a2001105d02402005450d002003200541186c6a2109200141046a210803402003280200210a2002200341086a280200220536020c2002410c6a2001105d02400240024002402008280200220b200428020022076b20054f0d00200720056a220c2007490d28200b4101742207200c200c2007491b22074100480d28200b450d012001280200200b2007101a220b0d020c080b2001280200210b0c020b2007101b220b450d060b2001200b36020020082007360200200428020021070b2004200720056a360200200b20076a200a20051095031a2003410c6a280200210a2002200341146a280200220536020c2002410c6a2001105d02400240024002402008280200220b200428020022076b20054f0d00200720056a220c2007490d28200b4101742207200c200c2007491b22074100480d28200b450d012001280200200b2007101a220b0d020c090b2001280200210b0c020b2007101b220b450d070b2001200b36020020082007360200200428020021070b2004200720056a360200200b20076a200a20051095031a200341186a22032009470d000b0b200041086a28020021030b20034101460d032003450d0420002d000021030b0240200341ff017122044103460d0020044102470d07200110dd01418495c3001029000b024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2320034101742205200420042005491b22054100480d232003450d01200128020020032005101a2204450d020c070b200128020021040c070b2005101b22040d050b20054101101c000b20074101101c000b20074101101c000b41d8a5c2001029000b41d8a5c2001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00000240200041086a28020022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d2020034101742205200420042005491b22054100480d202003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000410c6a200110cf012002200041306a36020c2002410c6a200110b401200041086a28020021030b024020034103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d2020034101742205200420042005491b22054100480d202003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110cf012002200041306a36020c2002410c6a200110b4012002200041c0006a36020c2002410c6a200110b401200041086a28020021030b20034101460d012003450d0220002d000021030b200341ff01714104470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1c20034101742205200420042005491b22054100480d1c2003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41a080c3001029000b41a080c3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a00000240200041086a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1b20034101742205200420042005491b22054100480d1b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1b20044101742203200520052003491b22034100480d1b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041086a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1b20034101742205200420042005491b22054100480d1b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041106a20011063200041086a2d000021030b0240200341ff01714104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1b20034101742205200420042005491b22054100480d1b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1b20034101742205200420042005491b22054100480d1b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041096a2d00003a0000200041086a2d000021030b200341ff017122034101460d012003450d0220002d000021030b200341ff01714105470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1720034101742205200420042005491b22054100480d172003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b418880c3001029000b418880c3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a00000240200041086a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a2001105d200041086a2d000021030b0240200341ff01714104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110cf01200041086a2d000021030b0240200341ff01714105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a2001105d200041086a2d000021030b0240200341ff01714106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a2001105d200041206a2001105d2002200041106a36020c2002410c6a200110b401200041086a2d000021030b0240200341ff01714107470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200041106a20011063200041086a2d000021030b0240200341ff01714108470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200041106a20011063200041086a2d000021030b0240200341ff01714109470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a00002000410c6a2001105d200041086a2d000021030b0240200341ff0171410a470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041096a2d00003a0000200041086a2d000021030b0240200341ff0171410b470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a2001105d200041086a2d000021030b0240200341ff0171410c470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1620034101742205200420042005491b22054100480d162003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410a3a00002000410c6a28020021032002200041146a280200220436020c2002410c6a2001105d02402004450d0020044105742108200141046a210b03400240024002400240200b2802002207200528020022046b41204f0d00200441206a220a2004490d1720074101742204200a200a2004491b22044100480d172007450d01200128020020072004101a22070d020c080b200128020021070c020b2004101b2207450d060b20012007360200200b2004360200200528020021040b2005200441206a360200200720046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200841606a22080d000b0b200041086a2d000021030b200341ff017122034101460d022003450d0320002d000021030b200341ff01714106470d05024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1220034101742205200420042005491b22054100480d122003450d01200128020020032005101a2204450d020c060b200128020021040c060b2005101b22040d040b20054101101c000b20044101101c000b41a0e3c2001029000b41a0e3c2001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41063a00000240200041086a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000410c6a280200200110642002200041106a36020c2002410c6a200110b401200041086a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a2001105d200041086a2d000021030b0240200341ff01714104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a2001105d02400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041096a2d00003a0000200041086a2d000021030b0240200341ff01714105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002000410c6a2802002001106402400240024002400240024002400240024002400240024002400240024002400240024002400240200041096a2d000022034101460d0020034102470d01200141046a280200200141086a2802002203470d03200341016a22042003490d1f20034101742205200420042005491b22054100480d1f2003450d08200128020020032005101a22040d090c100b200141046a28020020052802002203470d01200341016a22042003490d1e20034101742205200420042005491b22054100480d1e2003450d04200128020020032005101a22040d050c0e0b200141046a280200200141086a2802002203470d02200341016a22042003490d1d20034101742205200420042005491b22054100480d1d2003450d09200128020020032005101a22040d0a0c0f0b200128020021040c040b200128020021040c060b200128020021040c080b2005101b2204450d090b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00000c060b2005101b2204450d070b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00000c030b2005101b2204450d050b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00000b200041106a2903002106024002400240200141046a2802002204200141086a28020022036b41084f0d00200341086a22052003490d1320044101742203200520052003491b22034100480d132004450d01200128020020042003101a2204450d020c060b200128020021040c060b2003101b22040d040b20034101101c000b20054101101c000b20054101101c000b20054101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200420036a2006370000200041086a2d000021030b0240200341ff01714106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a2001105d200041086a2d000021030b0240200341ff01714107470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200041106a200110632000410c6a2001105d200041086a2d000021030b200341077122034101460d012003450d0220002d000021030b200341ff01714107470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41ecaac3001029000b41ecaac3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a000002400240024002400240200041086a28020022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0f20034101742205200420042005491b22054100480d0f2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000410c6a28020021042002200041146a280200220836020c2002410c6a2001105d02402008450d00200141046a210b03400240024002400240200b28020020052802002203470d00200341016a22072003490d102003410174220a20072007200a491b220a4100480d102003450d0120012802002003200a101a22070d020c070b200128020021070c020b200a101b2207450d050b20012007360200200b200a360200200528020021030b2005200341016a360200200720036a20042d00003a0000200441016a21042008417f6a22080d000b0b200041186a2001105d200041086a28020021030b20034103470d03024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c040b200128020021040c040b2005101b22040d020b20054101101c000b200a4101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a2001105d200041106a200110cf01200041346a2001105d200041386a2001105d200041086a28020021030b024020034104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a2001105d200041086a28020021030b024020034105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a2001105d200041086a28020021030b024020034106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a200110cf012002200041386a36020c2002410c6a200110b401200041306a2001105d200041086a28020021030b024020034107470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a2001105d200041086a28020021030b024020034108470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000410c6a200110cf01200041086a28020021030b024020034109470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041106a20011063200041086a28020021030b02402003410a470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041106a20011063200041086a28020021030b20034101460d012003450d0220002d000021030b200341ff01714108470d08024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0720034101742205200420042005491b22054100480d072003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41dccac2001029000b41dccac2001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a00000240200041086a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0620034101742205200420042005491b22054100480d062003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000410c6a28020020011064200041086a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0620034101742205200420042005491b22054100480d062003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d0620044101742203200520052003491b22034100480d062004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0620034101742205200420042005491b22054100480d062003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041296a2d00003a0000200041086a2d000021030b200341ff01714104470d03024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0320034101742205200420042005491b22054100480d032003450d01200128020020032005101a2204450d020c040b200128020021040c040b2005101b22040d020b20054101101c000b101d000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1120044101742203200520052003491b22034100480d112004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041086a2d000021030b0240200341ff01714105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1120034101742205200420042005491b22054100480d112003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a0000200041106a20011063200041086a2d000021030b0240200341ff01714106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1120034101742205200420042005491b22054100480d112003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a0000200041106a20011063200041086a2d000021030b200341ff017122034101460d012003450d0220002d000021030b200341ff01714109470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0d20034101742205200420042005491b22054100480d0d2003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41a8e5c2001029000b41a8e5c2001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41093a00000240200041046a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a2001105d2000410c6a28020020011064200041046a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d0c20044101742203200520052003491b22034100480d0c2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041286a2001105d02400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041256a2d00003a0000200041046a2d000021030b200341037122034101460d012003450d0220002d000021030b200341ff0171410a470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0820034101742205200420042005491b22054100480d082003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41d0aec3001029000b41d0aec3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410a3a000002400240024002400240200041046a28020022034102460d002003450d0120034101470d0441f4c1c3001029000b024002400240200141046a28020020052802002203470d00200341016a22042003490d0820034101742205200420042005491b22054100480d082003450d01200128020020032005101a2204450d020c040b200128020021040c040b2005101b22040d020b20054101101c000b41f4c1c3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41003a0000200041086a28020021082002200041106a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d0720054101742204200720072004491b22044100480d072005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a0b20002d000021030b0240024002400240024002400240024002400240200341ff0171410b470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0f20034101742205200420042005491b22054100480d0f2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410b3a00000240200041086a28020022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a36020c2002410c6a200110b4012000410c6a200110cf01200041086a28020021030b024020034103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a36020c2002410c6a200110b401200041086a28020021030b024020034104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a2001105d2002200041186a36020c2002410c6a200110b401200041286a20011063200041106a2001105d200041086a28020021030b024020034105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a2001105d200041086a28020021030b024020034106470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d1020034101742205200420042005491b22054100480d102003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a2001105d200041086a28020021030b20034101460d012003450d0220002d000021030b200341ff0171410c470d04024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41f0fcc2001029000b41f0fcc2001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410c3a00000240200041086a2d000022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041c0006a280200210702400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2007360000200041106a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041186a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041206a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041286a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041306a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041386a290300210602400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2006370000200041c4006a280200210702400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2007360000200041c8006a280200210702400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2007360000200041086a2d000021030b0240200341ff01714103470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41013a0000200041186a200110632000410c6a28020021082002200041146a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d0b20054101742204200720072004491b22044100480d0b2005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a2d000021030b0240200341ff01714104470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2207200341016a360200200420036a41023a00002000410c6a200110cf012002200041c0006a36020c2002410c6a200110b401200041d0006a20011063200041306a28020021082002200041386a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d0b20054101742204200720072004491b22044100480d0b2005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a2d000021030b0240200341ff01714105470d0002400240024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002002200041386a36020c2002410c6a200110b401200041c8006a2001106302400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2207200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002000412c6a28020021082002200041346a280200220336020c2002410c6a2001105d02400240024002400240200141046a2802002205200728020022046b20034f0d00200420036a22072004490d0b20054101742204200720072004491b22044100480d0b2005450d01200128020020052004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021040b200141086a200420036a360200200520046a200820031095031a200041086a2d000021030b200341077122034101460d012003450d0220002d000021030b200341ff0171410d470d08024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0720034101742205200420042005491b22054100480d072003450d01200128020020032005101a2204450d020c050b200128020021040c050b2005101b22040d030b20054101101c000b41e4d4c3001029000b41e4d4c3001029000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a00000240200041046a28020022034102470d0002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0620034101742205200420042005491b22054100480d062003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a28020020011064200041046a28020021030b20034103470d03024002400240200141046a280200200141086a2802002203470d00200341016a22042003490d0320034101742205200420042005491b22054100480d032003450d01200128020020032005101a2204450d020c040b200128020021040c040b2005101b22040d020b20054101101c000b101d000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a200110cf01200041046a28020021030b20034101460d012003450d020b200241106a24000f0b41dceec2001029000b41dceec2001029000bd80101027f024002400240024002402000280200220141064b0d0020010e0704040104020403040b02402000410c6a2802002202450d0020002802042101200241186c210203400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141186a2101200241686a22020d000b0b200041086a280200450d03200041046a28020010190f0b200041086a280200450d02200028020410190f0b200041086a280200450d01200028020410190f0b200041086a280200450d00200028020410190f0b0bd51701267f230041900d6b2203240020034100360210419384c0004110200341106a41041003200320003703f00c200341086a2204420037030020034200370300419c82c000410d20031001200341106a41086a2205200429030037030020032003290300370310200341106a4110200341f00c6a410810032004420037030020034200370300418487c0004111200310012005200429030037030020032003290300370310200341106a4110200141201003024002404110101b2204450d00200441086a41002900828340370000200441002900fa8240370000200441104120101a2205450d0120052000427f7c370010200341086a22044200370300200342003703002005411820031001200341106a41086a2206200429030037030020032003290300370310200341106a411020014120100320051019200442003703002003420037030041a982c0004115200310012006200429030037030020032003290300370310200341106a41102002412010032004420037030020034200370300419c82c000410d2003100120062004290300370300200320032903003703100240200341106a411041d889c200410041001000417f460d00200342003703f00c02400240200341106a4110200341f00c6a41084100100041016a41084d0d0020032903f00c4200510d02200341086a2204420037030020034200370300419c82c000410d20031001200341106a41086a20042903003703002003200329030037031041002107427f21000240200341106a411041d889c200410041001000417f460d00200342003703f00c200341106a4110200341f00c6a41084100100041016a41084d0d0220032903f00c427f7c21000b200341106a410041e00c1094031a41002108410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f41002120410021214100212241002123410021244100212541002126410021270340200341f00c6a42002000427f7c2000501b22001060200341106a202722014103704105746a220441186a200341f00c6a41186a290200370000200441106a200341f00c6a41106a290200370000200441086a200341f00c6a41086a290200370000200420032902f00c370000200141016a21274100210541002102024003402001200141036e2206417d6c6a4102470d01200341106a20056a220441df006a2d000022262004411f6a2d000022287120262028722004413f6a2d00007172211c200441de006a2d000022262004411e6a2d000022287120262028722004413e6a2d00007172211b200441dd006a2d000022262004411d6a2d000022287120262028722004413d6a2d00007172211a200441dc006a2d000022262004411c6a2d000022287120262028722004413c6a2d000071722119200441db006a2d000022262004411b6a2d000022287120262028722004413b6a2d000071722118200441da006a2d000022262004411a6a2d000022287120262028722004413a6a2d000071722117200441d9006a2d00002226200441196a2d00002228712026202872200441396a2d000071722116200441d8006a2d00002226200441186a2d00002228712026202872200441386a2d000071722115200441d7006a2d00002226200441176a2d00002228712026202872200441376a2d000071722114200441d6006a2d00002226200441166a2d00002228712026202872200441366a2d000071722113200441d5006a2d00002226200441156a2d00002228712026202872200441356a2d000071722112200441d4006a2d00002226200441146a2d00002228712026202872200441346a2d000071722111200441d3006a2d00002226200441136a2d00002228712026202872200441336a2d000071722110200441d2006a2d00002226200441126a2d00002228712026202872200441326a2d00007172210f200441d1006a2d00002226200441116a2d00002228712026202872200441316a2d00007172210e200441d0006a2d00002226200441106a2d00002228712026202872200441306a2d00007172210d200441cf006a2d000022262004410f6a2d000022287120262028722004412f6a2d00007172210c200441ce006a2d000022262004410e6a2d000022287120262028722004412e6a2d00007172210b200441cd006a2d000022262004410d6a2d000022287120262028722004412d6a2d00007172210a200441cc006a2d000022262004410c6a2d000022287120262028722004412c6a2d000071722109200441cb006a2d000022262004410b6a2d000022287120262028722004412b6a2d000071722108200441ca006a2d000022262004410a6a2d000022287120262028722004412a6a2d000071722107200441c9006a2d00002226200441096a2d00002228712026202872200441296a2d00007172211d200441c8006a2d00002226200441086a2d00002228712026202872200441286a2d00007172211e200441c7006a2d00002226200441076a2d00002228712026202872200441276a2d00007172211f200441c6006a2d00002226200441066a2d00002228712026202872200441266a2d000071722120200441c5006a2d00002226200441056a2d00002228712026202872200441256a2d000071722121200441c4006a2d00002226200441046a2d00002228712026202872200441246a2d000071722122200441c3006a2d00002226200441036a2d00002228712026202872200441236a2d000071722123200441c2006a2d00002226200441026a2d00002228712026202872200441226a2d000071722124200441c1006a2d00002226200441016a2d00002228712026202872200441216a2d000071722125200441c0006a2d0000222620042d00002228712026202872200441206a2d000071722126200541800c460d01200341106a20052006410574200141096e41e0006c6b6a6a220441ff006a201c3a0000200441fe006a201b3a0000200441fd006a201a3a0000200441fc006a20193a0000200441fb006a20183a0000200441fa006a20173a0000200441f9006a20163a0000200441f8006a20153a0000200441f7006a20143a0000200441f6006a20133a0000200441f5006a20123a0000200441f4006a20113a0000200441f3006a20103a0000200441f2006a200f3a0000200441f1006a200e3a0000200441f0006a200d3a0000200441ef006a200c3a0000200441ee006a200b3a0000200441ed006a200a3a0000200441ec006a20093a0000200441eb006a20083a0000200441ea006a20073a0000200441e9006a201d3a0000200441e8006a201e3a0000200441e7006a201f3a0000200441e6006a20203a0000200441e5006a20213a0000200441e4006a20223a0000200441e3006a20233a0000200441e2006a20243a0000200441e1006a20253a0000200441e0006a20263a0000200541e0006a210520062101200241016a22024111490d000b0b202741d100470d000b2003201c3a008f0d2003201b3a008e0d2003201a3a008d0d200320193a008c0d200320183a008b0d200320173a008a0d200320163a00890d200320153a00880d200320143a00870d200320133a00860d200320123a00850d200320113a00840d200320103a00830d2003200f3a00820d2003200e3a00810d2003200d3a00800d2003200c3a00ff0c2003200b3a00fe0c2003200a3a00fd0c200320093a00fc0c200320083a00fb0c200320073a00fa0c2003201d3a00f90c2003201e3a00f80c2003201f3a00f70c200320203a00f60c200320213a00f50c200320223a00f40c200320233a00f30c200320243a00f20c200320253a00f10c200320263a00f00c200341086a2204420037030020034200370300418b82c000411120031001200341106a41086a2205200429030037030020032003290300370310200341106a4110200341f00c6a41201003200442003703002003420037030041ed82c000410d200310012005200429030037030020032003290300370310200341106a41101002200341900d6a24000f0b41fcf9c00041331030000b41fcf9c00041331030000b4188a6c2001029000b41104101101c000b41204101101c000bb00202027f017e230041206b22012400024002404113101b2202450d002002410f6a41002800998340360000200241086a410029009283403700002002410029008a8340370000200241134133101a2202450d01200220002900003700132002412b6a200041186a290000370000200241236a200041106a2900003700002002411b6a200041086a29000037000042002103200141106a41086a220042003703002001420037031020024133200141106a1001200141086a200029030037030020012001290310370300024002402001411041d889c200410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021030b20021019200141206a240020030f0b41fcf9c00041331030000b41134101101c000b41334101101c000bca0301057f230041106b2202240041002103200241003a000f200128020020012802042002410f6a410120012802081000210420012001280208200441016a41014b22046a22053602080240024002402004450d0002400240024020022d000f22064103712204450d0020044101460d0120044102470d0220024100360208200220063a000841012103200141086a220441002001280200200141046a280200200241086a41017241032005100022012001417f461b22014103200141034922011b20042802006a36020020010d04200228020841027621040c050b20064102762104410121030c040b41002103200241003b0106200220063a00062001280200200141046a280200200241066a4101724101200510002104200141086a22012001280200200441016a220141014b6a36020020014102490d0120022f01064102762104410121030c030b200641044f0d02200141046a28020021044100210320024100360200200141086a2206410020012802002004200241042005100022012001417f461b22014104200141044922011b20062802006a36020020010d0020022802002104410121030c020b0c010b410021030b2000200436020420002003360200200241106a24000bfdac0107067f017e017f037e037f067e047f23004180036b22022400200241003a000820012802002001280204200241086a410120012802081000210320012001280208200341016a220341014b6a220436020802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020034102490d0020022d00082203410d4b0d0e024020030e0e0002030405060708090a0b0c0d0e000b41002105200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22012001280200200341016a41014b22016a3602002001450d12024020022d00082201450d004101210520014101470d130b200020053a0001200041003a0000200041026a200241086a41ee001095031a20024180036a24000f0b2000410e3a000020024180036a24000f0b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d0d20022d00080d0d200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220341002001280200200141046a2205280200200241086a41202004100022042004417f461b22044120200441204922041b20032802006a220636020020040d0d200241d0016a41086a22042002411c6a290200370300200241d0016a41106a2207200241246a280200360200200220022902143703d001200229020c210820022802082109200241b8016a41106a2007280200360200200241b8016a41086a2004290300370300200220022903d0013703b80120052802002104200241003602082003410020012802002004200241086a41042006100022012001417f461b2201410420014104491b20032802006a360200200141034d0d0d20022802082101200241b6016a20022d00ba013a0000200220083702ac01200220093602a801200220022f01b8013b01b401200241cb016a310000210820022800bb01210320022900bf01210a20023500c701210b200220022900af013700d702200220022903a8013703d002200220022900d70237000f200220022903d002370308200220022903083703b0022002200229000f3700b702200041276a20083c0000200041236a200b3e0000200041013a0000200041046a20013600002000411b6a200a370000200041176a2003360000200020022f00d0023b0001200041036a200241d2026a2d00003a0000200041086a20022903b0023700002000410f6a20022900b702370000200041286a200241086a41c8001095031a20024180036a24000f0b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d4020022d00082203450d1620034101460d1720034102470d40200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20062802006a22063602002003411f4d0d33200241e8016a41086a2203200241086a41146a290200370300200241e8016a41106a2205200241086a411c6a280200360200200220022902143703e80120022802082104200229020c2108200241d0026a41146a2003290300370200200241d0026a411c6a2005280200360200200220083702d402200220043602d002200220022903e8013702dc02410121050c340b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d0d20022d00080d0d20024200370308200141086a220341002001280200200141046a280200200241086a41082004100022012001417f461b2201410820014108491b20032802006a360200200141074d0d0d20022903082108200041033a0000200041086a2008370300200020022800d002360001200041046a200241d0026a41036a280000360000200041106a200241086a41e0001095031a20024180036a24000f0b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d4220022d00082203450d1620034101460d1720034102470d42200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20062802006a22043602002003411f4d0d33200241e8016a41086a22052002411c6a290200370300200241e8016a41106a2206200241246a280200360200200220022902143703e801200229020c210820022802082103200241b8016a41106a2006280200360200200241b8016a41086a2005290300370300200220022903e8013703b801200341ff01712106200341807e712105410121030c340b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d4520022d0008220341064b0d45024020030e0700353637384344000b200141046a2206280200210320024100360208200141086a2205410020012802002003200241086a41042004100022032003417f461b2203410420034104491b20052802006a2204360200200341034d0d45200228020821034200210a20024200370310200242003703082005410020012802002006280200200241086a41102004100022012001417f461b2201411020014110491b20052802006a3602002001410f4d0d45200228021422044180808078712107200229020c210b2002280208210641002105420021080c440b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d6020022d0008220341034b0d60024020030e0400171819000b200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20062802006a22063602002003411f4d0d45200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210c20022802082107200241f7016a350000200241fb016a3100004220868442188620022900ef01220a422888842108200a421886210a20022d00eb01411874210520023301ec0120023100ee0142108684210b20022f01e80120022d00ea01411074722103410121040c460b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220441014b6a22053602004102210320044102490d2b20022d00082204450d0d20044101470d2b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002106200141086a220741002001280200200141046a280200200241086a41202005100022042004417f461b2204412020044120491b20072802006a22053602002004411f4d0d18200241e8016a41086a22062002411c6a290200370300200241e8016a41106a2207200241246a280200360200200220022902143703e801200229020c210820022802082104200241b8016a41106a2007280200360200200241b8016a41086a2006290300370300200220022903e8013703b801200441ff01712107200441807e712106410121040c190b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d5c20022d0008220341044b0d5c024020030e05002d1a1b1c000b200241206a4200370300200241086a41106a4200370300200241086a41086a4200370300200242003703084100210d200141086a220541002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20052802006a22063602002003411f4d0d57200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210820022802082103200220022900ef013703f0022002200241f4016a2900003700f502200341ff0171210d200341807e71210e20022f01e80120022d00ea014110747221034101210520022800eb0121040c580b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a36020020034102490d6120022d0008450d0a0c610b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d2120022d0008220341044b0d21024020030e05001b1c1d1e000b200141046a28020021054100210320024100360208200141086a2206410020012802002005200241086a41042004100022012001417f461b2201410420014104491b20062802006a360200200141034d0d21200228020821074200210a42002108410021014100210d4100210f410021060c200b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d074105210320022d0008220541044b0d5d024020050e050022232425000b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002107200141086a220541002001280200200141046a280200200241086a41202004100022042004417f461b2204412020044120491b20052802006a22093602002004411f4d0d45200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e80120022802082105200229020c2108200241be026a20022d00ea013a0000200220083702b402200220053602b002200220022f01e8013b01bc02200220022900ef013703a0022002200241f4016a2900003700a5024101210720022800eb0121060c460b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a220341014b6a220436020020034102490d0b20022d00082203450d0920034101470d0b200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220341002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20032802006a3602002001411f4d0d0b200241d0016a41086a22012002411c6a290200370300200241d0016a41106a2203200241246a280200360200200220022902143703d001200229020c210820022802082104200241b8016a41106a22052003280200360200200241b8016a41086a22032001290300370300200220022903d0013703b801200241d0026a41106a2005280200360200200241d0026a41086a2003290300370300200220022903b8013703d00220044108762101410121030c0a0b200241003a00082001280200200141046a280200200241086a4101200410002103200141086a22042004280200200341016a41014b22036a22043602002003450d0220022d00080d02200141046a2206280200210520024100360208200141086a2203410020012802002005200241086a41042004100022042004417f461b2204410420044104491b20032802006a2205360200200441034d0d022002280208210420024200370310200242003703082003410020012802002006280200200241086a41102005100022012001417f461b2201411020014110491b20032802006a3602002001410f4d0d0220022903082108200041106a200241086a41086a290300370300200041086a20083703002000410d3a0000200041186a2004360200200020022800d002360001200041046a200241d3026a2800003600002000411c6a200241086a41d4001095031a20024180036a24000f0b2000410e3a000020024180036a24000f0b200220022902d0023703082002200241d7026a29000037000f2000410e3a000020024180036a24000f0b2000410e3a000020024180036a24000f0b2000410e3a000020024180036a24000f0b2000410e3a000020024180036a24000f0b410521030c550b200241086a2001105620022802082201450d56200229020c2108200041093a0000200041086a2008370000200041046a2001360000200020022f00d0023b0001200041036a200241d2026a2d00003a0000200041106a200241086a41e0001095031a20024180036a24000f0b200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002106200141086a220741002001280200200141046a280200200241086a41202005100022042004417f461b2204412020044120491b20072802006a22073602002004411f4d0d1b200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210c20022802082109200241f7016a350000200241fb016a3100004220868442188620022900ef01220a422888842108200a421886210a20022d00eb01411874210620023301ec0120023100ee0142108684210b20022f01e80120022d00ea01411074722104410121050c1c0b41002103200241003a00082001280200200141046a280200200241086a4101200410002104200141086a22012001280200200441016a41014b22016a3602002001450d0120022d00082104200241d0026a41106a200241086a41106a280000360200200241d0026a41086a200241086a41086a290000370300200220022900083703d0020b200241086a41106a200241d0026a41106a2802002205360200200241086a41086a200241d0026a41086a290300220a370300200241b0026a41086a2206200a370300200241b0026a41106a22072005360200200220022903d002220a3703b0022002200a370308200041056a20014110763a0000200041036a20013b0000200041066a2008370000200041026a20043a0000200020033a00012000410c3a00002000410e6a20022903b002370000200041166a20062903003700002000411e6a2007280200360000200041226a200241086a41ce001095031a20024180036a24000f0b200241086a41106a200241d0026a41106a280200360200200241086a41086a200241d0026a41086a290300370300200220022903d0023703082000410e3a000020024180036a24000f0b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002106200141086a220541002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20052802006a22073602002003411f4d0d24200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200228020821042002200229020c2208370298022002200436029402200220022900ef013703a8012002200241f4016a2900003700ad0120022f01e80120022d00ea014110747221034101210620022800eb0121050c250b4200210a200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220341002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20032802006a3602002001411f4d0d25200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c21082002280208210420022900ef01220a422888210b200a421886210c20022d00eb01411874210520023301ec0120023100ee0142108684210a20022f01e80120022d00ea0141107472210320023500f701200241fb016a3100004220868442188621104200211141012101420021120c260b42002108200242003703102002420037030841002103200141086a220541002001280200200141046a280200200241086a41102004100022012001417f461b2201411020014110491b20052802006a3602002001410f4d0d2b200241086a41086a290300220b422088a721042002290308210a200ba721054200210c410021090c2a0b200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20062802006a22063602002003411f4d0d27200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210c20022802082107200241f7016a350000200241fb016a3100004220868442188620022900ef01220a422888842108200a421886210a20022d00eb01411874210520023301ec0120023100ee0142108684210b20022f01e80120022d00ea01411074722103410121040c280b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002103200141086a220541002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20052802006a3602002001411f4d0d30200241e8016a41086a22012002411c6a290200370300200241e8016a41106a2204200241246a280200360200200220022902143703e801200229020c210a20022802082103200241b8016a41106a2004280200360200200241b8016a41086a2001290300370300200220022903e8013703b801200341ff01712101200341807e712103410121040c310b200141046a280200210320024100360208200141086a2205410020012802002003200241086a41042004100022012001417f461b2201410420014104491b20052802006a360200200141034d0d4820022802082103410221050c310b200241086a2001103a20022802082203450d47200229020c2108200241086a2001103a2008a7210420022802082207450d462008422088a7210f200229020c2110410321050c300b41002107410021040b200241d0016a41106a200241b8016a41106a280200360200200241d0016a41086a200241b8016a41086a290300370300200220022903b8013703d0012004450d11200241b6016a20022d00d2013a0000200220083702ac01200220022f01d0013b01b401200220062007723602a801200241e3016a310000210820022800d301210420022900d701210a20023500df01210b200141046a2209280200210620024100360208200141086a2207410020012802002006200241086a41042005100022052005417f461b2205410420054104491b20072802006a2206360200200541034d0d11200228020821052009280200210920024100360208200141086a2207410020012802002009200241086a41042006100022062006417f461b2206410420064104491b20072802006a2209360200200641034d0d1120022802082106200141046a280200210d20024100360208200741002001280200200d200241086a41042009100022012001417f461b2201410420014104491b20072802006a360200200141034d0d11200228020821012002200b20084220868422083e00eb02200241ef026a20084220883c00002002200a3700e302200220043600df02200220022900af013700d702200220022903a8013703d002200220022900d70237007f200220022903d002370378200220022900e302370380022002200241e8026a29000037008502410121030c120b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002103200141086a220541002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20052802006a3602002001411f4d0d30200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e80120022802082101200229020c2108200241ae026a20022d00ea013a0000200220083702a402200220013602a002200220022f01e8013b01ac02200220022900ef013703f0022002200241f4016a2900003700f5024101210320022800eb0121040c310b200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002103200141086a220541002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20052802006a3602002001411f4d0d31200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210820022802082101200241f7016a350000200241fb016a3100004220868442188620022900ef01220b42288884210a200b421886210b20022d00eb01411874210320023301ec0120023100ee0142108684210c20022f01e80120022d00ea01411074722104410121050c320b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20062802006a22063602002003411f4d0d33200241e8016a41086a22042002411c6a290200370300200241e8016a41106a2205200241246a280200360200200220022902143703e801200229020c210820022802082103200241b8016a41106a2005280200360200200241b8016a41086a2004290300370300200220022903e8013703b801200341ff01712104200341807e712105410121030c340b4200210a200242003703102002420037030841002103200141086a220541002001280200200141046a280200200241086a41102004100022012001417f461b2201411020014110491b20052802006a3602002001410f4d0d06200241086a41086a2903002208422088a7210f2002290308210c2008a7210d410121064100210442002108410021090c030b200141046a2206280200210320024100360208200141086a2205410020012802002003200241086a41042004100022032003417f461b2203410420034104491b20052802006a2207360200200341034d0d052002280208210420024200370310200242003703082005410020012802002006280200200241086a41102007100022032003417f461b2203411020034110491b20052802006a22063602002003410f4d0d05200241086a41086a2203290300210a20022903082110200241086a41186a4200370300200241086a41106a42003703002003420037030020024200370308200141086a220341002001280200200141046a280200200241086a41202006100022012001417f461b2201412020014120491b20032802006a3602002001411f4d0d052002200229000f3700af01200220022903083703a8012002280017210120023500232108200229001b210b200241fb016a200241086a411f6a3100003c00002002200b3700ef01200220083e00f701200241e4026a200241e8016a41086a290300370200200241ec026a200241f8016a280200360200200220013600eb012002200241b6016a2d00003a00ea01200220022f01b4013b01e801200220022902ac013702d402200220022802a80122013602d002200220022903e8013702dc022010421888200a42288684210820044118762103200a421888210a20023500eb02200241d0026a411f6a31000042208684210b20022800e702210520022800e302210f20022800df02210d20022900d702210c20022800d30221072010a72109410221060c040b200242003703102002420037030841002105200141086a220341002001280200200141046a280200200241086a41102004100022012001417f461b2201411020014110491b20032802006a3602002001410f4d0d042002290308210c20023500c701200241cb016a31000042208684210a20022f01bc0120022d00be0141107472210920022f01b80120022d00ba01411074722104200241086a41086a290300220b422088a7210f20022900bf01210820022d00bb012103200ba7210d410321060c020b200242003703102002420037030841042106200141086a220341002001280200200141046a280200200241086a41102004100022012001417f461b2201411020014110491b20032802006a3602002001410f4d0d032002290308210c20022902d401220b421888200241dc016a290200220a422886842108200a421888210a20022802d00122044118762103200241086a41086a2903002210422088a7210f2010a7210d200ba721090b0b0b200020022800d0023600012000410a3a00002000410b6a20014110763a0000200041096a20013b0000200041106a200c370000200041246a200b370000200041206a20053600002000410c6a2007360000200041086a20063a0000200041c0006a2002290308370300200041386a200a421886200842288884370000200041046a200241d3026a2800003600002000412c6a2003411874200441ffffff077172360000200041c8006a200241086a41086a290300370300200041d0006a200241086a41106a290300370300200041d8006a200241086a41186a290300370300200041e0006a200241086a41206a290300370300200041e8006a200241306a290300370300200041306a20084218862009ad42ffffff078384370000200041186a200fad422086200dad8437000020024180036a24000f0b2000410e3a000020024180036a24000f0b42002108200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002106200141086a220541002001280200200141046a280200200241086a41202004100022042004417f461b2204412020044120491b20052802006a22093602002004411f4d0d2c200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c21122002280208210520022900ef012208422888210a2008421886210b20022d00eb01411874210620023301ec0120023100ee0142108684210820022f01e80120022d00ea0141107472210420023500f701200241fb016a31000042208684421886210c4200211041012107420021110c2d0b200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002106200141086a220541002001280200200141046a280200200241086a41202004100022012001417f461b2201412020014120491b20052802006a3602002001411f4d0d2d200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210c20022802082105200241f7016a350000200241fb016a3100004220868442188620022900ef01220a422888842108200a421886210a20022d00eb01411874210620023301ec0120023100ee0142108684210b20022f01e80120022d00ea01411074722101410121040c2e0b200141046a280200210520024100360208200141086a2206410020012802002005200241086a41042004100022012001417f461b2201410420014104491b20062802006a360200200141034d0d392002280208210f2002200241086a41056a29000037009d012002200229020837039801200220022902d002370388012002200241d0026a41056a29000037008d01410321030c3a0b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220641002001280200200141046a280200200241086a41202004100022042004417f461b2204412020044120491b20062802006a22073602002004411f4d0d2d200241e8016a41086a22052002411c6a290200370300200241e8016a41106a2206200241246a280200360200200220022902143703e801200229020c210820022802082104200241b8016a41106a2006280200360200200241b8016a41086a2005290300370300200220022903e8013703b801200441ff01712106200441807e712105410121040c2e0b4200210b4200210a42002108410021050b200241dc016a20084200843702002002200a200b843702d40120022006200441ffffff0771723602d0012005450d00200241c4026a200241d0016a41086a290300370200200241cc026a200241e0016a2802003602002002200c3702b402200220093602b002200220022903d0013702bc02200141046a2209280200210420024100360208200141086a2206410020012802002004200241086a41042007100022042004417f461b2204410420044104491b20062802006a2207360200200441034d0d002002280208210520092802002104200241003602082006410020012802002004200241086a41042007100022042004417f461b2204410420044104491b20062802006a2207360200200441034d0d0020022802082106200141046a280200210420024100360208200141086a2209410020012802002004200241086a41042007100022012001417f461b2201410420014104491b20092802006a360200200141034d0d00200228020821012002200241b7026a2900003700a702200220022902b0023703a002200220022900c3023703f0022002200241c8026a2900003700f50220022800bf022104200220022900a70237007f200220022903a002370378200220022903f00237038002200220022900f50237008502410021030c010b0b2002200229007f37000f2002200229037837030820022002290380023703d00120022002290085023700d501024020034102470d002000410e3a000020024180036a24000f0b2002200229000f3700ef01200220022903083703e801200220022903d0013703b801200220022900d5013700bd01200041073a0000200041046a20033a0000200041146a2004360000200041306a20013600002000412c6a2006360000200041286a2005360000200020022f00d0013b0001200041036a200241d0016a41026a2d00003a0000200041056a20022903e8013700002000410c6a20022900ef01370000200041186a20022903b8013700002000411d6a20022900bd01370000200041ec006a200241c0006a280200360200200041e4006a200241086a41306a290200370200200041dc006a200241086a41286a290200370200200041d4006a200241286a290200370200200041cc006a200241086a41186a290200370200200041c4006a200241186a2902003702002000413c6a200241106a290200370200200041346a200229020837020020024180036a24000f0b200241206a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002107200141086a220541002001280200200141046a280200200241086a41202004100022032003417f461b2203412020034120491b20052802006a22063602002003411f4d0d2d200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210820022802082103200220022900ef013703782002200241f4016a29000037007d200341ff0171210f200341807e71210720022f01e80120022d00ea014110747221034101210520022800eb0121040c2e0b20022902d402210820022802d00221040b200241d0016a41106a200241ec026a280200360200200241d0016a41086a200241e4026a290200370300200220022902dc023703d0012005450d0b200241dc016a290200211120022902d401211220022802d0012103200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220741002001280200200141046a2209280200200241086a41202006100022052005417f461b2205412020054120491b20072802006a22063602002005411f4d0d0b200241e8016a41086a22052002411c6a290200370300200241e8016a41106a2207200241246a280200360200200220022902143703e8012002280208210d200229020c210a200241b8016a41106a2007280200360200200241b8016a41086a2005290300370300200220022903e8013703b801200241b6016a20022d00ba013a00002002200a3702ac012002200d3602a801200220022f01b8013b01b401200241cb016a310000211320022800bb01210720022900bf01211420023500c70121152002420037031020024200370308200141086a220d410020012802002009280200200241086a41102006100022052005417f461b2205411020054110491b200d2802006a22063602002005410f4d0d0b200241086a41086a290300210b2002290308210a2002420037031020024200370308200d41002001280200200141046a280200200241086a41102006100022012001417f461b2201411020014110491b200d2802006a3602002001410f4d0d0b200241106a290300210c20022903082110200241c8026a220120113702002002201520134220868422113e02f802200241fc026a220520114220883c0000200220123702c002200220033602bc02200220083702b402200220043602b002200220022903a8013703a002200220022900af013700a702200220143703f002200220022900c302370398012002200129000037009d0120022f01a00220022d00a2024110747221012005310000211120022902f402211220022800bf02210520022800a302210920022900a70221132014a7210d410221060c0a0b41002106410021030b200241d0016a41106a200241b8016a41106a280200360200200241d0016a41086a200241b8016a41086a290300370300200220022903b8013703d0012003450d0d200241b6016a20022d00d2013a0000200220083702ac01200220022f01d0013b01b401200220052006723602a801200241e3016a310000210b20022800d301210520022900d701210a20023500df0121102002420037031020024200370308200141086a220341002001280200200141046a280200200241086a41102004100022012001417f461b2201411020014110491b20032802006a3602002001410f4d0d0d200241106a290300210c2002290308210820022010200b42208684220b3e00eb02200241ef026a200b4220883c0000200220053600df02200220022900af013700d702200220022903a8013703d002200b42ffffffffff1f83210b2002200a3700e30220022f01d00220022d00d202411074722101200a422088a7210620022900df022210422088a7210420022900d702210a20022800d30221072010a72105410221090c0c0b200141046a2206280200210320024100360208200141086a2205410020012802002003200241086a41042004100022032003417f461b2203410420034104491b20052802006a2204360200200341034d0d102002280208210320024200370310200242003703082005410020012802002006280200200241086a41102004100022042004417f461b2204411020044110491b20052802006a3602002004410f4d0d10200241106a290300210a2002290308210c200241086a2001103a20022802082206450d10200c421888200a422886842108200a421888210a200229020c210b200ca7210941012105410021070c0f0b200141046a2206280200210320024100360208200141086a2205410020012802002003200241086a41042004100022032003417f461b2203410420034104491b20052802006a2204360200200341034d0d0f20022802082103200241003a000820012802002006280200200241086a410120041000210120052005280200200141016a41014b22016a3602002001450d0f20022d0008220141034f0d0f20022f01b401200241b6016a2d000041107472210420022902ac01210b20022802a80121064102210541002107410021090c0e0b200141046a28020021034100210620024100360208200141086a2205410020012802002003200241086a41042004100022012001417f461b2201410420014104491b20052802006a36020041032105200141034d0d0e2002280208210320022902bc01220b421888200241c4016a290200220a422886842108200a421888210a20022802b80122044180808078712107200ba721090c0d0b41042105200141046a280200210320024100360208200141086a2206410020012802002003200241086a41042004100022012001417f461b2201410420014104491b20062802006a360200200141034d0d0d2002280208210320022902d401220b421888200241dc016a290200220a422886842108200a421888210a20022802d00122044180808078712107200ba721090c0c0b0b200241dc016a20022900ad01370000200220053600d301200220022903a8013700d701200220033b01d001200220034110763a00d2012006450d032002200241d0016a41077222062900003703782002200641056a29000037007d4200210a200242003703102002420037030841002106200141086a220941002001280200200141046a280200200241086a41102007100022012001417f461b2201411020014110491b20092802006a3602002001410f4d0d03200241086a41086a290300210b200229030821132002200229007d370085022002200229037837038002200220022900850237009d01200220022903800237039801200b422088a7210d200ba721074200210b0c020b420021114200210c4200210b4200211242002110410021010b200241dc016a22062010200b8420118437020020022012200c84200a843702d40120022005200341ffffff0771723602d0012001450d01200220022900d7013703b801200220062900003700bd0120022800d3012105200220022900bd0137009d01200220022903b8013703980141012106410021074100210d0b2002200229009d0137000d2002200229039801370308200220022903083703d0022002200229000d3700d502200041176a20034110763a0000200041156a20033b00002000412b6a20014110763a0000200041296a20013b0000200041e8006a200c370000200041e0006a2010370000200041d8006a200b370000200041d0006a200a370000200041c8006a2011370000200041c0006a2012370000200041386a200dad4220862007ad84370000200041306a2013370000200041023a0000200041186a20053600002000410d6a2008370000200041096a2004360000200041086a20063a00002000412c6a200936000020002002280008360001200041046a2002410b6a2800003600002000411c6a20022903d002370000200041216a20022900d50237000020024180036a24000f0b2002200229009d0137000d20022002290398013703082000410e3a000020024180036a24000f0b4200210b4200210a42002108410021040b200241dc016a20084200843702002002200a200b843702d40120022005200341ffffff0771723602d0012004450d01200241c4026a200241d0016a41086a290300370200200241cc026a200241d0016a41106a2802003602002002200c3702b402200220073602b002200220022903d0013702bc02200141046a280200210320024100360208200141086a2204410020012802002003200241086a41042006100022012001417f461b2201410420014104491b20042802006a360200200141034d0d01200228020821032002200241b7026a2900003700a702200220022902b0023703a002200220022900c3023703f0022002200241c8026a2900003700f50220022800bf02210520023502f802200241fc026a31000042208684210b20022f01a00220022d00a20241107472210120022802f402210620022802f002210420022900a702210a20022800a3022107410121090b200020022800d002360001200041043a00002000410b6a20014110763a0000200041096a20013b0000200041386a200c370000200041306a2008370000200041106a200a3700002000412c6a2003360000200041246a200b370000200041206a20063600002000410c6a2007360000200041086a20093a0000200041c0006a2002290308370300200041046a200241d3026a280000360000200041c8006a200241086a41086a290300370300200041d0006a200241086a41106a290300370300200041d8006a200241086a41186a290300370300200041e0006a200241086a41206a290300370300200041e8006a200241306a290300370300200041186a2004ad4220862005ad8437000020024180036a24000f0b2000410e3a000020024180036a24000f0b200141046a280200210320024100360208200141086a2205410020012802002003200241086a41042004100022012001417f461b2201410420014104491b20052802006a360200200141034d0d022002280208210320022902ec01220b421888200241f4016a290200220a422886842108200a421888210a20022802e80122044180808078712107200ba72109410521050c010b200141046a22062802002103200241003602d002200141086a2205410020012802002003200241d0026a41042004100022032003417f461b2203410420034104491b20052802006a2204360200200341034d0d0120022802d0022103200241003a00d00220012802002006280200200241d0026a410120041000210120052005280200200141016a41014b22016a3602002001450d0120022d00d00221012002290318220c421888200241206a290300220a422886842108200a421888210a200228021422044180808078712107200229020c210b20022802082106200ca72109410621050b200020022800d002360001200041053a0000200041146a200b370000200041106a20063600002000410c6a2003360000200041096a20013a0000200041086a20053a0000200041306a2002290308370300200041286a200a421886200842288884370000200041046a200241d3026a2800003600002000411c6a2007200441ffffff077172360000200041386a200241086a41086a290300370300200041c0006a200241086a41106a290300370300200041c8006a200241206a290300370300200041d0006a200241086a41206a290300370300200041d8006a200241086a41286a290300370300200041e0006a200241086a41306a290300370300200041e8006a200241086a41386a290300370300200041206a20084218862009ad42ffffff07838437000020024180036a24000f0b2000410e3a000020024180036a24000f0b4200210b4200210a42002108410021040b200241dc016a20084200843702002002200a200b843702d40120022005200341ffffff0771723602d0012004450d19200241b0026a41146a200241d0016a41086a290300370200200241b0026a411c6a200241d0016a41106a2802003602002002200c3702b402200220073602b002200220022903d0013702bc02200241086a41186a4200370300200241086a41106a4200370300200241086a41086a42003703002002420037030841002105200141086a220341002001280200200141046a280200200241086a41202006100022012001417f461b2201412020014120491b20032802006a3602002001411f4d0d19200241e8016a41086a2201200241086a41146a290200370300200241e8016a41106a2203200241086a411c6a280200360200200220022902143703e80120022802082106200229020c210a200241d0026a41146a2001290300370200200241d0026a411c6a20032802003602002002200a3702d402200220063602d002200220022903e8013702dc02200241d0026a41186a290300210c20022903e002210b20022802dc0221092002200241b7026a2900003700a702200220022902b0023703a002200220022900c3023703f0022002200241b0026a41186a2900003700f50220022800bf02210720023502f802200241fc026a31000042208684210820022903f002211020022800ab02210f20022800a702210420022800a302210320022f00a102210d20022d00a00221010c020b41002101410021040b200241d0016a41106a200241b8016a41106a280200360200200241d0016a41086a200241b8016a41086a290300370300200220022903b8013703d0012004450d17200241b6016a20022d00d2013a0000200220022f01d0013b01b401200220032001723602a8012003410876210d20023500df01200241e3016a3100004220868421082002200a3702ac01200a421888a7210420022800d301210720022900d701211020022800b301210f20022800ab012103410121050b200020022f00d0023b0001200041063a0000200041246a20084220883c0000200041206a20083e00002000413d6a200c370000200041356a200b370000200041316a2009360000200041296a200a370000200041256a2006360000200041186a2010370000200041146a2007360000200041106a200f3600002000410c6a2004360000200041086a2003360000200041066a200d3b0000200041056a20013a0000200041046a20053a0000200041036a200241d2026a2d00003a0000200041e8006a200241086a41206a290300370300200041e0006a200241086a41186a290300370300200041d8006a200241086a41106a290300370300200041d0006a200241086a41086a290300370300200041c8006a200229030837030020024180036a24000f0b20022902b40221080b200241dc016a20022900a502370000200220063600d3012002200241b0026a410e6a2d00003a00d201200220022f01bc023b01d001200220022903a0023700d7012007450d16200241b8016a410e6a20022d00d2013a0000200220083702bc01200220022f01d0013b01c4012002200241d0016a41077222042900003703a801410521032002200441056a2900003700ad01200220053602b801200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220d41002001280200200141046a220f280200200241086a41202009100022042004417f461b2204412020044120491b200d2802006a220e3602002004411f4d0d16200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e801200229020c210820022802082107200220022900ef01370380022002200241e8016a410c6a2900003700850220022800eb01210920022f01e801210420022d00ea012116200241d0026a410c6a200229008502370000200220163a00d202200220043b01d002200220093600d30220022002290380023700d7022002420037031020024200370308200d41002001280200200f280200200241086a4110200e100022012001417f461b2201411020014110491b200d2802006a3602002001410f4d0d162005410876210d20042016411074722104200241086a41086a290300210c2002290308210b200220022903a801370378200220022900ad0137007d2002200241d7026a22012900003703f0022002200141056a2900003700f50220022900bf01210a20022800bb01210f2002200229007d37009d012002200229037837039801200220022903f00237038801200220022900f50237008d0120074108762101410021030c170b20022902a402210820022802a00221010b200241dc016a220520022900f502370000200220043600d3012002200241ae026a2d00003a00d201200220022f01ac023b01d001200220022903f0023700d7012003450d102005290200210b20022802d001210320022902d401211020022002410d6a29000037009d0120022002290008370398012010421888200b42288684210a20034118762104200b421888210c2010a7210e410221050c020b4200210c4200210b4200210a410021050b200241dc016a200a4200843702002002200b200c843702d40120022003200441ffffff0771723602d0012005450d0e200241c4026a200241d8016a290300370200200241cc026a200241e0016a280200360200200220083702b402200220013602b002200220022903d0013702bc02200220022900083703980120022002410d6a29000037009d0120022902c002220b421888200241b0026a41186a290200220c42288684210a200c421888210c20022802bc0222034118762104200ba7210e410321050b0c100b41002104410021030b200241d0016a41106a200241b8016a41106a280200360200200241d0016a41086a200241b8016a41086a290300370300200220022903b8013703d0012003450d0b200241a8016a410e6a20022d00d2013a0000200220083702ac01200220022f01d0013b01b401200220052004723602a801200241e3016a310000210820022800d301210420022900d701210a20023500df01210b200241003a0008410421052001280200200141046a280200200241086a4101200610002103200141086a22012001280200200341016a41014b22016a3602002001450d0b20022d000821072002200b20084220868422083e00eb02200241ef026a220120084220883c00002002200a3700e302200220043600df02200220022900af013700d702200220022903a8013703d002200220022901083703980120022002410d6a29000037009d012004410876210e20023500eb02200131000042208684210c20022f01dc02200241d0026a410e6a2d000041107472210320022900e302210a20022902d402210820022802d00221010c080b420021104200210b4200210a420021114200210c410021070b200241dc016a220d200c200a8420108437020020022011200b842008843702d40120022006200441ffffff0771723602d0012007450d0d200220022900d7013703b8012002200d2900003700bd0120022800d3012106200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220741002001280200200141046a280200200241086a41202009100022012001417f461b2201412020014120491b20072802006a3602002001411f4d0d0d200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e80120022802082107200229020c2108200241ae026a220120022d00ea013a0000200220083702a402200220073602a002200220022f01e8013b01ac02200220022900ef013703f0022002200241f4016a2900003700f50220022800eb012109200220022903f002370378200220022900f50237007d20012d0000210320022f01ac02210f2002200536029402200220022903b8013703a801200220022900bd013700ad012002201237029802200220022903a80137039801200220022900ad0137009d0120022002290378370388012002200229007d37008d0120124218882004ad42288684210a2005410876210d20074108762101200f2003411074722104200228009702210f410121030c0e0b4200210b4200210a42002108410021040b200241dc016a20084200843702002002200a200b843702d40120022006200141ffffff0771723602d0012004450d0b200241c4026a200241d0016a41086a290300370200200241cc026a200241e0016a2802003602002002200c3702b402200220053602b002200220022903d0013702bc02200220022900c302370398012002200241c8026a29000037009d01200220022900083703880120022002410d6a29000037008d012005410876210d20022800bf02210620022900b702210a20022800b302210f410221030c0c0b41002106410021040b200241d0016a41106a200241b8016a41106a280200360200200241d0016a41086a200241b8016a41086a290300370300200220022903b8013703d0012004450d09200241b6016a20022d00d2013a0000200220083702ac01200220022f01d0013b01b401200220052006723602a801200241e3016a310000210820022800d301210620022900d701210a20023500df01210b200241003a00082001280200200141046a280200200241086a4101200710002104200141086a22012001280200200441016a41014b22016a3602002001450d0920022d000821072002200b20084220868422083e00eb02200241ef026a20084220883c00002002200a3700e302200220063600df02200220022900af013700d702200220022903a8013703d002200220022900e302370398012002200241e8026a29000037009d01200220022901083703880120022002410d6a29000037008d0120022900d702210a20022800d302210f20022f00d102210d20022d00d0022105410421030c0a0b4100210e410021050b200241dc016a20022900f502370000200220022903f0023700d701200220033b01d001200220034110763a00d201200220043600d3012005450d03200241df016a350000210c200241e3016a310000211020022900d701210a200141046a220f280200210520024100360208200141086a2207410020012802002005200241086a41042006100022052005417f461b2205410420054104491b20072802006a2206360200200541034d0d0320022802082109200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a221641002001280200200f280200200241086a41202006100022052005417f461b2205412020054120491b20162802006a22173602002005411f4d0d03200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e80120022802082107200229020c210b200241c6016a20022d00ea013a00002002200b3702bc01200220073602b801200220022f01e8013b01c401200220022900ef013703a8012002200241f4016a2900003700ad0120022800eb012106200220022903a801370378200220022900ad0137007d20022900bf01210b20022800bb01210f200141046a280200211841002105200241003602082016410020012802002018200241086a41042017100022012001417f461b2201410420014104491b20162802006a360200200141034d0d03200e200d7221012004410876210e200c201042208684210c200228020821172002200229007d37009d012002200229037837039801200441ff01712104200741087621160b0c050b4100210f410021050b200241dc016a200229007d370000200220043600d301200220022903783700d701200220033b01d001200220034110763a00d2012005450d002002200241d0016a4107722205290000370380022002200541056a29000037008502200241206a4200370300200241086a41106a4200370300200241086a41086a420037030020024200370308200141086a220941002001280200200141046a220d280200200241086a41202006100022052005417f461b2205412020054120491b20092802006a220e3602002005411f4d0d00200241e8016a41086a2002411c6a290200370300200241e8016a41106a200241246a280200360200200220022902143703e80120022802082105200229020c210a200220022900ef013703b8012002200241f4016a2900003700bd0120022800eb01210620022f01e801211820022d00ea0121192002200a370298022002200536029402200220022903b8013703a801200220022900bd013700ad01200241003a00082001280200200d280200200241086a4101200e1000210520092009280200200541016a41014b22056a22163602002005450d0020022d0008210d200141046a2217280200210520024100360208200141086a220e410020012802002005200241086a41042016100022052005417f461b2205410420054104491b200e2802006a2216360200200541034d0d00200228020821092017280200210520024100360208200e410020012802002005200241086a41042016100022012001417f461b2201410420014104491b200e2802006a360200200141034d0d002007200f72210120022802082117200241dc026a2205200229008502370000200241b0026a41086a20024194026a41086a2802003602002002201820194110747222073b01bc02200241be026a20074110763a0000200220043600d30220022002290380023700d70220022002290294023703b002200220022903a8013703a002200220022900ad013700a502200220033b01d002200220034110763a00d202200220022903a00237039801200220022900a50237009d0120022902d40222104218882005290200220b42288684210a200b421888210c20022802d0022203411876210420022900b702210b20022800b302210f20022f00b102211620022d00b00221072010a7210e410121050c030b2002200229009d0137000d20022002290398013703082000410e3a000020024180036a24000f0b2004450d00200310190b2000410e3a000020024180036a24000f0b2002200229009d0137000d2002200229039801370308200220022903083703d0022002200229000d3700d5022000411d6a200c421886200a42288884370000200041156a200a421886200ead42ffffff078384370000200041083a0000200041346a20063600002000412c6a200b370000200041286a200f360000200041266a20163b0000200041256a20073a0000200041116a2004411874200341ffffff077172360000200041096a2008370000200041056a2001360000200041046a20053a0000200020022f00b0023b0001200041036a200241b2026a2d00003a0000200041386a20022903d0023700002000413d6a20022900d502370000200041cc006a2017360000200041c8006a2009360000200041c5006a200d3a0000200041d0006a2002290308370300200041d8006a200241086a41086a290300370300200041e0006a200241186a290300370300200041e8006a200241086a41186a29030037030020024180036a24000f0b0b2002200229009d0137000d200220022903980137030820022002290388013703e8012002200229008d013700ed01024020034105470d002000410e3a000020024180036a24000f0b2002200229000d3700d501200220022903083703d001200220022903e8013703a002200220022900ed013700a502200041376a20044110763a0000200041356a20043b00002000412c6a20014110763a00002000412a6a20013b00002000410b3a0000200041186a2006360000200041106a200a3700002000410c6a200f3600002000410a6a200d3b0000200041096a20053a0000200041086a20033a0000200041386a20093600002000412d6a2008370000200041296a20073a0000200020022800e801360001200041046a200241eb016a2800003600002000411c6a20022903d001370000200041216a20022900d501370000200041d8006a200c370000200041d0006a200b370000200041c1006a20022900a5023700002000413c6a20022903a002370000200041e0006a2002290308370300200041e8006a200241086a41086a29030037030020024180036a24000f0b2000410e3a000020024180036a24000bbeca0103067f027e037f230041106b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d0000417f6a2203410c4b0d00024002400240024002400240024002400240024020030e0d0008050602090b070d040c0103000b200141046a280200200141086a2802002203470d14200341016a22042003490d5820034101742205200420042005491b22054100480d582003450d29200128020020032005101a2204450d2a0c560b200141046a280200200141086a2802002203470d0c200341016a22042003490d5220034101742205200420042005491b22054100480d522003450d1a200128020020032005101a2204450d1b0c500b200141046a2206280200200141086a22052802002203470d0c200341016a22042003490d5620034101742207200420042007491b22074100480d562003450d1b200128020020032007101a2204450d1c0c4b0b200141046a280200200141086a2802002203470d0c200341016a22042003490d5020034101742205200420042005491b22054100480d502003450d1c200128020020032005101a2204450d1d0c480b200141046a280200200141086a2802002203470d0c200341016a22042003490d4f20034101742205200420042005491b22054100480d4f2003450d1d200128020020032005101a2204450d1e0c450b200141046a280200200141086a2802002203470d0c200341016a22042003490d5320034101742205200420042005491b22054100480d532003450d1e200128020020032005101a2204450d1f0c420b200141046a280200200141086a2802002203470d0c200341016a22042003490d5220034101742205200420042005491b22054100480d522003450d1f200128020020032005101a2204450d200c3f0b200141046a280200200141086a2802002203470d0c200341016a22042003490d5120034101742205200420042005491b22054100480d512003450d20200128020020032005101a2204450d210c3c0b200141046a280200200141086a2802002203470d0d200341016a22042003490d5020034101742205200420042005491b22054100480d502003450d23200128020020032005101a2204450d240c390b200141046a280200200141086a2802002203470d0d200341016a22042003490d4f20034101742205200420042005491b22054100480d4f2003450d24200128020020032005101a2204450d250c360b200141046a280200200141086a2802002203470d0d200341016a22042003490d4e20034101742205200420042005491b22054100480d4e2003450d25200128020020032005101a2204450d260c330b200141046a280200200141086a2802002203470d0d200341016a22042003490d4d20034101742205200420042005491b22054100480d4d2003450d26200128020020032005101a2204450d270c300b200141046a280200200141086a2802002203470d0d200341016a22042003490d4720034101742205200420042005491b22054100480d472003450d27200128020020032005101a2204450d280c2d0b200141046a280200200141086a2802002203470d0d200341016a22042003490d4620034101742205200420042005491b22054100480d462003450d28200128020020032005101a2204450d290c2a0b200128020021040c440b200128020021040c3f0b200128020021040c3c0b200128020021040c390b200128020021040c360b200128020021040c330b200128020021040c300b200128020021040c420b200128020021040c2c0b200128020021040c290b200128020021040c260b200128020021040c230b200128020021040c200b200128020021040c1d0b2005101b22040d350b20054101101c000b2007101b22040d2f0b20074101101c000b2005101b22040d2b0b20054101101c000b2005101b22040d270b20054101101c000b2005101b22040d230b20054101101c000b2005101b22040d1f0b20054101101c000b2005101b22040d1b0b20054101101c000b2005101b22040d2c0b20054101101c000b2005101b22040d150b20054101101c000b2005101b22040d110b20054101101c000b2005101b22040d0d0b20054101101c000b2005101b22040d090b20054101101c000b2005101b22040d050b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41093a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1f20034101742205200420042005491b22044100480d1f2003450d01200128020020032004101a2205450d020c030b200128020021050c030b2004101b22050d010b20044101101c000b20012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41003a0000200041046a280200210320022000410c6a280200220036020c2002410c6a2001105d2000450d162003200041286c6a210a200141046a2105024002400340024002400240024020052802002206200428020022006b41204f0d00200041206a22072000490d2120064101742200200720072000491b22004100480d212006450d01200128020020062000101a22060d020c050b200128020021060c020b2000101b2206450d030b2001200636020020052000360200200428020021000b2004200041206a360200200620006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2903002108024002400240024020052802002206200428020022006b41084f0d00200041086a22072000490d2120064101742200200720072000491b22004100480d212006450d01200128020020062000101a22060d020c060b200128020021060c020b2000101b2206450d040b2001200636020020052000360200200428020021000b2004200041086a360200200620006a2008370000200a200341286a2203470d000c190b0b20004101101c000b20004101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410b3a000002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041086a2d0000417f6a220341034b0d00024020030e0400040203000b200141046a280200200141086a2802002203470d07200341016a22042003490d3520034101742205200420042005491b22054100480d352003450d0f200128020020032005101a2204450d100c1b0b200141046a28020020052802002203470d03200341016a22042003490d3420034101742205200420042005491b22054100480d342003450d08200128020020032005101a2204450d090c180b200141046a280200200141086a2802002203470d03200341016a22042003490d3320034101742205200420042005491b22054100480d332003450d09200128020020032005101a2204450d0a0c150b200141046a280200200141086a2802002203470d03200341016a22042003490d3220034101742205200420042005491b22054100480d322003450d0a200128020020032005101a2204450d0b0c120b200141046a280200200141086a2802002203470d04200341016a22042003490d3120034101742205200420042005491b22054100480d312003450d0d200128020020032005101a2204450d0e0c0f0b200128020021040c150b200128020021040c120b200128020021040c0f0b200128020021040c140b200128020021040c0b0b2005101b22040d0f0b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d2520044101742203200520052003491b22034100480d252004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d2320044101742203200520052003491b22034100480d232004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d2320034101742205200420042005491b22054100480d232003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041296a2d00003a0000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002000410c6a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d2120044101742203200520052003491b22034100480d212004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1f20044101742203200520052003491b22034100480d1f2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1f20044101742203200520052003491b22034100480d1f2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041296a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041d8006a2903002108200041d0006a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1f20044101742203200020002003491b22034100480d1f2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1d20044101742203200520052003491b22034100480d1d2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1d20044101742203200520052003491b22034100480d1d2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041296a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a0000200041056a2104200141046a28020021062005280200210302400240024002400240024002400240024002400240200041046a2d00004101470d0020062003470d01200341016a22052003490d2620034101742206200520052006491b22064100480d262003450d03200128020020032006101a2205450d040c090b20062003470d01200341016a22052003490d2520034101742206200520052006491b22064100480d252003450d04200128020020032006101a2205450d050c060b200128020021050c080b200128020021050c050b2006101b22050d050b20064101101c000b2006101b22050d010b20064101101c000b20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41003a000002400240024002400240200141046a2802002205200628020022036b41204f0d00200341206a22062003490d2220054101742203200620062003491b22034100480d222005450d01200128020020052003101a2205450d020c030b200128020021050c030b2003101b22050d010b20034101101c000b20012005360200200141046a2003360200200141086a28020021030b200141086a2206200341206a360200200520036a220341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041286a280200210502400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22062003490d2220044101742203200620062003491b22034100480d222004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a20053600002000412c6a280200210502400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22062003490d2220044101742203200620062003491b22034100480d222004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041306a280200210002400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22052003490d2220044101742203200520052003491b22034100480d222004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41013a000002400240024002400240200141046a2802002205200628020022036b41204f0d00200341206a22062003490d2020054101742203200620062003491b22034100480d202005450d01200128020020052003101a2205450d020c030b200128020021050c030b2003101b22050d010b20034101101c000b20012005360200200141046a2003360200200141086a28020021030b200141086a2206200341206a360200200520036a220341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041286a280200210502400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22062003490d2020044101742203200620062003491b22034100480d202004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a20053600002000412c6a280200210502400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22062003490d2020044101742203200620062003491b22034100480d202004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041306a280200210002400240024002400240200141046a2802002204200628020022036b41044f0d00200341046a22052003490d2020044101742203200520052003491b22034100480d202004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200141046a28020021042005280200210302400240024002400240024002400240024002400240200041016a2d00004101470d0020042003470d01200341016a22042003490d2420034101742200200420042000491b22004100480d242003450d03200128020020032000101a2204450d040c090b20042003470d01200341016a22042003490d2320034101742200200420042000491b22004100480d232003450d04200128020020032000101a2204450d050c060b200128020021040c080b200128020021040c050b2000101b22040d050b20004101101c000b2000101b22040d010b20004101101c000b20012004360200200141046a2000360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200241106a24000f0b20012004360200200141046a2000360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41063a00000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041046a2d000022034101460d00024020034102460d0020034103470d02200141046a280200200141086a2802002203470d05200341016a22042003490d2e20034101742205200420042005491b22054100480d2e2003450d0b200128020020032005101a2204450d0c0c150b200141046a280200200141086a2802002203470d02200341016a22042003490d2d20034101742205200420042005491b22054100480d2d2003450d06200128020020032005101a2204450d070c120b200141046a28020020052802002203470d02200341016a22042003490d2c20034101742205200420042005491b22054100480d2c2003450d07200128020020032005101a2204450d080c0f0b200141046a280200200141086a2802002203470d03200341016a22042003490d2b20034101742205200420042005491b22054100480d2b2003450d0a200128020020032005101a2204450d0b0c0c0b200128020021040c100b200128020021040c0d0b200128020021040c100b200128020021040c090b2005101b22040d0b0b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d090b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d2220044101742203200520052003491b22034100480d222004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d2220044101742203200520052003491b22034100480d222004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041256a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d2020044101742203200520052003491b22034100480d202004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200041086a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1e20044101742203200520052003491b22034100480d1e2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041086a28020021032002200041106a280200220436020c2002410c6a2001105d0240024002402004450d0020044105742107200141046a210a03400240024002400240200a2802002206200528020022046b41204f0d00200441206a220b2004490d1f20064101742204200b200b2004491b22044100480d1f2006450d01200128020020062004101a22060d020c060b200128020021060c020b2004101b2206450d040b20012006360200200a2004360200200528020021040b2005200441206a360200200620046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200741606a22070d000b0b200041146a280200210320022000411c6a280200220436020c2002410c6a2001105d2004450d1020044105742106200141086a2100200141046a21070340024002400240024020072802002205200028020022046b41204f0d00200441206a220a2004490d1e20054101742204200a200a2004491b22044100480d1e2005450d01200128020020052004101a22050d020c060b200128020021050c020b2004101b2205450d040b2001200536020020072004360200200028020021040b2000200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200641606a22060d000c110b0b20044101101c000b20044101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240024002400240024002400240024002400240024002400240200041086a2d000022034101460d0020034102470d01200141046a280200200141086a2802002203470d03200341016a22042003490d2620034101742205200420042005491b22054100480d262003450d07200128020020032005101a2204450d080c0f0b200141046a28020020052802002203470d01200341016a22042003490d2520034101742205200420042005491b22054100480d252003450d04200128020020032005101a2204450d050c0c0b200141046a280200200141086a2802002203470d02200341016a22042003490d2420034101742205200420042005491b22054100480d242003450d07200128020020032005101a2204450d080c090b200128020021040c0b0b200128020021040c0c0b200128020021040c070b2005101b22040d070b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1e20044101742203200520052003491b22034100480d1e2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a2903002108200041306a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1e20044101742203200020002003491b22034100480d1e2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1c20044101742203200520052003491b22034100480d1c2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1a20044101742203200520052003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1a20044101742203200520052003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041296a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041d8006a2903002108200041d0006a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22052003490d1a20044101742203200520052003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a2203200837000820032009370000200041e8006a2903002108200041e0006a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1a20044101742203200020002003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a000002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041046a2d0000417f6a220341034b0d00024020030e0400040203000b200141046a280200200141086a2802002203470d07200341016a22042003490d2b20034101742205200420042005491b22054100480d2b2003450d0f200128020020032005101a2204450d100c1b0b200141046a28020020052802002203470d03200341016a22042003490d2a20034101742205200420042005491b22054100480d2a2003450d08200128020020032005101a2204450d090c180b200141046a280200200141086a2802002203470d03200341016a22042003490d2920034101742205200420042005491b22054100480d292003450d09200128020020032005101a2204450d0a0c150b200141046a280200200141086a2802002203470d03200341016a22042003490d2820034101742205200420042005491b22054100480d282003450d0a200128020020032005101a2204450d0b0c120b200141046a280200200141086a2802002203470d04200341016a22042003490d2720034101742205200420042005491b22054100480d272003450d0d200128020020032005101a2204450d0e0c0f0b200128020021040c150b200128020021040c120b200128020021040c0f0b200128020021040c140b200128020021040c0b0b2005101b22040d0f0b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1b20044101742203200520052003491b22034100480d1b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1920044101742203200520052003491b22034100480d192004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1920034101742205200420042005491b22054100480d192003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a200041256a2d00003a0000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1720044101742203200520052003491b22034100480d172004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041c8006a280200210602400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a200636000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041256a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041cc006a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1320044101742203200520052003491b22034100480d132004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1320044101742203200520052003491b22034100480d132004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041256a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1320034101742205200420042005491b22054100480d132003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a200041c5006a2d00003a0000200041c8006a280200210602400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1320044101742203200520052003491b22034100480d132004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041cc006a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1320044101742203200520052003491b22034100480d132004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240024002400240024002400240024002400240024002400240024002400240200041086a2d000022034101460d0020034102470d01200141046a280200200141086a2802002203470d03200341016a22042003490d2220034101742205200420042005491b22054100480d222003450d07200128020020032005101a2204450d080c0f0b200141046a28020020052802002203470d01200341016a22042003490d2120034101742205200420042005491b22054100480d212003450d04200128020020032005101a2204450d050c0c0b200141046a280200200141086a2802002203470d02200341016a22042003490d2020034101742205200420042005491b22054100480d202003450d07200128020020032005101a2204450d080c090b200128020021040c0b0b200128020021040c0c0b200128020021040c070b2005101b22040d070b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a2903002108200041106a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1a20044101742203200020002003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1820044101742203200520052003491b22034100480d182004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002000412c6a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1820044101742203200520052003491b22034100480d182004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1620044101742203200520052003491b22034100480d162004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a2903002108200041306a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1620044101742203200020002003491b22034100480d162004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d1420034101742205200420042005491b22054100480d142003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041086a290300210802400240024002400240200141046a2802002204200528020022036b41084f0d00200341086a22002003490d1420044101742203200020002003491b22034100480d142004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200420036a2008370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410a3a000002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041086a2d0000417f6a220341034b0d00024020030e0400040203000b200141046a280200200141086a2802002203470d07200341016a22042003490d2520034101742205200420042005491b22054100480d252003450d0f200128020020032005101a2204450d100c1b0b200141046a28020020052802002203470d03200341016a22042003490d2420034101742205200420042005491b22054100480d242003450d08200128020020032005101a2204450d090c180b200141046a280200200141086a2802002203470d03200341016a22042003490d2320034101742205200420042005491b22054100480d232003450d09200128020020032005101a2204450d0a0c150b200141046a280200200141086a2802002203470d03200341016a22042003490d2220034101742205200420042005491b22054100480d222003450d0a200128020020032005101a2204450d0b0c120b200141046a280200200141086a2802002203470d04200341016a22042003490d2120034101742205200420042005491b22054100480d212003450d0d200128020020032005101a2204450d0e0c0f0b200128020021040c150b200128020021040c120b200128020021040c0f0b200128020021040c140b200128020021040c0b0b2005101b22040d0f0b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d070b20054101101c000b2005101b22040d0b0b20054101101c000b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000412c6a280200210602400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041386a2903002108200041306a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220320083700082003200937000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d1520044101742203200520052003491b22034100480d152004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220341186a290000370000200141106a200341106a290000370000200141086a200341086a29000037000020012003290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041186a2903002108200041106a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1320044101742203200020002003491b22034100480d132004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041186a2903002108200041106a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d1120044101742203200020002003491b22034100480d112004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000410c6a280200210002400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0f20044101742203200520052003491b22034100480d0f2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a2903002108200041106a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d0d20044101742203200020002003491b22034100480d0d2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0b20034101742205200420042005491b22054100480d0b2003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a280200210602400240024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0b20044101742203200520052003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041106a2903002108200041086a290300210902400240024002400240200141046a2802002204200528020022036b41104f0d00200341106a22002003490d0b20044101742203200020002003491b22034100480d0b2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41053a0000024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041086a2d0000417f6a220341054b0d0002400240024002400240024020030e06000402030105000b200628020020052802002203470d09200341016a22042003490d3220034101742207200420042007491b22074100480d322003450d13200128020020032007101a2204450d140c270b200628020020052802002203470d05200341016a22042003490d3120034101742207200420042007491b22074100480d312003450d0c200128020020032007101a2204450d0d0c240b200628020020052802002203470d05200341016a22042003490d3020034101742207200420042007491b22074100480d302003450d0d200128020020032007101a2204450d0e0c210b200628020020052802002203470d05200341016a22042003490d2f20034101742207200420042007491b22074100480d2f2003450d0e200128020020032007101a2204450d0f0c1e0b200628020020052802002203470d06200341016a22042003490d2e20034101742207200420042007491b22074100480d2e2003450d11200128020020032007101a2204450d120c1b0b200628020020052802002203470d06200341016a22042003490d2d20034101742207200420042007491b22074100480d2d2003450d12200128020020032007101a2204450d130c180b200628020020052802002203470d06200341016a22042003490d2c20034101742207200420042007491b22074100480d2c2003450d13200128020020032007101a2204450d140c150b200128020021040c1f0b200128020021040c1c0b200128020021040c190b200128020021040c1e0b200128020021040c150b200128020021040c120b200128020021040c0f0b2007101b22040d170b20074101101c000b2007101b22040d130b20074101101c000b2007101b22040d0f0b20074101101c000b2007101b22040d130b20074101101c000b2007101b22040d090b20074101101c000b2007101b22040d050b20074101101c000b2007101b22040d010b20074101101c000b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41003a00002000410c6a28020021070240024002400240024020062802002204200528020022036b41044f0d00200341046a220a2003490d1a20044101742203200a200a2003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a2007360000200041186a2903002108200041106a29030021090240024002400240024020062802002204200528020022036b41104f0d00200341106a22002003490d1a20044101742203200020002003491b22034100480d1a2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341106a360200200420036a2201200837000820012009370000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41063a00002000410c6a28020021070240024002400240024020062802002204200528020022036b41044f0d00200341046a220a2003490d1820044101742203200a200a2003491b22034100480d182004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a200736000002400240024002400240200628020020052802002203470d00200341016a22042003490d1820034101742206200420042006491b22064100480d182003450d01200128020020032006101a2204450d020c030b200128020021040c030b2006101b22040d010b20064101101c000b20012004360200200141046a2006360200200141086a28020021030b2005200341016a360200200420036a200041096a2d00003a0000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41023a00002000410c6a28020021070240024002400240024020062802002204200528020022036b41044f0d00200341046a220a2003490d1620044101742203200a200a2003491b22034100480d162004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a200736000002400240024002400240024002400240024002400240024002400240024002400240200041096a2d000022034101460d0020034102470d01200628020020052802002203470d03200341016a22042003490d2220034101742200200420042000491b22004100480d222003450d07200128020020032000101a2204450d080c0f0b200628020020052802002203470d01200341016a22042003490d2120034101742200200420042000491b22004100480d212003450d04200128020020032000101a2204450d050c0c0b200628020020052802002203470d02200341016a22042003490d2020034101742200200420042000491b22004100480d202003450d07200128020020032000101a2204450d080c090b200128020021040c0b0b200128020021040c0c0b200128020021040c070b2000101b22040d070b20004101101c000b2000101b22040d070b20004101101c000b2000101b22040d010b20004101101c000b20012004360200200141046a2000360200200141086a28020021030b2005200341016a360200200420036a41003a00000c0c0b20012004360200200141046a2000360200200141086a28020021030b2005200341016a360200200420036a41013a0000200241106a24000f0b20012004360200200141046a2000360200200141086a28020021030b2005200341016a360200200420036a41023a0000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41043a00002000410c6a28020021000240024002400240024020062802002204200528020022036b41044f0d00200341046a22062003490d1420044101742203200620062003491b22034100480d142004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41033a00002000410c6a28020021000240024002400240024020062802002204200528020022036b41044f0d00200341046a22062003490d1220044101742203200620062003491b22034100480d122004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41053a00002000410c6a28020021000240024002400240024020062802002204200528020022036b41044f0d00200341046a22062003490d1020044101742203200620062003491b22034100480d102004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a2000360000200241106a24000f0b20012004360200200141046a2007360200200141086a28020021030b2005200341016a360200200420036a41013a00002000410c6a28020021070240024002400240024020062802002204200528020022036b41044f0d00200341046a220a2003490d0e20044101742203200a200a2003491b22034100480d0e2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b2005200341046a360200200420036a2007360000200041286a2903002108200041206a29030021090240024002400240024020062802002204200528020022036b41104f0d00200341106a22072003490d0e20044101742203200720072003491b22034100480d0e2004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a220b200341106a360200200420036a2203200837000820032009370000200041106a28020021032002200041186a280200220436020c2002410c6a2001105d2004450d0020044105742107200141046a210c0340024002400240024020062802002200200528020022046b41204f0d00200441206a220a2004490d0e20004101742204200a200a2004491b22044100480d0e2000450d01200128020020002004101a22000d020c060b200128020021000c020b2004101b2200450d040b20012000360200200c2004360200200b28020021040b2005200441206a360200200020046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200741606a22070d000b0b200241106a24000f0b20044101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410c3a0000200041026a2104200141046a2802002106200528020021030240024002400240024002400240024002400240024020002d00014101470d0020062003470d01200341016a22002003490d0b20034101742205200020002005491b22054100480d0b2003450d03200128020020032005101a2200450d040c090b20062003470d01200341016a22002003490d0a20034101742205200020002005491b22054100480d0a2003450d04200128020020032005101a2200450d050c060b200128020021000c080b200128020021000c050b2005101b22000d050b20054101101c000b2005101b22000d010b20054101101c000b20012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41003a000002400240024002400240200141046a28020020052802002203470d00200341016a22002003490d0720034101742205200020002005491b22054100480d072003450d01200128020020032005101a2200450d020c030b200128020021000c030b2005101b22000d010b20054101101c000b20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a20042d00003a0000200241106a24000f0b20012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41013a0000024002400240200141046a2802002200200528020022036b41204f0d00200341206a22052003490d0320004101742203200520052003491b22034100480d032000450d01200128020020002003101a2200450d020c040b200128020021000c040b2003101b22000d020b20034101101c000b101d000b20012000360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200020036a220141186a200441186a290000370000200141106a200441106a290000370000200141086a200441086a29000037000020012004290000370000200241106a24000f0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240024002400240200141046a28020020052802002203470d00200341016a22042003490d0520034101742205200420042005491b22054100480d052003450d01200128020020032005101a2204450d020c030b200128020021040c030b2005101b22040d010b20054101101c000b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240024002400240200141046a2802002204200528020022036b41204f0d00200341206a22052003490d0520044101742203200520052003491b22034100480d052004450d01200128020020042003101a2204450d020c030b200128020021040c030b2003101b22040d010b20034101101c000b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041086a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041046a2802002100024002400240200141046a2802002204200528020022036b41044f0d00200341046a22052003490d0320044101742203200520052003491b22034100480d032004450d01200128020020042003101a2204450d020c040b200128020021040c040b2003101b22040d020b20034101101c000b101d000b20012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2000360000200241106a24000b130020004106360204200041e187c0003602000bd40101037f230041306b22002400024002400240419384c000411041d889c200410041001000417f460d002000410036022041012101419384c0004110200041206a41044100100041016a41044d0d0220002802202102419384c000411010020c010b410021010b20002002410020011b36020c200041206a41086a220142003703002000420037032041b980c0004115200041206a1001200041106a41086a200129030037030020002000290320370310200041106a41102000410c6a41041003200041306a24000f0b41fcf9c00041331030000b13002000410b360204200041a0a6c2003602000b02000bbc1508017f017e027f017e047f017e047f017e230041c0016b2201240042002102200141a0016a41086a22034200370300200142003703a001418b82c0004111200141a0016a1001200141e0006a41086a22042003290300370300200120012903a001370360200141e0006a4110100220034200370300200142003703a00141b980c0004115200141a0016a100120042003290300370300200120012903a001370360200141e0006a4110100220034200370300200142003703a00141ce80c0004117200141a0016a100120042003290300370300200120012903a001370360200141e0006a411010022004420037030020014200370360419c82c000410d200141e0006a100120032004290300370300200120012903603703a0010240024002400240024002400240024002400240200141a0016a411041d889c200410041001000417f460d002001420037038001200141a0016a411020014180016a41084100100041016a41084d0d022001290380012105200141e0006a41086a2203420037030020014200370360419c82c000410d200141e0006a1001200141a0016a41086a2003290300370300200120012903603703a001200141a0016a41101002420121020c010b0b200141a0016a41086a22034200370300200142003703a001418487c0004111200141a0016a1001200141e0006a41086a2003290300370300200120012903a00137036002400240200141e0006a411041d889c200410041001000417f460d00200141b8016a4200370300200141a0016a41106a420037030020034200370300200142003703a001200141e0006a4110200141a0016a4120410010002203417f460d032003411f4d0d0320014180016a41186a2206200141a0016a41186a220429030037030020014180016a41106a2207200141a0016a41106a220829030037030020014180016a41086a2209200141a0016a41086a2203290300370300200120012903a0013703800120034200370300200142003703a001418487c0004111200141a0016a1001200141e0006a41086a2003290300370300200120012903a001370360200141e0006a4110100220042006290300370300200820072903003703002003200929030037030020012001290380013703a001200141186a2004290300370300200141106a2008290300370300200141086a2003290300370300200120012903a0013703000c010b200141a0016a41186a20014180016a41186a290300370300200141a0016a41106a20014180016a41106a290300370300200320014180016a41086a29030037030020012001290380013703a001200141186a4200370300200141106a4200370300200141086a4200370300200142003703000b410821064200210a200141a0016a41086a22034200370300200142003703a00141fe81c000410d200141a0016a1001200141e0006a41086a2003290300370300200120012903a0013703600240200141e0006a411041d889c200410041001000417f460d0020014210370284012001200141e0006a36028001200141a0016a20014180016a105c20012802a0012206450d0520012902a401210a200141a0016a41086a22034200370300200142003703a00141fe81c000410d200141a0016a1001200141e0006a41086a2003290300370300200120012903a001370360200141e0006a411010020b200141a0016a41086a22034200370300200142003703a00141a982c0004115200141a0016a1001200141e0006a41086a2003290300370300200120012903a00137036002400240200141e0006a411041d889c200410041001000417f460d00200141b8016a4200370300200141a0016a41106a420037030020034200370300200142003703a001200141e0006a4110200141a0016a4120410010002203417f460d042003411f4d0d0420014180016a41186a2207200141a0016a41186a220429030037030020014180016a41106a2209200141a0016a41106a220829030037030020014180016a41086a220b200141a0016a41086a2203290300370300200120012903a0013703800120034200370300200142003703a00141a982c0004115200141a0016a1001200141e0006a41086a2003290300370300200120012903a001370360200141e0006a4110100220042007290300370300200820092903003703002003200b29030037030020012001290380013703a001200141206a41186a2004290300370300200141206a41106a2008290300370300200141206a41086a2003290300370300200120012903a0013703200c010b200141a0016a41186a20014180016a41186a290300370300200141a0016a41106a20014180016a41106a290300370300200320014180016a41086a29030037030020012001290380013703a001200141206a41186a4200370300200141206a41106a4200370300200141206a41086a4200370300200142003703200b200141e0006a41186a22034200370300200141e0006a41106a22044200370300200141e0006a41086a2208420037030020014200370360200141e0006a1007200141c0006a41186a2003290300370300200141c0006a41106a2004290300370300200141c0006a41086a200829030037030020012001290360370340200141a0016a41186a2207200141186a290300370300200141a0016a41106a2209200141106a290300370300200141a0016a41086a220b200141086a290300370300200120012903003703a00120034200370300200442003703002008420037030020014200370360200141a0016a4120200542002002a71b2202427f7c200141e0006a1008450d0720014180016a41186a220c200329030037030020014180016a41106a220d200429030037030020014180016a41086a220e200829030037030020012001290360370380012003200c2903003703002004200d2903003703002008200e29030037030020012001290380013703602007200329030037030020092004290300370300200b2008290300370300200120012903603703a001024002400240200a4220882205a72203200aa7470d00200341016a22042003490d062005a74101742208200420042008491bad220f42287e2205422088a70d062005a722044100480d062003450d012006200341286c2004101a2206450d020c080b200a210f0c080b2004101b22060d060b20044108101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b101d000b41fcf9c00041331030000b200a4220882205a721030b2006200341286c6a220341003a0000200341196a200141b8016a290300370000200341116a200141b0016a290300370000200341096a200141a8016a290300370000200320012903a001370001200341216a200128008001360000200341246a20014183016a280000360000200f42ffffffff0f8320054220864280808080107c84210a0b2000200129030037001420002002370300200020012903403700342000412c6a200141186a290300370000200041246a200141106a2903003700002000411c6a200141086a2903003700002000413c6a200141c0006a41086a290300370000200041c4006a200141c0006a41106a290300370000200041cc006a200141c0006a41186a290300370000200041ec006a200141206a41186a290300370000200041e4006a200141206a41106a290300370000200041dc006a200141206a41086a290300370000200020012903203700542000410c6a200a37020020002006360208200141c0016a24000b130020004106360204200041bcadc2003602000b130020004109360204200041b88cc0003602000b130020004101360204200041e4b0c2003602000b810603037f017e077f02400240024002400240024002402001280200417e6a220241054b0d000240024002400240024002400240024002400240024002400240024020020e06000402030105000b2001410c6a2802002202417f4c0d11200128020421012002450d092002101b22030d0a20024101101c000b2001410c6a2802002202417f4c0d10200128020421012002450d042002101b22030d0520024101101c000b2001410c6a2802002202417f4c0d0f200128020421012002450d052002101b22030d0620024101101c000b20004105360200200041086a200141086a2903003703000f0b200041033602000f0b2001410c6a2802002204ad42187e2205422088a70d0c2005a72203417f4c0d0c200128020421022003450d062003101b2206450d092004450d070c0a0b410121030b20032001200210950321012000410c6a2002360200200041086a200236020020002001360204200041063602000f0b410121030b20032001200210950321012000410c6a2002360200200041086a200236020020002001360204200041043602000f0b410121030b20032001200210950321012000410c6a2002360200200041086a200236020020002001360204200041023602000f0b4104210620040d030b410021080c030b41d8a5c2001029000b20034104101c000b2002200441186c6a210741002108200621010340200241086a2802002203417f4c0d0220022802002109024002402003450d002003101b220a0d010c050b4101210a0b200a20092003109503210a200241146a2802002209417f4c0d022002410c6a280200210b024002402009450d002009101b220c0d010c060b4101210c0b200c200b2009109503210b200141146a2009360200200141106a20093602002001410c6a200b360200200141086a2003360200200141046a20033602002001200a360200200141186a2101200841016a2108200241186a22022007470d000b0b20002006360204200041073602002000410c6a2008360200200041086a20043602000f0b102b000b20034101101c000b20094101101c000bfe07030f7f017e017f200241086a2103200241046a21042001280200220521060240024002400240024003400240024002400240200428020020032802002207470d00200741016a22082007490d0520074101742209200820082009491b22094100480d052007450d01200228020020072009101a22080d020c060b200228020021080c020b2009101b2208450d040b2002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b200141086a280200210a2001280204220b2107024002402001410c6a280200220c450d00200b21072005450d00200b200c410c6c6a220d41746a210e200241086a210341002107200b210f0340200f210802400340200828020022100d01200741016a2107200d2008410c6a2208470d000c040b0b2008410c6a210f200741016a21112005417f6a2105200841046a290200211203400240024002400240200241046a220428020020032802002206470d00200641016a22092006490d0820064101742201200920092001491b22014100480d082006450d01200228020020062001101a22090d020c0a0b200228020021090c020b2001101b2209450d080b2002200936020020042001360200200328020021060b2003200641016a360200200920066a200741807f72200741ff0071200741077622061b3a00002006210720060d000b2012422088a72213210603400240024002400240200428020020032802002207470d00200741016a22092007490d0820074101742201200920092001491b22014100480d082007450d01200228020020072001101a22090d020c0b0b200228020021090c020b2001101b2209450d090b2002200936020020042001360200200328020021070b2003200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b024002400240024020042802002206200328020022076b20134f0d00200720136a22092007490d0720064101742207200920092007491b22074100480d072006450d01200228020020062007101a22060d020c0b0b200228020021060c020b2007101b2206450d090b2002200636020020042007360200200328020021070b2003200720136a360200200620076a201020131095031a02402012a7450d00201010190b0240200e2008460d002011210720050d010b0b2008410c6a21070b2007200b200c410c6c6a2202460d000340024020072802002206450d00200741046a280200450d00200610190b2007410c6a22072002470d000b0b0240200a450d00200b10190b2000411a3a00000f0b101d000b20094101101c000b20014101101c000b20014101101c000b20074101101c000b900101027f2001280200210402404120101b2205450d002005200429001c370000200541186a200441346a290000370000200541106a2004412c6a290000370000200541086a200441246a29000037000002402001411c6a2204280200450d00200141186a28020010190b20004104360200200442a08080808004370200200141186a20053602000f0b41204101101c000b991006027f017e047f027e027f027e230041e0016b22042400024002400240024002400240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241286a2903002106200241346a2802002107200241c4006a2802002108200241d4006a2802002109200241e4006a280200210a200441286a200128022441206a2903004200200241146a2802002202ad4200109903200128022c220342002003290308220b427f200429032820042903304200521b7d220c200c200b56200c507222031b37030820030d13024002402002450d0020024100480d0a2002101b2203450d0b2003210d4100210e024020024102490d00200341002002417f6a220e109403200e6a210d0b200d41003a0000200e41016a210e0c010b41002102410121034100210e0b024002400240200128022828020820052003200e10092205417e460d0020050d0a2003450d16200441f8006a200e4120200e412049220d1b22056a41004100412020056b2005411f4b1b1094031a200441f8006a200320051095031a200d0d00200441386a41186a200441f8006a41186a290000370300200441386a41106a200441f8006a41106a290000370300200441386a41086a200441f8006a41086a2900003703002004200429007837033802402002450d00200310190b200441186a200141246a28020041206a29030042002008ad42001099032001412c6a280200220242002002290308220b427f200429031820042903204200521b7d220c200c200b56200c507222021b37030820020d162008450d0120084100480d0b2008101b2202450d0e2002210541002103024020084102490d00200241002008417f6a220310940320036a21050b200541003a0000200341016a21030c020b2002450d15200310190c150b4100210841012102410021030b024002400240200128022828020820072002200310092205417e460d0020050d0d2002450d16200442003703c001200442003703b801200441b8016a20022003411020034110491b1095031a2003410f4d0d00200441c0016a290300210f20042903b801211002402008450d00200210190b200441086a200141246a28020041206a2903004200200aad42001099032001412c6a280200220242002002290308220b427f200429030820042903104200521b7d220c200c200b56200c507222021b37030820020d16200a450d01200a4100480d0b200a101b2202450d1041012103200221050240200a4102490d0020024100200a417f6a220310940320036a2105200a21030b200541003a00000c020b2008450d15200210190c150b4100210a41012102410021030b02400240200128022828020820092002200310092205417e460d0020050d0e2002450d15200141206a41003602002001412c6a2802002205290308220b210c02402006500d004101210e2006210c200b2006540d130b2005200b200c7d3703082005290310210b20044198016a41186a200541186a2903003703002004200c3703a0012004200c370398012004200b3703a801200441b8016a20012802002802182010200f20044198016a200441386a2002200310774101210e20042d00b8014101470d01200441d8006a41086a200441f8006a41086a290300370300200441d8006a41106a200441f8006a41106a290300370300200441d8006a41186a200441f8006a41186a290300370300200541086a220320044198016a41086a29030020032903007c37030020042004290378370358200a0d130c140b200a450d14200210190c140b200441f8006a41186a2203200441d1016a290000370300200441f8006a41106a220e200441c9016a290000370300200441f8006a41086a2208200441c1016a290000370300200420042900b901370378200441d8006a41086a22072008290300370300200441d8006a41106a2208200e290300370300200441d8006a41186a220e2003290300370300200541086a220320044198016a41086a29030020032903007c37030020042004290378370358200441b8016a41186a200e290300370300200441b8016a41106a2008290300370300200441b8016a41086a2007290300370300200420042903583703b8010240024002402001411c6a2802002205200141206a28020022036b41204f0d00200341206a220e2003490d0b20054101742203200e200e2003491b22034100480d0b2005450d01200141186a28020020052003101a2205450d020c110b200141186a28020021050c110b2003101b22050d0f0b20034101101c000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41ccd6c3001029000b101d000b20024101101c000b41ccd6c3001029000b20084101101c000b41ccd6c3001029000b200a4101101c000b2001411c6a2003360200200141186a2005360200200141206a28020021030b200141206a200341206a360200200520036a220341186a200441b8016a41186a290300370000200341106a200441b8016a41106a290300370000200341086a200441b8016a41086a290300370000200320042903b8013700004100210e0b200a450d010b200210190b200041003602002000200e360204200441e0016a24000f0b20004105360200200441e0016a24000bbc2203027f027e077f230041d00b6b22082400024020012802182001280234220928029001470d00200041013a0000200041086a4124360200200041046a41d8cdc100360200200841d00b6a24000f0b200442002004290308220a20094188016a2903007d220b200b200a56200b507222091b37030802402009450d00200041013a0000200041086a412a360200200041046a41fccdc100360200200841d00b6a24000f0b200841d8026a41186a22094200370300200841d8026a41106a220c4200370300200841d8026a41086a220d4200370300200842003703d80220062007200841d8026a1005200841c0006a41186a2009290300370300200841c0006a41106a200c290300370300200841c0006a41086a200d290300370300200820082903d8023703400240024002400240024002404120101b2209450d0020092005290000370000200941186a200541186a290000370000200941106a200541106a290000370000200941086a200541086a2900003700002009412041c000101a2209450d0120092008290340370020200941386a200841c0006a41186a290300370000200941306a200841c0006a41106a290300370000200941286a200841c0006a41086a290300370000200941c000418001101a2209450d022009200141c0006a220e290000370040200941d8006a200e41186a290000370000200941d0006a200e41106a290000370000200941c8006a200e41086a290000370000200841d8026a41186a220c4200370300200841d8026a41106a220d4200370300200841d8026a41086a220f4200370300200842003703d802200941e000200841d8026a1005200841086a41186a200c290300370300200841086a41106a200d290300370300200841086a41086a200f290300370300200820082903d80237030820091019200841d8026a2001200841086a10c902024020082d00d8024101470d00200041013a0000200041086a4117360200200041046a41a6cec100360200200841d00b6a24000f0b2008413c6a419cc1c300360200200841286a41086a2209420037030020082001360238200841a0c0c10036022c2008410036022820084188026a41186a200541186a29000037030020084188026a41106a200541106a29000037030020084188026a41086a200541086a2900003703002008200529000037038802417f210c2008417f360228200841c0006a41186a200841086a41186a290300370300200841c0006a41106a200841086a41106a290300370300200841c0006a41086a200841086a41086a29030037030020082008290308370340418009101b220f450d03200841286a4104722110200f41003b0106200f4100360200200f41086a200841d8026a41f8081095031a200941003602002008200f36022c200f2f010622114105742112410021090240024002400240034020122009460d01200841c0006a200f20096a41086a4120109703220d450d03200c41016a210c200941206a2109200d41004e0d000c020b0b2011210c0b200841a8026a41186a200841c0006a41186a290300370300200841a8026a41106a200841c0006a41106a290300370300200841a8026a41086a200841c0006a41086a290300370300200820082903403703a802200841346a21094100450d010c060b200c41016a210c200841346a210941010d050b200841c0006a411c6a200841a8026a41086a290300370200200841e4006a200841a8026a41106a290300370200200841ec006a200841a8026a41186a290300370200200820093602502008200c36024c200820103602482008200f36024420084100360240200820082903a802370254200841d8026a411c6a4200370200200841d8026a41106a200841c8026a41086a290300370300200841fd026a20082900a00137000020084185036a200841a0016a41086a2900003700002008418d036a200841a0016a41106a29000037000020084195036a200841a0016a41186a2900003700002008419c036a200841bf016a280000360000200842003703d802200841023a00fc02200841a0c0c1003602f002200820082903c8023703e002200841c0006a200841d8026a10860121090c050b41204101101c000b41c0004101101c000b4180014101101c000b4180094108101c000b200841f0026a4200370300200841ec026a41a0c0c100360200200841003602f802200841003602e802200842003703e002200841a0c0c1003602dc02200841003602d802200f200c41c8006c6a41e8026a2109200841d8026a1084010b200941013a0024200941256a2008290388023700002009412d6a20084188026a41086a290300370000200941356a20084188026a41106a2903003700002009413d6a20084188026a41186a2903003700002008200828022841016a360228200841c0006a41106a200841286a41106a290300370300200841c0006a41086a200841286a41086a29030037030020084188016a200841086a41086a29030037030020084190016a200841086a41106a29030037030020084198016a200841086a41186a290300370300200820082903283703402008200829030837038001200141186a2802002109200141346a290200210b200128023c210c200841ec006a4200370200200841e4006a428080808080013702002008200c36027c2008200b3702742008420837025c2008200941016a360258200820044101200e200841086a20022003200841c0006a10ca020240024020082802002209450d0020082802042101200041013a0000200041086a2001360200200041046a20093602000c010b200841d8026a20052001413c6a28020028020010cb02024020082802d8024101470d00200041046a20082902dc02370200200041013a00000c010b200841a8026a41186a2209200841f4026a280200360200200841a8026a41106a220c200841ec026a290200370300200841a8026a41086a220d200841e4026a290200370300200820082902dc023703a802200841a0016a41106a200d290300370300200841a0016a41186a200c290300370300200841c0016a2009280200360200200841063602a401200841e7d7c1003602a001200820082903a8023703a801200141386a280200210c200841d8016a41186a200141d8006a290000370300200841d8016a41106a200141d0006a290000370300200841d8016a41086a200141c8006a290000370300200820012900403703d801200841c8026a41086a22094200370300200842003703c802419399c100410d200841c8026a1001200841f8016a41086a220d2009290300370300200820082903c8023703f8014200210b02400240024002400240200841f8016a411041d889c200410041001000417f460d00200842003703a802200841f8016a4110200841a8026a41084100100041016a41084d0d0120082903a802210b0b20094200370300200842003703c802418b82c0004111200841c8026a1001200d2009290300370300200820082903c8023703f80102400240200841f8016a411041d889c200410041001000417f460d00200841c0026a4200370300200841a8026a41106a4200370300200841b0026a4200370300200842003703a802200841f8016a4110200841a8026a4120410010002209417f460d032009411f4d0d0320084188026a41186a200841a8026a41186a29030037030020084188026a41106a200841a8026a41106a29030037030020084188026a41086a200841a8026a41086a290300370300200820082903a802370388020c010b200841a0026a420037030020084198026a420037030020084190026a420037030020084200370388020b200841fc026a200841d8016a41086a29030037020020084184036a200841d8016a41106a2903003702002008418c036a200841d8016a41186a2903003702002008419c036a20084188026a41086a290300370200200841a4036a20084188026a41106a290300370200200841ac036a20084188026a41186a290300370200200820023703d802200820082903d8013702f4022008200b3703e802200820082903880237029403200820033703e0022008200841c0006a3602f002200841003602b002200842013703a802200841c8016a200c200841a0016a200841d8026a20062007200841a8026a200410cc020240024020082802c80122094101460d0020094102470d01200041046a20082902cc01370200200041013a0000200841b8016a280200450d06200841b4016a28020010190c060b200841c8016a41086a280200450d0020082802cc0110190b200841d8026a41186a200e41186a290000370300200841d8026a41106a200e41106a290000370300200841d8026a41086a200e41086a290000370300200841a8026a41086a200841086a41086a290300370300200841a8026a41106a200841086a41106a290300370300200841a8026a41186a200841086a41186a2903003703002008200e2900003703d802200820082903083703a8020240024002400240200841e4006a2802002209200841e0006a280200470d00200941016a220c2009490d062009410174220d200c200c200d491b220dad42d8007e220b422088a70d06200ba722054100480d062009450d01200841dc006a280200200941d8006c2005101a220c0d020c070b200841dc006a280200210c0c020b2005101b220c450d050b200841e0006a200d360200200841dc006a200c360200200841e4006a28020021090b200c200941d8006c6a220920082903d802370001200941013a0000200920082903a8023700212009200829008802370041200941096a200841d8026a41086a220d290300370000200941116a200841d8026a41106a290300370000200941196a200841d8026a41186a290300370000200941296a200841a8026a41086a2205290300370000200941316a200841a8026a41106a290300370000200941396a200841a8026a41186a290300370000200941d0006a20084197026a290000370000200941c9006a20084188026a41086a290000370000200841e4006a2209200928020041016a2204360200200d200841c0006a41086a220f2903003703002005200841e4026a280200360200200820082903403703d802200820082902dc023703a802200841f0006a2802002112200841ec006a2802002106200841c0006a41286a2802002109200841e0006a2802002107200841c0006a411c6a280200210c0240200841a0016a41186a280200450d00200841b4016a28020010190b200f2005280200360200200820082903a802370340200d200f280200360200200820082903403703d8022001200841d8026a10cd022008200c200441d8006c6a3602e4022008200c3602e002200820073602dc022008200c3602d8022001411c6a200841d8026a10da0120082009201241f8006c6a3602e402200820093602e002200820063602dc02200820093602d802200141286a200841d8026a10db01200041003a0000200041196a200841086a41186a290300370000200041116a200841086a41106a290300370000200041096a200841086a41086a29030037000020002008290308370001200841d00b6a24000f0b41fcf9c00041331030000b41fcf9c00041331030000b101d000b20054108101c000b200841cc006a280200210d2008280244210902400240200841c8006a2802002200450d002000210c2009210103402001280280092101200c417f6a220c0d000b0340200920092f01064102746a4180096a28020021092000417f6a22000d000c020b0b200921010b200841d8026a411c6a20092f0106360200200841f0026a4100360200200841ec026a20093602002008200d3602f802200841003602e802200842003703e002200820013602dc02200841003602d802200841d8026a10ad020240200841e0006a280200450d00200841c0006a411c6a28020010190b0240200841f0006a2802002209450d00200941f8006c2101200841e8006a28020041206a2109034020091043200941f8006a2109200141887f6a22010d000b0b0240200841ec006a280200450d00200841e8006a28020010190b200841d00b6a24000bd60403027f027e057f230041106b22042400024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d01200228020421052004200128022441186a2903004200200241146a2802002202ad4200109903200128022c2203420020032903082206427f200429030020042903084200521b7d220720072006562007507222031b37030820030d09200128020c21032001410036020c2003450d02200141106a29020022074280808080105a0d03024002400240024020022007422088a722084d0d002007a7220920086b200220086b220a4f0d012008200a6a220b2008490d082009410174220c200b200b200c491b220b4100480d082009450d0220032009200b101a2203450d030c090b2002200820022008491b21020c0b0b2003200822096a210b200a4102490d090c080b200b101b22030d060b200b4101101c000b41a88ec00041f4031030000b41a88ec00041f4031030000b419c92c00041fd001030000b41b8b4c3001029000b101d000b20074220882106200bad210720032006a722096a210b200a4102490d010b200b410020022008417f7322086a1094031a2003200920026a20086a22096a210b0b200b41003a0000200941016a21020b0240200128022828020820052003200210092208417e460d0020080d022007a72108024020012802302205450d00200141346a280200450d00200510190b200141386a2002360200200141346a2008360200200141306a20033602000c010b2007a7450d00200310190b20004105360200200441106a24000f0b41ccd6c3001029000b960101027f2001280200280218210402404120101b2205450d0020052004290040370000200541186a200441d8006a290000370000200541106a200441d0006a290000370000200541086a200441c8006a29000037000002402001411c6a2204280200450d00200141186a28020010190b20004104360200200442a08080808004370200200141186a20053602000f0b41204101101c000ba203020b7f027e230041106b22042400024002402001280200280218220528020022064100480d00200641ffffffff07460d00200541c0006a21072005200641016a2208360200200541046a2106200541086a28020021090240024003402006280200220b41086a210c200b2f0106220a41057421064100210d0240024003402006450d012007200c4120109703220e450d02200641606a2106200d41016a210d200c41206a210c200e417f4a0d000b200d417f6a210a0b2009450d022009417f6a2109200b200a4102746a4180096a21060c010b0b200b41e8026a200d41c8006c6a2206450d002006280200450d00200641106a290300210f200641086a29030021100c010b200420052802102007200541146a280200280214110200200441086a290300210f20052802002108200429030021100b20052008417f6a3602004110101b2206450d01200620103700002006200f37000802402001411c6a220c280200450d00200141186a28020010190b20004104360200200c42908080808002370200200141186a2006360200200441106a24000f0b107b000b41104101101c000b7701017f230041c0006b220024002000411836020c200041a2dcc100360208200041346a4106360200200041246a41023602002000410336022c20004202370214200041d4d8c3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41e4d8c30010f201000b6202017e027f200128022c290308210402404108101b2205450d002005200437000002402001411c6a2206280200450d00200141186a28020010190b20004104360200200642888080808001370200200141186a20053602000f0b41084101101c000b7703017f027e017f200128022c220441186a29030021052004290310210602404110101b2204450d00200420063700002004200537000802402001411c6a2207280200450d00200141186a28020010190b20004104360200200742908080808002370200200141186a20043602000f0b41104101101c000ba80202057f027e230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200141086a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128020421082004200128022441286a29030042002005ad4200109903200128022c2202420020022903082209427f200429030020042903084200521b7d220a200a200956200a507222021b37030820020d0020012802282802082007200820066a2005100a2202417e460d0020020d04410421030b20002003360200200441106a24000f0b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41e4d6c3001029000b1600200041003602002000200141086a2802003602040bd00303017f027e017f230041c0006b220424000240024002402003450d0020022802000d00200228020421032004200128022441206a290300420042204200109903200128022c2202420020022903082205427f200429030020042903084200521b7d220620062005562006507222021b37030802400240024020020d004120101b2202450d0420024200370000200241176a4200370000200241106a4200370000200241086a42003700002002411f6a41003a00000240200128022828020820032002412010092203417e460d0020030d062002450d01200441106a20012802002802182203200341c0006a200241201081012004280210450d02200441206a41086a200441106a41086a220328020036020020042004290310370320200441306a41086a2207200328020036020020042004290310370330200141186a210302402001411c6a280200450d00200328020010190b20032004290330370200200341086a2007280200360200410021010c030b200210190b20004105360200200441c0006a24000f0b200141206a4100360200410121010b200210192000410036020020002001360204200441c0006a24000f0b41a88ec00041f4031030000b41204101101c000b41ccd6c3001029000b8e0501137f02400240200128020022054100480d00200541ffffffff07460d002001200541016a360200200141046a2106200141086a28020021070c010b107b000b410021050340024002400240024002400240024002400240024020050e020001010b2006280200220941086a210a20092f0106220841057421054100210b0240024003402005450d012002200a4120109703220c450d02200541606a2105200b41016a210b200a41206a210a200c417f4a0d000b200b417f6a21080b2007450d022007417f6a2107200920084102746a4180096a2106410021050c0a0b200941e8026a200b41c8006c6a2205450d01200541186a210d2005411c6a280200210e4108210f410c2110417f21114102211241900221134101211441742115410021160c080b200d2802002208200f6a210520082f0106221720106c210a4100210b0240024002400340200b210c200a450d01024002400240200320052802002005280208220b2004200b2004491b109703220d450d0041012109200d20164e0d010c020b200b2004460d0520112014200b20044b1b21090b200520106a2105200c20146a210b200a20156a210a20092011470d010b0b200e0d010c030b2017210c200e450d020b200e20116a210e2008200c2012746a20136a210d410121050c090b2008418c016a220a200c410c6c6a2205450d0020052802002204450d01200a200c410c6c6a2802082205417f4c0d062005450d022005101b220a0d0320054101101c000b20002001280210200220032004200141146a28020028020c1103000c040b4100210a0c020b4101210a0b200a200420051095031a0b200020053602042000200a360200200041086a20053602000b20012001280200417f6a3602000f0b102b000b410121050c000b0b930101027f2001280200210402404120101b2205450d002005200429003c370000200541186a200441d4006a290000370000200541106a200441cc006a290000370000200541086a200441c4006a29000037000002402001411c6a2204280200450d00200141186a28020010190b20004104360200200442a08080808004370200200141186a20053602000f0b41204101101c000bbf0d05057f027e017f017e047f230041b00a6b220424000240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241146a2802002106200241246a2802002107200241346a2802002108200441186a200128022441206a290300420042204200109903200128022c2202420020022903082209427f200429031820042903204200521b7d220a200a200956200a507222031b3703084105210220030d0e4120101b220b450d04200b4200370000200b41176a4200370000200b41106a4200370000200b41086a4200370000200b411f6a41003a0000024020012802282802082005200b412010092203417e460d0020030d06200b450d0f024002400240024002402006450d00200441086a200141246a28020041206a29030042002008ad220c42001099032001412c6a2802002203420020032903082209427f200429030820042903104200521b7d220a200a200956200a507222031b37030820030d052008450d0120084100480d0f2008101b220d450d1041012103200d2105024020084102490d00200d41002008417f6a220310940320036a2105200821030b200541003a00000c020b4100210d0c020b410021034101210d4200210c0b20012802282802082007200d200310092205417e460d0120050d0b200d450d02200c2003ad42208684210a0b200128020028021821064120101b220e450d08200e200b290000370000200e41186a200b41186a290000370000200e41106a200b41106a290000370000200e41086a200b41086a29000037000020062802000d092006417f360200200441f8096a41186a200641d8006a290000370300200441f8096a41106a200641d0006a290000370300200441f8096a41086a200641c8006a290000370300200420062900403703f809024002402006280204220541a0c0c100460d00200641086a28020021070c010b418009101b2205450d0e41002107200541003b010620054100360200200541086a20044180016a41f8081095031a200641086a4100360200200641046a20053602000b200641046a210f02400240034020052f01062210410574210841002102410021030240034020082002460d01200441f8096a200520026a41086a41201097032201450d03200241206a2102200341016a21032001417f4a0d000b2003417f6a21100b02402007450d002007417f6a2107200520104102746a4180096a28020021050c010b0b200441286a41186a200441f8096a41186a290300370300200441286a41106a200441f8096a41106a290300370300200441286a41086a200441f8096a41086a290300370300200420042903f8093703282006410c6a2102410021072010210341000d010c100b2006410c6a21024101450d0f0b20044198016a420037030020044194016a41a0c0c100360200200441003602a00120044100360290012004420037038801200441a0c0c1003602840120044100360280012005200341c8006c6a41e8026a210220044180016a1084010c0f0b200c500d00200d10190b200b10190c0e0b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41204101101c000b41ccd6c3001029000b41204101101c000b108501000b41ccd6c3001029000b101d000b20084101101c000b4180094108101c000b200441f8096a411c6a200441286a41086a2903003702002004419c0a6a200441286a41106a290300370200200441a40a6a200441286a41186a290300370200200420023602880a200420033602840a2004200f3602800a200420053602fc09200420073602f8092004200429032837028c0a20044180016a411c6a420037020020044180016a41106a200441f0006a41086a290300370300200441a5016a2004290048370000200441ad016a200441c8006a41086a290000370000200441b5016a200441c8006a41106a290000370000200441bd016a200441c8006a41186a290000370000200441c4016a200441e7006a2800003600002004420037038001200441023a00a401200441a0c0c100360298012004200429037037038801200441f8096a20044180016a10860121020b200442a0808080800437024c2004200e3602482004200a3702fc092004200d3602f80920044180016a200241186a200441c8006a200441f8096a1087010240200428028001450d002004280284012202450d0020044188016a280200450d00200210190b2006200628020041016a360200200b1019410421020b20002002360200200441b00a6a24000bd80101067f230041206b22012400200141086a200010ac02024020012802082202450d00200141186a2103200141146a2104034020032802002105200428020021060240200128020c450d00200210190b02402006450d002005450d00200610190b200141086a200010ac02200128020822020d000b0b02402000280204220641a0c0c100460d0020062802002102200610192002450d0020022802002105200210192005450d00024020052802002206450d000340200510192006210520062802002202210620020d000b0b200510190b200141206a24000b7701017f230041c0006b220024002000411036020c20004192dcc100360208200041346a4107360200200041246a41023602002000410336022c20004202370214200041d4d8c3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41e4d8c30010f201000bd31801187f230041d00c6b2202240020002802102203200328020041016a360200200028020c21042000280208210520002802042103200241186a41186a22062000412c6a290000370300200241186a41106a2207200041246a290000370300200241186a41086a22082000411c6a29000037030020022000290014370318200241e8016a200141c8001095031a024020032f01062201410b4f0d00200320044105746a220041286a200041086a2209200120046b4105741096031a200041206a2006290300370000200041186a2007290300370000200041106a2008290300370000200920022903183700002003200441c8006c6a220041b0036a200041e8026a2200200341066a22032f010020046b41c8006c1096031a2000200241e8016a41c8001095032100200320032f010041016a3b0100200241d00c6a240020000f0b024002400240418009101b220a450d00200a41003b0106200a4100360200200a41086a200241a8036a41f80810950321012002200341ca016a2d00003a00da02200220032f00c8013b01d802200220032900db013703c8022002200341e0016a2900003700cd02200341cb016a280000210b200341cf016a280000210c200341d3016a280000210d200341d7016a280000210e200241a8036a20034198066a41c8001095031a2001200341e8016a200341066a22062f010041796a22004105741095032101200a41e8026a200341e0066a200041c8006c1095032107200641063b0100200a20003b0106200220022d00da023a00c602200220022f01d8023b01c402200220022903c8023703b002200220022900cd023700b502200241e0026a200241a8036a41c8001095031a02400240200441064b0d00200341086a20044105746a220141206a2001200341066a22002f010020046b4105741096031a200141186a200241186a41186a290300370000200141106a200241186a41106a290300370000200141086a200241186a41086a29030037000020012002290318370000200341e8026a200441c8006c6a220f41c8006a200f20002f010020046b41c8006c1096031a200f200241e8016a41c8001095031a0c010b200120044105746a41c07e6a2001200441796a22064105746a2201200041ffff037120066b4105741096031a200141186a200241186a41186a290300370000200141106a200241186a41106a290300370000200141086a200241186a41086a290300370000200120022903183700002007200441c8006c6a220041d07c6a200041887c6a220f200a41066a22002f010020066b41c8006c1096031a200f200241e8016a41c8001095031a0b200241d0016a41026a220420022d00c6023a0000200020002f010041016a3b0100200220022f01c4023b01d001200220022903b002370360200220022900b502370065200241f0006a200241e0026a41c8001095031a200241146a41026a221020042d00003a0000200220022f01d0013b01142002200229036037030020022002290065370005200241186a200241f0006a41c8001095031a02400240024020032802002207450d0020032f010421110340200241e4016a41026a221620102d00003a0000200220022f01143b01e401200220022903003703d001200220022900053700d501200241e8016a200241186a41c8001095031a201141ffff0371210620072f01062203410a4d0d0241b009101b2201450d03200141003b010620014100360200200141086a200241a8036a41a80910950321002002200741ca016a2d00003a00da02200220072f00c8013b01d802200220072900db013703c8022002200741e0016a2900003700cd02200741cb016a2800002112200741cf016a2800002115200741d3016a2800002114200741d7016a2800002113200241a8036a20074198066a41c8001095031a2000200741e8016a200741066a22092f0100220441796a22034105741095032117200141e8026a200741e0066a200341c8006c109503211820014180096a2007419c096a2004417a6a22084102741095032119200941063b0100200120033b010602402008450d00410021032019210003402000280200220420033b010420042001360200200041046a21002008200341016a2203470d000b0b200241e0026a200241a8036a41c8001095031a200220022d00da023a00c602200220022f01d8023b01c402200220022903c8023703b002200220022900cd023700b502200241dc026a41026a220820022d00c6023a0000200220022f01c4023b01dc02200220022903b002370360200220022900b502370065200241a8036a200241e0026a41c8001095031a02400240201141ffff0371220041064b0d00200741086a2203200641016a22044105746a200320064105746a220320092f0100221120066b22194105741096031a2003200e36000f2003200d36000b2003200c3600072003200b360003200341026a20162d00003a0000200320022f01e4013b0000200320022903d001370013200341186a20022900d501370000200741e8026a200641c8006c6a220341c8006a2003201941c8006c1096031a2003200241e8016a41c8001095031a2009201141016a22033b010020074180096a2211200641027422196a41086a201120044102746a2211200341ffff037120046b4102741096031a2011200a360200200020092f010022044f0d01200720196a4184096a2103034020032802002200200641016a22063b010420002007360200200341046a210320042006470d000c020b0b20172006417a6a22044105746a2017200641796a22034105746a2200200141066a22092f010020036b4105741096031a200041186a20022900d5013700002000200e36000f2000200d36000b2000200c3600072000200b360003200041026a20162d00003a0000200020022f01e4013b0000200020022903d0013700132018200641c8006c6a220041d07c6a200041887c6a220020092f010020036b41c8006c1096031a2000200241e8016a41c8001095031a200920092f010041016a22003b01002019200641027422116a416c6a201920044102746a2209200041ffff0371220620046b4102741096031a2009200a360200200420064b0d00200120116a41e8086a2100034020002802002204200341016a22033b010420042001360200200041046a210020062003470d000b0b200241cc016a41026a220320082d00003a0000200220022f01dc023b01cc01200220022903603703b801200220022900653700bd01200241f0006a200241a8036a41c8001095031a201020032d00003a0000200220022f01cc013b0114200220022903b801370300200220022900bd01370005200241186a200241f0006a41c8001095031a024020072802002203450d0020072f010421112012210b2013210e2014210d2015210c200321072001210a0c010b0b2012210b2013210e2014210d2015210c2001210a0b41b009101b2203450d03200341003b010620034100360200200341086a200241a8036a41a809109503210120032005280200220036028009200520033602002005200528020441016a360204200041003b010420002003360200200120032f010622044105746a220020022f01143b00002000200e36000f2000200d36000b2000200c3600072000200b36000320002002290300370013200041026a200241146a41026a2d00003a0000200041186a20022900053700002003200441c8006c6a41e8026a200241186a41c8001095031a20034180096a200441016a22004102746a200a360200200320003b0106200a20003b0104200a20033602000c040b200741086a2200200641016a22044105746a200020064105746a2200200320066b22014105741096031a2000200e36000f2000200d36000b2000200c3600072000200b360003200041026a200241e4016a41026a2d00003a0000200020022f01e4013b0000200020022903d001370013200041186a20022900d5013700002007200641c8006c6a220041b0036a200041e8026a2200200141c8006c1096031a2000200241e8016a41c8001095031a200741066a2200200341016a22033b010020074180096a220120064102746a41086a200120044102746a2201200341ffff037120046b4102741096031a2001200a360200201141ffff037120002f010022034f0d03200a20043b0104200a200736020020042003460d032003417f6a210120072004417f6a22034102746a4188096a2100034020002802002204200341026a3b010420042007360200200041046a21002001200341016a2203470d000c040b0b41b0094108101c000b4180094108101c000b41b0094108101c000b200241d00c6a2400200f0bc916050f7f017e207f017e057f230041a0036b2204240020022802082105200228020421062002280200210702400240024002402001280200220841a0c0c100460d00200128020421090c010b419002101b2208450d0141002109200841003b010620084100360200200841086a200441e8006a4188021095031a20014100360204200120083602000b0c010b4190024104101c000b41002102024003400240024002400240024002400240024020020e020001010b200841086a210220082f0106220b410c6c210c4100210d4100210e024002400240024002400340200e210a200c200d460d01024002400240200720022802002002280208220e20052005200e4b1b109703220f450d0041012110200f41004e0d010c020b2005200e460d06417f41012005200e491b21100b2002410c6a2102200a41016a210e200d410c6a210d2010417f470d010b0b20090d010c020b200b210a2009450d010b2009417f6a21092008200a4102746a4190026a2802002108410021020c0a0b200441186a20083602002001200128020841016a3602082004411c6a200aad4220862001ad843702002004200636020c2004200736020820042005ad370310200441c8006a41086a220e200341086a2802003602002004200329020037034820082f01062202410b4f0d01200841086a220d200a410c6c2211410c6a22126a200d20116a220d2002200a6b410c6c220a1096031a200d2005360208200d2006360204200d20073602002008418c016a220d20126a200d20116a220d200a1096031a200d41086a200e280200360200200d2004290348370200200841066a200241016a3b01000c0a0b02402006450d00200710190b200441e8006a41086a2202200341086a280200220e36020020042003290200221337036820022008200d6a220d4194016a22112802003602002004200d418c016a220d290200370368200d20133702002011200e360200200441086a41086a220d200228020036020020042004290368370308200041013602002000410c6a200d28020036020020002004290308370204200441a0036a24000f0b419002101b2214450d04201441003b010620144100360200201441086a200441e8006a418802109503210d200441e8006a41086a220e200841dc016a280200360200200420082902d4013703682008290254211320082802502115200d200841dc006a200841066a22112f010041796a2202410c6c2212109503210d2014418c016a200841e0016a20121095032112201141063b0100201420023b0106200441d8006a41086a200e2802003602002004200429036837035802400240200a41064b0d00200841086a2202200a410c6c2211410c6a22126a200220116a2202200841066a220d2f0100220e200a6b410c6c220a1096031a2002200536020820022006360204200220073602002008418c016a220220126a200220116a2202200a1096031a200241086a200441c8006a41086a280200360200200220042903483702000c010b200d200a410c6c220e41b87f6a22116a200d200e41ac7f6a220e6a220d200241ffff0371200a41796a220a6b410c6c1096031a200d2005360208200d2006360204200d2007360200201220116a2012200e6a2202201441066a220d2f0100220e200a6b410c6c1096031a200241086a200441c8006a41086a280200360200200220042903483702000b41012111200d200e41016a3b010041082116200441386a41086a2217200441d8006a41086a221828020036020020042004290358370338200441286a41086a22192017280200360200200420042903383703282008280200221a450d0120082f0104211b41ffff03211c410a211d41c002211e4100211f41b802212041d400212141d000212241dc01212341d401212441dc0021254106212641792127410c212841e0012129418c01212a41ac02212b419002212c417a212d4102212e419402212f4104211241ac7f213041b87f2131416c213241f80121330c060b200441c8006a20166a2236201928020036020020042004290328370348201b201c712110201a2f01062202201d4d0d01201e101b220a450d02200a201f3b0106200a201f360200200a20166a200441e8006a20201095032102201a20216a2902002134201a20226a2802002135200441e8006a20166a220c201a20236a2802003602002004201a20246a2902003703682002201a20256a201a20266a220b2f0100220d20276a220e20286c220f1095032137200a202a6a201a20296a200f1095032138200a202c6a201a202b6a200d202d6a220f202e741095032139200b20263b0100200a200e3b01060240200f450d00410021022039210d0340200d280200220e20023b0104200e200a360200200d20126a210d200f200220116a2202470d000b0b2018200c28020036020020042004290368370358200c20182802003602002004200429035837036802400240201b201c71220220264b0d00201a20166a220e201020286c220d20286a220f6a200e200d6a220e200b2f0100221b20106b20286c22391096031a200e2013370204200e2015360200201a202a6a220e200f6a200e200d6a220d20391096031a200d20166a2036280200360200200d2004290348370200200b201b20116a220d3b0100201a202c6a220e2010202e74220b6a20166a200e201020116a220f202e746a221b200d201c71220e200f6b202e741096031a201b20143602002002200e4f0d01201a200b6a202f6a210203402002280200220d201020116a22103b0104200d201a360200200220126a2102200e2010470d000c020b0b2037201020286c220220316a220f6a2037200220306a221b6a220d200a20266a220e2f0100201020276a22026b20286c1096031a200d2013370204200d20153602002038200f6a2038201b6a220d200e2f0100220f20026b20286c1096031a200d20166a2036280200360200200d2004290348370200200e200f20116a220f3b010020392010202e74221b6a20326a20392010202d6a220d202e746a220e200f201c712210200d6b202e741096031a200e2014360200200d20104b0d00200a201b6a20336a210d0340200d280200220e200220116a22023b0104200e200a360200200d20126a210d20102002470d000b0b2017200c2802003602002004200429036837033820192017280200360200200420042903383703280240201a2802002202450d00201a2f0104211b20342113203521152002211a200a2114410121020c070b2034211320352115200a21140b41c002101b2202450d03200241003b010620024100360200200241086a200441e8006a41b802109503210e20022001280200220d36029002200120023602002001200128020441016a360204200d41003b0104200d2002360200200e20022f0106220d410c6c22116a220e2013370204200220116a22114194016a200441286a41086a2802003602002011418c016a2004290328370200200e201536020020024190026a200d41016a220d4102746a20143602002002200d3b01062014200d3b0104201420023602000c060b201a41086a220e2010410c6c220d410c6a22116a200e200d6a220e200220106b410c6c220a1096031a200e2013370204200e2015360200201a418c016a220e20116a200e200d6a220d200a1096031a200d41086a200441c8006a41086a280200360200200d2004290348370200201a41066a200241016a220d3b0100201a4190026a220e20104102746a41086a200e201041016a22024102746a220e200d41ffff0371221120026b4102741096031a200e2014360200201b41ffff037120114f0d05201a2002417f6a22024102746a4194026a210d0340200d280200220e200241016a22023b0104200e201a360200200d41046a210d20112002470d000c060b0b41c0024104101c000b4190024104101c000b41c0024104101c000b410121020c000b0b20004100360200200441a0036a24000ba80202057f027e230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200141206a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128021821082004200128022441286a29030042002005ad4200109903200128022c2202420020022903082209427f200429030020042903084200521b7d220a200a200956200a507222021b37030820020d0020012802282802082007200820066a2005100a2202417e460d0020020d04410421030b20002003360200200441106a24000f0b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41e4d6c3001029000b1600200041003602002000200141206a2802003602040b840a04027f027e027f037e230041d0026b220424000240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441106a200128022441206a2903004200200241146a2802002202ad4200109903200128022c2203420020032903082206427f200429031020042903184200521b7d220720072006562007507222031b37030820030d0a024002402002450d0020024100480d052002101b2203450d062003210841002109024020024102490d00200341002002417f6a220910940320096a21080b200841003a0000200941016a21090c010b4100210241012103410021090b02400240200128022828020820052003200910092205417e460d0020050d042003450d0c2004200936027c20042003360278200441d8016a200441f8006a103820042d00d8012205410e470d010b2002450d0b200310190c0b0b20044180016a200441d8016a41017241d7001095031a200420053a0020200441206a41017220044180016a41d7001095031a02402002450d00200310190b200441003602e001200442013703d801200441206a200441d8016a106420043502e001210a024020042802dc01450d0020042802d80110190b42002107200441d8016a41086a22024200370300200442003703d80141fdc7c1004117200441d8016a100120044180016a41086a22032002290300370300200420042903d8013703800142002106024020044180016a411041d889c200410041001000417f460d00200442003703e001200442003703d80120044180016a4110200441d8016a4110410010002205417f460d062005410f4d0d0620042903d80121060b20024200370300200442003703d8014194c8c1004117200441d8016a100120032002290300370300200420042903d80137038001024020044180016a411041d889c200410041001000417f460d00200442003703e001200442003703d80120044180016a4110200441d8016a4110410010002202417f460d072002410f4d0d0720042903d80121070b2001412c6a2802002202290310220b200241186a290300220c844200510d0720042007200a7e20067c4200200b200c109803200242002002290308220620042903007d220720072006562007507222031b37030802402003450d00200441206a108b010c0b0b2001280200210220044180016a200441206a41d8001095031a200441f0016a2002280218220241d8006a290000370300200441e8016a200241d0006a290000370300200441e0016a200241c8006a290000370300200420022900403703d801200441f8016a20044180016a41d8001095031a200241306a220328020022012002412c6a280200470d09200141016a22052001490d0320014101742209200520052009491b2205ad42f8007e2207422088a70d032007a722094100480d03024002402001450d00200241286a280200200141f8006c2009101a2201450d010c0a0b2009101b22010d090b20094108101c000b41a88ec00041f4031030000b41a88ec00041f4031030000b41ccd6c3001029000b101d000b20024101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41d8fdc2001029000b2002412c6a2005360200200241286a2001360200200241306a28020021010b200241286a280200200141f8006c6a200441d8016a41f8001095031a2003200328020041016a360200410421020c010b410521020b20002002360200200441d0026a24000b970501027f024002400240024002400240024002400240024002400240024002400240024020002d00002201410c4b0d0020010e0d0f010f0f0f0203040506070f080f0b200041046a2802004102470d0e200041086a2200280200108b01200028020010190f0b200041086a280200220141064b0d0a024020010e070e0e000e0c0e0d0e0b200041106a280200450d0d2000410c6a28020010190f0b200041086a2d0000410c490d0c200041106a280200450d0c2000410c6a28020010190f0b200041086a2d000022014105460d0520014102470d0b2000410c6a2200280200108b01200028020010190f0b200041086a2802004102470d0a200041106a280200450d0a2000410c6a28020010190f0b200041086a2d00004102470d092000410c6a2200280200108b01200028020010190f0b200041046a2d00004102470d082000410c6a2200280200108b01200028020010190f0b200041046a2802004102490d072000410c6a280200450d07200041086a28020010190f0b200041086a2d000022014103490d0620014104460d0120014103470d02200041106a280200450d062000410c6a28020010190f0b2000410c6a2200280200108b01200028020010190f0b200041346a280200450d04200041306a28020010190f0b200041306a280200450d032000412c6a28020010190f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141186a2101200241686a22020d000b0b200041106a280200450d022000410c6a28020010190f0b200041106a280200450d012000410c6a28020010190f0b200041106a280200450d002000410c6a28020010190f0b0b5201027e02402003450d0020022802000d00200128022c220342002003290308220420023502047d220520052004562005507222021b37030820004105410420021b3602000f0b41a88ec00041f4031030000bad0d06027f017e047f027e027f027e230041b0016b220424000240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241286a2903002106200241346a2802002107200241c4006a2802002108200241d4006a2802002109200241e4006a280200210a200441206a200128022441206a2903004200200241146a2802002202ad4200109903200128022c220342002003290308220b427f200429032020042903284200521b7d220c200c200b56200c507222031b37030820030d0e024002402002450d0020024100480d0a2002101b2203450d0b2003210d4100210e024020024102490d00200341002002417f6a220e109403200e6a210d0b200d41003a0000200e41016a210e0c010b41002102410121034100210e0b024002400240200128022828020820052003200e10092205417e460d0020050d0a2003450d1120044180016a200e4120200e4120491b22056a41004100412020056b2005411f4b1b1094031a20044180016a200320051095031a200e411f4d0d00200441306a41186a20044180016a41186a290000370300200441306a41106a20044180016a41106a290000370300200441306a41086a20044180016a41086a290000370300200420042900800137033002402002450d00200310190b200441106a200141246a28020041206a29030042002008ad42001099032001412c6a280200220242002002290308220b427f200429031020042903184200521b7d220c200c200b56200c507222021b37030820020d112008450d0120084100480d0b2008101b2202450d0e2002210541002103024020084102490d00200241002008417f6a220310940320036a21050b200541003a0000200341016a21030c020b2002450d10200310190c100b4100210841012102410021030b024002400240200128022828020820072002200310092205417e460d0020050d0d2002450d112004420037038801200442003703800120044180016a20022003411020034110491b1095031a2003410f4d0d0020044188016a290300210f200429038001211002402008450d00200210190b2004200141246a28020041206a2903004200200aad42001099032001412c6a280200220242002002290308220b427f200429030020042903084200521b7d220c200c200b56200c507222021b37030820020d11200a450d01200a4100480d0b200a101b2202450d1041012103200221050240200a4102490d0020024100200a417f6a220310940320036a2105200a21030b200541003a00000c020b2008450d10200210190c100b4100210a41012102410021030b02400240024002400240200128022828020820092002200310092205417e460d0020050d112002450d13200141206a41003602002001411c6a280200210e20012802182108200142013702182001412c6a2802002205290308220b210c2006500d012006210c200b20065a0d0141012103200e450d0220081019200a0d030c040b200a450d12200210190c120b2005200b200c7d3703082005290310210b200441d0006a41186a200541186a2903003703002004200c3703582004200c3703502004200b3703602001280200280218210720044180016a41186a200441306a41186a29030037030020044180016a41106a200441306a41106a29030037030020044180016a41086a200441306a41086a2903003703002004200429033037038001200441003602a8012004200e3602a401200420083602a001200441f0006a200720044180016a2010200f200441d0006a20022003200441a0016a108e01200441f0006a41086a290300210c2004280274210e200428027021082005200429035820052903087c3703084101210320084101460d00200e450d0002402001411c6a2203280200450d00200141186a28020010190b2003200c370200200141186a200e360200410021030b200a450d010b200210190b2000410036020020002003360204200441b0016a24000f0b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41a88ec00041f4031030000b41ccd6c3001029000b101d000b20024101101c000b41ccd6c3001029000b20084101101c000b41ccd6c3001029000b200a4101101c000b20004105360200200441b0016a24000bf61703027f027e087f230041c0036b2209240002400240024020012802182001280234220a28029001470d00200041c8cfc10036020420004101360200200041086a4129360200200841046a2802000d010c020b200542002005290308220b200a4180016a2903007d220c200c200b56200c5072220a1b37030802400240200a450d00200041f1cfc10036020420004101360200200041086a41233602000c010b200941106a2001200210c902200941cc006a419cc1c300360200200941386a41086a4200370300200941e4006a4200370200200941dc006a4280808080800137020020094180016a200241086a29000037030020094188016a200241106a29000037030020094190016a200241186a29000037030020092001360248200941a0c0c10036023c4100210d2009410036023820094208370254200920022900003703782009200128023c3602742009200141346a29020037026c4101210a2009200141186a28020041016a3602500240024002400240024002400240024002400240024002402003200484500d00200941086a20054100200141c0006a200220032004200941386a10ca0220092802082202450d00200928020c21012000200236020420004101360200200041086a2001360200200941c4006a280200210a200928023c2101200941386a41086a2802002202450d012002210520012100034020002802800921002005417f6a22050d000b0340200120012f01064102746a4180096a28020021012002417f6a22020d000c030b0b0240024020092d0010450d0020094198016a41186a200941296a29000037030020094198016a41106a200941216a29000037030020094198016a41086a200941196a2900003703002009200929001137039801200941f0016a20094198016a2001413c6a28020028020010cb0220092802f0014101470d01200020092902f40137020420004101360200200941c4006a280200210a200928023c2101200941386a41086a2802002202450d042002210520012100034020002802800921002005417f6a22050d000b0340200120012f01064102746a4180096a28020021012002417f6a22020d000c060b0b410021074101210e0c070b200941a0036a41186a220a2009418c026a280200360200200941a0036a41106a220d20094184026a290200370300200941a0036a41086a2202200941fc016a290200370300200920092902f4013703a003200941b8016a41106a2002290300370300200941b8016a41186a200d290300370300200941d8016a200a280200360200200941043602bc01200941d7e4c1003602b801200920092903a0033703c001200141386a280200210a200941d0026a41186a200141d8006a290000370300200941d0026a41106a200141d0006a290000370300200941d0026a41086a200141c8006a290000370300200920012900403703d00220024200370300200942003703a003419399c100410d200941a0036a100120094190036a41086a2002290300370300200920092903a003370390034200210c024020094190036a411041d889c200410041001000417f460d00200942003703a00320094190036a4110200941a0036a41084100100041016a41084d0d0a20092903a003210c0b200941a0036a41086a22024200370300200942003703a003418b82c0004111200941a0036a100120094190036a41086a2002290300370300200920092903a0033703900320094190036a411041d889c200410041001000417f460d04200941b8036a4200370300200941a0036a41106a420037030020024200370300200942003703a00320094190036a4110200941a0036a4120410010002202417f460d0a2002411f4d0d0a200941f0026a41186a200941a0036a41186a290300370300200941f0026a41106a200941a0036a41106a290300370300200941f0026a41086a200941a0036a41086a290300370300200920092903a0033703f0020c050b200121000b200941f0016a411c6a20012f010636020020094188026a410036020020094184026a20013602002009200a360290022009410036028002200942003703f801200920003602f401200941003602f001200941f0016a10ad020240200941d8006a280200450d00200941386a411c6a28020010190b0240200941e8006a2802002201450d00200141f8006c2100200941e0006a28020041206a2101034020011043200141f8006a2101200041887f6a22000d000b0b200941e4006a280200450d09200941e0006a2802001019200841046a2802000d0a0c0b0b200121000b200941f0016a411c6a20012f010636020020094188026a410036020020094184026a20013602002009200a360290022009410036028002200942003703f801200920003602f401200941003602f001200941f0016a10ad020240200941d8006a280200450d00200941386a411c6a28020010190b0240200941e8006a2802002201450d00200141f8006c2100200941e0006a28020041206a2101034020011043200141f8006a2101200041887f6a22000d000b0b200941e4006a280200450d07200941e0006a2802001019200841046a2802000d080c090b20094188036a4200370300200941f0026a41106a4200370300200941f0026a41086a4200370300200942003703f0020b20094194026a200941d0026a41086a2903003702002009419c026a200941d0026a41106a290300370200200941a4026a200941d0026a41186a290300370200200941b4026a200941f0026a41086a290300370200200941bc026a200941f0026a41106a290300370200200941c4026a200941f0026a41186a290300370200200920033703f001200920092903d00237028c022009200c37038002200920092903f0023702ac02200920043703f8012009200941386a36028802200941a0036a41086a200841086a280200360200200920082902003703a003200941e0016a200a200941b8016a200941f0016a20062007200941a0036a200510cc024101210a0240024020092802e00122024101460d004100210d4100210720024102470d01200020092902e401370204200041013602000240200941d0016a280200450d00200941cc016a28020010190b200941c4006a2802002108200928023c2101200941c0006a2802002202450d032002210520012100034020002802800921002005417f6a22050d000b0340200120012f01064102746a4180096a28020021012002417f6a22020d000c050b0b200941ec016a280200210d200941e0016a41086a280200210720092802e401210a0b0240200941d0016a280200450d00200941cc016a28020010190b4100210e0b200941f0016a41086a220f200941386a41086a2206290300370300200941b8016a41086a2210200941f0016a410c6a280200360200200920092903383703f001200920092902f4013703b801200941e4006a2802002111200941386a41286a2802002102200941e8006a2802002112200941d8006a2802002113200941386a411c6a2802002105200941dc006a280200211420062010280200360200200920092903b801370338200f2006280200360200200920092903383703f0012001200941f0016a10cd0220092005201441d8006c6a3602fc01200920053602f801200920133602f401200920053602f0012001411c6a200941f0016a10da0120092002201241f8006c6a3602fc01200920023602f801200920113602f401200920023602f001200141286a200941f0016a10db012000410c6a200d360200200041086a20073602002000200a36020420004100360200200e450d06200841046a280200450d0620082802001019200941c0036a24000f0b200121000b200941f0016a411c6a20012f010636020020094188026a410036020020094184026a200136020020092008360290022009410036028002200942003703f801200920003602f401200941003602f001200941f0016a10ad020240200941d8006a280200450d00200941386a411c6a28020010190b0240200941e8006a2802002201450d00200141f8006c2100200941e0006a28020041206a2101034020011043200141f8006a2101200041887f6a22000d000b0b200941e4006a280200450d04200941e0006a2802001019200941c0036a24000f0b41fcf9c00041331030000b41fcf9c00041331030000b200841046a280200450d010b200828020010190b200941c0036a24000b7703017f027e017f2001280200220441086a29030021052004290300210602404110101b2204450d00200420063700002004200537000802402001411c6a2207280200450d00200141186a28020010190b20004104360200200742908080808002370200200141186a20043602000f0b41104101101c000b6202017e027f2001280200290310210402404108101b2205450d002005200437000002402001411c6a2206280200450d00200141186a28020010190b20004104360200200642888080808001370200200141186a20053602000f0b41084101101c000b930c03057f017e027f230041106b22022400200241003602082002420137030002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200128020022034101460d00024020034102460d0020034103470d02200128020421014101101b2203450d0d20024101360204200241086a22042004280200220541016a36020020022003360200200320056a41003a00002001280200210620022001280208220136020c2002410c6a2002105d20022802042205200428020022036b20014f0d05200320016a22042003490d1520054101742203200420042003491b22034100480d152005450d0a200228020020052003101a2204450d0b0c180b200141086a2802002103200128020421054101101b2201450d0d20024101360204200241086a22042004280200220641016a36020020022001360200200120066a41033a00002005290300210720022802042205200428020022016b41084f0d02200141086a22042001490d1420054101742201200420042001491b22014100480d142005450d05200228020020052001101a2204450d060c120b200128020421014101101b2203450d0d20024101360204200241086a22042004280200220541016a36020020022003360200200320056a41023a000020022802042205200428020022036b41204f0d02200341206a22042003490d1320054101742203200420042003491b22034100480d132005450d06200228020020052003101a2204450d070c0f0b200141086a2802002103200128020421014101101b2204450d0d200241086a22052005280200220541016a3602002002410136020420022004360200200420056a41013a00002002200336020c2002410c6a2002105d2003450d1720034105742108200241086a220928020021042002280204210503400240024002400240200520046b41204f0d00200441206a22032004490d1720054101742204200320032004491b22044100480d172005450d01200228020020052004101a22060d020c0e0b20022802002106200421030c020b2004101b2206450d0c0b200220043602042002200636020020092802002103200421050b2009200341206a2204360200200620036a220341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a29000037000020032001290000370000200141206a2101200841606a22080d000c180b0b200228020021040c100b200228020021040c0d0b200228020021040c130b2001101b22040d0c0b20014101101c000b2003101b22040d080b20034101101c000b2003101b22040d0d0b20034101101c000b20044101101c000b41014101101c000b41014101101c000b41014101101c000b41014101101c000b2002200336020420022004360200200241086a28020021030b200241086a200341206a360200200420036a220341086a200141086a290000370000200341106a200141106a290000370000200341186a200141186a290000370000200320012900003700000c070b2002200136020420022004360200200241086a28020021010b200241086a2205200141086a360200200420016a200737000002400240024020022802042204200528020022016b41c0004f0d00200141c0006a22052001490d0320044101742201200520052001491b22014100480d032004450d01200228020020042001101a2204450d020c040b200228020021040c040b2001101b22040d020b20014101101c000b101d000b2002200136020420022004360200200241086a28020021010b200241086a200141c0006a360200200420016a220141086a200341086a290000370000200141106a200341106a290000370000200141186a200341186a290000370000200141206a200341206a290000370000200141286a200341286a290000370000200141306a200341306a290000370000200141386a200341386a290000370000200120032900003700000c020b2002200336020420022004360200200241086a28020021030b200241086a200320016a360200200420036a200620011095031a0b20002002290300370200200041086a200241086a280200360200200241106a24000bdb0201027f200141346a280200210320012802302104024002400240024002400240200241ff017122024102460d0020024103470d0120040d0320004100360200200128020c22000d040c050b2004450d01200141386a2802002102200041013602002000410c6a2002360200200041086a2003360200200041046a2004360200200128020c22000d030c040b200041f58cc00036020420004102360200200041086a411036020002402004450d002003450d00200410190b200128020c2200450d030c020b20004102360200200041086a4110360200200041046a41f58cc000360200200128020c22000d010c020b41f0b1c2001029000b200141106a280200450d00200010190b02402001411c6a280200450d00200128021810190b200128022822012001280200417f6a22003602000240024020000d002001280208100b20012001280204417f6a22003602042000450d010b0f0b200110190bca0202037f017e230041306b22012400200141206a41086a220242003703002001420037032041c695c0004114200141206a1001200141086a200229030037030020012001290320370300024002402001411041d889c200410041001000417f460d002001200136021020014110360214200142003703202001410020014110200141206a41084100100022022002417f461b2202410820024108491b2203360218200241074d0d012001290320210420014100360220200141186a410020014110200141206a41042003100022022002417f461b2202410420024104491b20036a360200200241034d0d0120012802202102200141206a200141106a103a20012802202203450d01200020012902243703102000200336020c2000200236020820002004370300200141306a24000f0b2000410036020c200141306a24000f0b41fcf9c00041331030000bd20403057f027e027f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d024002400240024002402000450d002003200041306c6a2104200241106a41086a280200210520022802102106200228021421000340200341086a2903002107200329030021080240024002400240200020056b41104f0d00200541106a22092005490d072000410174220a20092009200a491b220a4100480d072000450d0120062000200a101a22060d020c080b200541106a21090c020b200a101b2206450d060b200a21000b200620056a22052007370008200520083700000240024002400240200020096b41204f0d00200941206a22052009490d072000410174220a20052005200a491b220a4100480d072000450d0120062000200a101a22060d020c090b200941206a21050c020b200a101b2206450d070b200a21000b200620096a220941186a200341286a290000370000200941106a200341206a290000370000200941086a200341186a2900003700002009200341106a290000370000200341306a22032004470d000b200241186a200536020020022000360214200220063602100c010b200241186a280200210520022802142100200228021021060b2001280204210320012802002109200241106a41086a220a42003703002002420037031020092003200241106a1001200241086a200a290300370300200220022903103703002002411020062005100302402000450d00200610190b200241206a24000f0b101d000b200a4101101c000b200a4101101c000bce0506027f017e0b7f017e027f017e230041d0006b22022400200241086a200110680240024002400240024002400240024002402002280208450d00200228020c2203ad42307e2204422088a70d032004a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0006a24000f0b4108210620030d030b4100210d4100210c0c030b102b000b20054108101c000b200141046a2107200141086a2108200241306a41186a21094100210a4100210b410021052003210c0240034020024200370338200242003703302008410020012802002007280200200241306a411020082802001000220d200d417f461b220d4110200d4110491b20082802006a220e360200200d410f4d0d01200241306a41086a220f29030021042002290330211020094200370300200241306a41106a22114200370300200f4200370300200242003703302008410020012802002007280200200241306a4120200e1000220d200d417f461b220d4120200d4120491b20082802006a360200200d411f4d0d01200541016a210d200241106a41186a220e2009290300370300200241106a41106a22122011290300370300200241106a41086a2211200f2903003703002002200229033037031002402005200c470d00200a200d200d200a491b220cad42307e2213422088a70d042013a7220f4100480d0402402005450d002006200b200f101a22060d010c060b200f101b2206450d050b2006200b6a2205200437030820052010370300200541286a200e290300370300200541206a2012290300370300200541186a2011290300370300200541106a2002290310370300200a41026a210a200b41306a210b200d2105200d2003490d000c020b0b200041003602000240200c450d00200610190b200241d0006a24000f0b2000200c36020420002006360200200041086a200d360200200241d0006a24000f0b101d000b200f4108101c000bd40402087f017e230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d024002400240024002402000450d002003200041286c6a2104200241106a41086a220528020021002002280214210603400240024002400240200620006b41204f0d00200041206a22072000490d0720064101742208200720072008491b22094100480d072006450d01200228021020062009101a22080d020c080b200041206a2107200228021021080c020b2009101b2208450d060b2002200936021420022008360210200921060b20052007360200200820006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a290300210a0240024002400240200620076b41084f0d00200741086a22002007490d0720064101742209200020002009491b22094100480d072006450d01200820062009101a22080d020c090b200741086a21000c020b2009101b2208450d070b2002200936021420022008360210200921060b20052000360200200820076a200a3700002004200341286a2203470d000c020b0b200241186a280200210020022802142106200228021021080b2001280204210320012802002107200241106a41086a220542003703002002420037031020072003200241106a1001200241086a2005290300370300200220022903103703002002411020082000100302402006450d00200810190b200241206a24000f0b101d000b20094101101c000b20094101101c000bed0201027f230041206b22022400024002404116101b2203450d002003410e6a41002900e39640370000200341086a41002900dd9640370000200341002900d59640370000200341164136101a2203450d01200320012900003700162003412e6a200141186a290000370000200341266a200141106a2900003700002003411e6a200141086a290000370000200241106a41086a220142003703002002420037031020034136200241106a1001200241086a2001290300370300200220022903103703000240024002402002411041d889c200410041001000417f460d002002410036021020024110200241106a41044100100041016a41044d0d02200228021021012002410036021020024110200241106a41044104100041016a41044d0d02200041086a200228021036020020002001360204200041013602000c010b200041003602000b20031019200241206a24000f0b41fcf9c00041331030000b41164101101c000b41364101101c000bc10301077f230041206b220224002002410036021820024201370310200028020021032002200028020822003602002002200241106a105d02400240024002402000450d0020004105742104200241106a41086a2802002100200228021021052002280214210603400240024002400240200620006b41204f0d00200041206a22072000490d0720064101742208200720072008491b22084100480d072006450d01200520062008101a22050d020c080b200041206a21070c020b2008101b2205450d060b200821060b200520006a22002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020072100200341206a2103200441606a22040d000b200241186a200736020020022006360214200220053602100c010b200241186a280200210720022802142106200228021021050b2001280204210320012802002100200241106a41086a220442003703002002420037031020002003200241106a1001200241086a2004290300370300200220022903103703002002411020052007100302402006450d00200510190b200241206a24000f0b101d000b20084101101c000b130020004109360204200041d0b4c2003602000b130020004107360204200041baa6c0003602000b130020004114360204200041ecbbc2003602000b7801047f230041106b22022400200241003602082002420137030002404101101b2203450d00200220033602002002410136020420002002290300370200200241086a22042004280200220441016a2205360200200320046a41003a0000200041086a2005360200200241106a24000f0b41014101101c000b3201017f02404104101b2202450d0020004284808080c00037020420002002360200200241003600000f0b41044101101c000b3201017f02404108101b2202450d0020004288808080800137020420002002360200200242053700000f0b41084101101c000b3201017f02404104101b2202450d0020004284808080c00037020420002002360200200241013600000f0b41044101101c000b3201017f02404104101b2202450d0020004284808080c00037020420002002360200200241023600000f0b41044101101c000b3901017f02404110101b2202450d002002420037000820024201370000200042908080808002370204200020023602000f0b41104101101c000b3901017f02404110101b2202450d002002420037000820024209370000200042908080808002370204200020023602000f0b41104101101c000bb50901047f230041206b220224000240024002402001280200417e6a220341084b0d000240024002400240024002400240024002400240024002400240024002400240024020030e09000502030106070408000b2001410c6a2802002203417f4c0d112003450d0e200128020421042003101b2205450d122005200420031095031a0c0f0b4101210320012d00044101470d07200141086a28020021050c080b2000410436020020002001280204360204200241206a24000f0b2000410536020020002001280204360204200241206a24000f0b20004109360200200041086a200141086a290300370300200241206a24000f0b2001280204210541012103200141086a22042d00004101470d052001410c6a28020021040c060b2000410736020020002001280204360204200241206a24000f0b4101210320012d00044101470d05200141086a28020021010c060b2000410a360200200041086a200141086a290300370300200241206a24000f0b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021030b200020033a0004200020022f011c3b0005200041086a20053602002000410c6a2002290300370200200041386a200141386a290300370300200041306a200141306a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a280200360200200141286a280200210120004106360200200041286a2001360200200241206a24000f0b2002411e6a200441036a2d00003a0000200241086a200141186a290200370300200241106a200141206a290200370300200241186a200141286a2d00003a0000200220042f00013b011c2002200141106a2902003703002001410c6a2802002104410021030b20002005360204200020022f011c3b0009200041086a20033a00002000410c6a2004360200200041106a20022903003702002000410b6a2002411e6a2d00003a0000200041186a200241086a290300370200200041206a200241106a290300370200200041286a200241186a2802003602002000412c6a2001412c6a29020037020020004103360200200241206a24000f0b2002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030b200020022f011c3b0005200020033a000420004108360200200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a280200360200200241206a24000f0b410121050b20002005360204200041023602002000410c6a2003360200200041086a2003360200200041106a200141106a280200360200200241206a24000f0b41dccac2001029000b102b000b20034101101c000bd4b0010d0c7f027e0d7f027e037f027e067f027e057f037e037f027e407f230041c0046b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802002204417e6a220541084b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e09000502030106070408000b2001410c6a2802002106200141086a2802002107200141106a280200210820012802042109200241096a280000210a200241056a280000210520022d0001210b20022d0000210120034194046a41026a220c200241046a2d00003a0000200341f8036a41086a220d200241156a290000370300200341f8036a410d6a220e2002411a6a2900003700002003200241026a2f01003b01940420032002410d6a2900003703f8032001450d12410121020c130b200141386a290300210f200141306a2903002110200141286a2802002111200341ac026a41026a200141076a2d00003a000020034190026a41086a200141186a29020037030020034190026a410d6a2001411d6a290000370000200320012f00053b01ac022003200141106a29020037039002200141086a28020021122001410c6a280200211320012d00042114200241096a280000210a200241056a280000210520022d0001211520022d0000211620034194046a41026a2217200241046a2d00003a0000200341f8036a41086a2218200241156a290000370300200341f8036a410d6a22192002411a6a2900003700002003200241026a2f01003b01940420032002410d6a2900003703f8032016450d08410121020c090b2001280204210c200241096a280000210a200241056a280000210520022d0001210720022d0000210120034194046a41026a2206200241046a2d00003a0000200341f8036a41086a2209200241156a290000370300200341f8036a410d6a220b2002411a6a2900003700002003200241026a2f01003b01940420032002410d6a2900003703f8032001450d0a410121020c0b0b20012802042107200241096a280000210a200241056a280000210520022d0001210620022d0000210120034194046a41026a2209200241046a2d00003a0000200341f8036a41086a220b200241156a290000370300200341f8036a410d6a220c2002411a6a2900003700002003200241026a2f01003b01940420032002410d6a2900003703f8032001450d0c410121020c0d0b20022d000120022d0000720d042003200141086a2903003703d002200341f8036a41086a22024200370300200342003703f80341ee95c000411c200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a4110200341d0026a410810030c670b200141306a280200211a2001412c6a280200211b2001280204211c200341ac026a41026a2001410b6a2d00003a000020034190026a41086a2001411c6a29020037030020034190026a410d6a200141216a290000370000200320012f00093b01ac022003200141146a29020037039002200141086a2d0000210b2001410c6a2802002107200141106a2802002109200241096a280000210a200241056a280000210520022d0001210c20022d0000210620034194046a41026a220d200241046a2d00003a0000200341f8036a41086a220e200241156a290000370300200341f8036a410d6a22082002411a6a2900003700002003200241026a2f01003b01940420032002410d6a2900003703f8032006450d10410121020c110b20022d000120022d0000720d02200320012802043602d002200341f8036a41086a22024200370300200342003703f80341b295c0004114200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a4110200341d0026a410410030c650b20034190026a41026a2209200141076a2d00003a0000200341e0036a41086a221a200141186a290200370300200341e0036a410d6a221c2001411d6a290000370000200320012f00053b0190022003200141106a2902003703e00320022d000120022d0000720d012001410c6a280200210a200141086a280200210520012d0004210220034194046a41026a20092d00003a0000200341d0026a41086a201a290300370300200341d0026a410d6a201c290000370000200320032f0190023b019404200320032903e0033703d002200241ff01714101470d1720034198046a2005410676106120032802a0042005413f7122024d0d1a20034190046a41026a20032802980420024105746a220241026a2d00003a000020034180046a200241136a29000037030020034185046a200241186a290000370000200320022f00003b0190042003200229000b3703f8032002280007210a2002280003210541012102200328029c04450d5c0c5b0b20022d000120022d000072450d100b41e580c00021054128210a0c650b20034190046a41026a20172d00003a0000200341e0036a41086a2018290300370300200341e0036a410d6a2019290000370000200320032f0194043b019004200320032903f8033703e00341012102201541ff01714101470d00200341b0026a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341e0036a41086a290300370300200341d0026a410d6a200341e0036a410d6a290000370000200320032f0190043b01b002200320032903e0033703d002410021020c010b412a210a418d81c00021050b200341cc026a41026a2216200341b0026a41026a2d00003a000020034198046a41086a2215200341d0026a41086a29030037030020034198046a41106a200341d0026a41106a290300370300200320032f01b0023b01cc02200320032903d0023703980420020d55200341d3036a2015290300370000200341d8036a20034198046a410d6a290000370000200320032f01cc023b01c0032003200a3600c703200320053600c30320032003290398043700cb03200320162d00003a00c2032010200f84500d0e20034194046a41026a2202200341ac026a41026a2d00003a0000200341d0026a41086a220520034190026a41086a290300370300200341d0026a410d6a20034190026a410d6a290000370000200320032f01ac023b01940420032003290390023703d002201441ff01714101470d13200341e0036a2012410676106120032802e8032012413f7122024d0d1720034190046a41026a20032802e00320024105746a220241026a2d00003a000020034180046a200241136a29000037030020034185046a200241186a290000370000200320022f00003b0190042003200229000b3703f80320022800072113200228000321124101210220032802e403450d520c510b20034190046a41026a20062d00003a0000200341e0036a41086a2009290300370300200341e0036a410d6a200b290000370000200320032f0194043b019004200320032903f8033703e00341012102200741ff01714101470d00200341c0036a41026a20034190046a41026a2d00003a000020034198046a41086a200341e0036a41086a29030037030020034198046a410d6a200341e0036a410d6a290000370000200320032f0190043b01c003200320032903e00337039804410021020c010b418d81c0002105412a210a0b200341cc026a41026a2207200341c0036a41026a2d00003a0000200341b0026a41086a220120034198046a41086a290300370300200341b0026a41106a20034198046a41106a290300370300200320032f01c0033b01cc0220032003290398043703b00220020d5f200341e3026a2001290300370000200341e8026a200341bd026a290000370000200320032f01cc023b01d0022003200a3600d702200320053600d302200320032903b0023700db02200320072d00003a00d202200341f8036a41086a22024200370300200342003703f80341c695c0004114200341f8036a100120012002290300370300200320032903f8033703b002200341b0026a4110100c450d0c4193b9c0002105411e210a0c5f0b20034190046a41026a20092d00003a0000200341e0036a41086a200b290300370300200341e0036a410d6a200c290000370000200320032f0194043b019004200320032903f8033703e00341012102200641ff01714101470d00200341c0036a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341e0036a41086a290300370300200341d0026a410d6a200341e0036a410d6a290000370000200320032f0190043b01c003200320032903e0033703d002410021020c010b412a210a418d81c00021050b200341cc026a41026a2201200341c0036a41026a2d00003a0000200341b0026a41086a2206200341d0026a41086a290300370300200341b0026a41106a200341d0026a41106a290300370300200320032f01c0033b01cc02200320032903d0023703b00220020d5c200341ab046a2006290300370000200341b0046a200341bd026a290000370000200320032f01cc023b0198042003200a36009f042003200536009b04200320032903b0023700a304200320012d00003a009a044116101b2202450d242002410e6a41002900e39640370000200241086a41002900dd9640370000200241002900d59640370000200241164136101a2202450d2520022003290398043700162002412e6a200341b0046a290300370000200241266a20034198046a41106a290300370000411e210a2002411e6a20034198046a41086a290300370000200341f8036a41086a22014200370300200342003703f80320024136200341f8036a1001200341b0026a41086a2001290300370300200320032903f8033703b002200341b0026a4110100c21012002101941fab9c000210520010d5c200341f8036a41086a22024200370300200342003703f80341fd96c0004116200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002410021010240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d2320032802d00221010b200341f8036a41086a22024200370300200342003703f80341eb96c0004112200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b00241002102200341b0026a411041d889c200410041001000417f460d13200342103702c4032003200341b0026a3602c003200341d0026a200341c0036a103a20032802d0022209450d29200341d8026a280200210620032802d402210220012007460d140c150b20034190046a41026a200c2d00003a0000200341e0036a41086a200d290300370300200341e0036a410d6a200e290000370000200320032f0194043b019004200320032903f8033703e00341012102200b41ff01714101470d00200341c0036a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341e0036a41086a290300370300200341d0026a410d6a200341e0036a410d6a290000370000200320032f0190043b01c003200320032903e0033703d002410021020c010b418d81c0002105412a210a0b200341cc026a41026a220b200341c0036a41026a2d00003a0000200341b0026a41086a2201200341d0026a41086a290300370300200341b0026a41106a200341d0026a41106a290300370300200320032f01c0033b01cc02200320032903d0023703b00220020d37200341ab046a2001290300370000200341b0046a200341bd026a290000370000200320032f01cc023b0198042003200a36009f042003200536009b04200320032903b0023700a3042003200b2d00003a009a04200341f8036a41086a22024200370300200342003703f80341eb96c0004112200341f8036a100120012002290300370300200320032903f8033703b00241002101200341b0026a411041d889c200410041001000417f460d07200342103702c4032003200341b0026a3602c003200341d0026a200341c0036a103a20032802d002220d450d23200341d8026a280200210120032802d402210b0c080b20034190046a41026a200d2d00003a0000200341e0036a41086a200e290300370300200341e0036a410d6a2008290000370000200320032f0194043b019004200320032903f8033703e00341012102200c41ff01714101470d00200341b0026a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341e0036a41086a290300370300200341d0026a410d6a200341e0036a410d6a290000370000200320032f0190043b01b002200320032903e0033703d002410021020c010b418d81c0002105412a210a0b200341cc026a41026a2206200341b0026a41026a2d00003a000020034198046a41086a220c200341d0026a41086a220d29030037030020034198046a41106a200341d0026a41106a290300370300200320032f01b0023b01cc02200320032903d0023703980420020d49200341d3036a200c290300370000200341d8036a20034198046a410d6a290000370000200320032f01cc023b01c0032003200a3600c703200320053600c30320032003290398043700cb03200320062d00003a00c20320034194046a41026a200341ac026a41026a2d00003a0000200d20034190026a41086a290300370300200341d0026a410d6a220220034190026a410d6a290000370000200320032f01ac023b01940420032003290390023703d002200b41ff01714101470d01200341e0036a2007410676106120032802e8032007413f7122024d0d0820034190046a41026a20032802e00320024105746a220241026a2d00003a000020034180046a200241136a29000037030020034185046a200241186a290000370000200320022f00003b0190042003200229000b3703f80320022800072109200228000321074101210220032802e403450d420c410b2003200141086a2903003703d002200341f8036a41086a22024200370300200342003703f80341da95c0004114200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a4110200341d0026a410810030c520b20034190046a41026a20034194046a41026a2d00003a0000200341f8036a41086a200341d0026a41086a290300370300200341f8036a410d6a2002290000370000200320032f0194043b019004200320032903d0023703f8030c410b41ccbac000210541d000210a20044102470d530c520b4114101b2202450d1d200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d1e200220032903d0023700144118210a2002412c6a200341d0026a41186a290300370000200241246a200341d0026a41106a2903003700002002411c6a200341d0026a41086a290300370000200341f8036a41086a22014200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2001290300370300200320032903f8033703b002200341b0026a4110100c2101200210192001450d08200341f8036a41086a22024200370300200342003703f803418a96c000410e200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a411041d889c200410041001000417f460d0c200342103702c4032003200341b0026a3602c00320034198046a200341c0036a103a2003280298042202450d20200328029c042101200341a0046a2802002205200c4d0d0d2002200c4105746a220a200341d0026a460d11200a200341d0026a4120109703450d1141e1b9c00021054119210a20010d0e0c520b4101210d4100210b0b200341f8036a41086a22024200370300200342003703f80341c695c0004114200341f8036a1001200341b0026a41086a22052002290300370300200320032903f8033703b0020240200341b0026a4110100c450d0041b6b5c0002105412e210a200b0d2e0c2f0b20024200370300200342003703f803419397c0004111200341f8036a100120052002290300370300200320032903f8033703b002410021020240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d1820032802d00221020b20022008470d042001450d0d200120064f0d0e41b9b6c000210541c500210a200b0d2d0c2e0b20034190046a41026a20034194046a41026a2d00003a0000200341f8036a41086a200341d0026a41086a290300370300200341f8036a410d6a200341d0026a410d6a290000370000200320032f0194043b019004200320032903d0023703f8030c450b20034190046a41026a20022d00003a0000200341f8036a41086a2005290300370300200341f8036a410d6a200341d0026a410d6a290000370000200320032f0194043b019004200320032903d0023703f8030c3f0b4100210220032802e4030d380c390b41002102200328029c040d400c410b41e4b5c00021054114210a200b0d280c290b4100210220032802e4030d390c3a0b41b1b9c00021050c490b410121094100210620012007470d010b20062007460d260b4198bac00021054116210a200620074d0d26200341e8026a4200370300200341e0026a4200370300200341d8026a4200370300200342003703d002200920074105746a220b200341d0026a460d25200b200341d0026a41201097030d260c250b41c9b9c00021050c450b41c9b9c00021054118210a2001450d440b200210190c430b41f8b5c000210541c100210a0c1e0b4114101b2202450d10200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d1120022003290398043700142002412c6a200341b0046a290300370000200241246a20034198046a41106a2903003700002002411c6a20034198046a41086a29030037000042002123200341f8036a41086a22014200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2001290300370300200320032903f8033703b002200341b0026a4110100c2101200210192001450d010c160b200320053602a0042003200136029c042003200236029804200341d0026a200c20034198046a10a5014200212c200341f8036a41086a22024200370300200342003703f8034192b7c0004112200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b00241002105200341b0026a411041d889c200410041001000417f460d01200342003703a0042003420037039804200341b0026a411020034198046a4110410010002202417f460d112002410f4d0d11200341a0046a290300211e200329039804212c0c020b200341f8036a41086a22024200370300200342003703f8034192b7c0004112200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a411041d889c200410041001000417f460d02200342003703d802200342003703d002200341b0026a4110200341d0026a4110410010002202417f460d112002410f4d0d11200341d8026a290300212420032903d00221230c030b4200211e0b20034188016a200341d0026a104420034188016a41086a29030021232003290388012124200341f8006a200341d0026a1045200341d0026a202c20242024202c562023201e562023201e511b22021b222c20032903787c222b201e202320021b221e200341f8006a41086a2903007c202b202c54ad7c1046200341d0026a2024202c7d2023201e7d2024202c54ad7d10470c3b0b420021240b200341106a20034198046a104502402003290310222c2023542202200341106a41086a290300221e202454201e2024511b450d0041d1fac00021054115210a200b0d190c1a0b411e210a20034198046a10a60122050d17200320034198046a104420034198046a2003290300222b20237c220f200341086a29030020247c200f202b54ad7c104720034198046a202c20237d201e20247d2002ad7d1046200341f8036a41086a22024200370300200342003703f803418a96c000410e200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b0024100210202400240200341b0026a411041d889c200410041001000417f460d00200342103702c4032003200341b0026a3602c003200341d0026a200341c0036a103a20032802d0022205450d10200341d0026a41086a2201280200210220032802d402210c200341d0026a41186a20034198046a41186a290300370300200341d0026a41106a20034198046a41106a290300370300200120034198046a41086a29030037030020032003290398043703d002200341d0026a2101200c2002460d010c110b200341d0026a41186a20034198046a41186a290300370300200341d0026a41106a20034198046a41106a290300370300200341d0026a41086a20034198046a41086a29030037030020032003290398043703d00241012105200341d0026a21010b200241016a220a2002490d342002410174220c200a200a200c491b220cad4205862223422088a70d342023a7220a4100480d34024002402002450d0020052002410574200a101a2205450d010c110b200a101b22050d100b200a4101101c000b41f4cac2001029000b41fcf9c00041331030000b41fcf9c00041331030000b41164101101c000b41364101101c000b41fcf9c00041331030000b41144101101c000b41344101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41144101101c000b41344101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b200520024105746a220a2001290000370000200a41186a200141186a290000370000200a41106a200141106a290000370000200a41086a200141086a2900003700002003200241016a3602d8022003200c3602d402200320053602d0022003410e3602c4032003418a96c0003602c003200341d0026a200341c0036a109801200c450d0020051019411421014114101b22020d010c020b411421014114101b2202450d010b200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200220014134101a2202450d0220022003290398043700142002412c6a200341b0046a290300370000200241246a20034198046a41106a2903003700002002411c6a20034198046a41086a290300370000200320083602d002200341f8036a41086a22014200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2001290300370300200320032903f8033703b002200341b0026a4110200341d0026a41041003200210194113101b2202450d032002410f6a41002800b3b740360000200241086a41002900acb740370000200241002900a4b740370000200241134133101a2208450d0420082003290398043700132008412b6a200341b0046a290300370000200841236a200341a8046a2903003700002008411b6a20034198046a41086a290300370000200341003602d802200342013703d002200320063602c003200341c0036a200341d0026a105d024002402006450d00200341d8026a220e280200210220032802d4022101200921050340024002400240024020022001470d00200141016a220a2001490d292001410174220c200a200a200c491b220c4100480d292001450d0120032802d0022001200c101a220a0d020c080b20032802d002210a0c020b200c101b220a450d060b2003200c3602d4022003200a3602d002200c21010b200e200241016a220c360200200a20026a20052d00003a0000200c2102200541016a21052006417f6a22060d000c020b0b200341d8026a280200210c20032802d402210120032802d002210a0b200341f8036a41086a22024200370300200342003703f80320084133200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a4110200a200c100302402001450d00200a10190b2008101902402007450d00200910190b200b450d26200d10190c260b20014101101c000b200c4101101c000b41344101101c000b41134101101c000b41334101101c000b200b450d010b200d10190b2007450d21200910190c210b42002123200341f8036a41086a22054200370300200342003703f80341a497c0004115200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b00202400240200341b0026a411041d889c200410041001000417f460d00200342003703d802200342003703d002200341b0026a4110200341d0026a4110410010002205417f460d042005410f4d0d04200341d8026a290300212320032903d00221240c010b420921240b200341a8016a20034198046a104541aebac0002105411e210a20032903a801222c202454220b200341b0016a290300221e202354201e2023511b0d0020034198046a10a601450d010b2002450d1f200910190c1f0b20034198016a20034198046a104420034198046a200329039801222b20247c220f20034198016a41086a29030020237c200f202b54ad7c104720034198046a202c20247d201e20237d200bad7d1046200341f8036a41086a22054200370300200342003703f803419397c0004111200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b0024100210b0240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0220032802d002210b0b4116101b2205450d022005410e6a41002900e39640370000200541086a41002900dd9640370000200541002900d59640370000200541164136101a2205450d0320052003290398043700162005412e6a200341b0046a290300370000200541266a200341a8046a2903003700002005411e6a20034198046a41086a2903003700004104101b220a450d04200a200b360000200a41044108101a220a450d05200a2007360004200341f8036a41086a220b4200370300200342003703f80320054136200341f8036a1001200341b0026a41086a200b290300370300200320032903f8033703b002200341b0026a4110200a41081003200a10192005101902400240024020062007470d00200341d0026a41186a220a20034198046a41186a290300370300200341d0026a41106a20034198046a41106a290300370300200341d0026a41086a220620034198046a41086a29030037030020032003290398043703d00220022007470d0a200741016a22022007490d1a20074101742205200220022005491b2202ad4205862223422088a70d1a2023a722054100480d1a2007450d01200920074105742005101a2209450d020c0a0b200341d0026a41186a220a20034198046a41186a290300370300200341d0026a41106a20034198046a41106a290300370300200341d0026a41086a220b20034198046a41086a29030037030020032003290398043703d002200620074d0d08200920074105746a220520032903d002370000200541186a200a290300370000200541106a200341d0026a41106a290300370000200541086a200b2903003700000c0a0b2005101b22090d080b20054101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41164101101c000b41364101101c000b41044101101c000b41084101101c000b41c0b4c20020072006104a000b200920074105746a220520032903d002370000200541186a200a290300370000200541106a200341d0026a41106a290300370000200541086a2006290300370000200741016a21060b200320063602d802200320023602d402200320093602d002200341123602c403200341eb96c0003602c003200341d0026a200341c0036a10980102402002450d00200910190b2003200141016a3602d002200341f8036a41086a22024200370300200342003703f80341fd96c0004116200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a4110200341d0026a410410030c120b20032802e00310190b20020d004101210241bde3c1002107411521090c010b200341e0036a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341f8036a41086a290300370300200341d0026a410d6a200341f8036a410d6a290000370000200320032f0190043b01e003200320032903f8033703d002410021020b200341cc026a41026a220a200341e0036a41026a2d00003a0000200341b0026a41086a2205200341d0026a41086a290300370300200341b0026a41106a200341d0026a41106a290300370300200320032f01e0033b01cc02200320032903d0023703b00202402002450d002009210a2007210520044102470d120c110b200341ab046a2005290300370000200341b0046a200341bd026a290000370000200320032f01cc023b0198042003200936009f042003200736009b04200320032903b0023700a3042003200a2d00003a009a04200341f8036a41086a22024200370300200342003703f80341c695c0004114200341f8036a100120052002290300370300200320032903f8033703b0020240200341b0026a4110100c450d0041b7b7c00021054126210a20044102470d120c110b024002400240024002404114101b2202450d00200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d01200220032903c0033700144118210a2002412c6a200341c0036a41186a290300370000200241246a200341c0036a41106a2903003700002002411c6a200341c0036a41086a290300370000200341f8036a41086a22054200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b0020240024002400240024002400240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d04200210194114101b2202450d09200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d0a2002200329039804370014412c210a2002412c6a200341b0046a290300370000200241246a20034198046a41106a2903003700002002411c6a20034198046a41086a290300370000200341f8036a41086a22054200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b002200341b0026a411041d889c200410041001000417f460d01200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0520032802d002210720021019200341f8036a41086a22024200370300200342003703f803419397c0004111200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a411041d889c200410041001000417f460d02200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0620032802d002201a470d030c0b0b2002101941ddb7c000210520044102470d1c0c1b0b2002101941aab8c000210520044102470d1b0c1a0b4100201a460d080b41f5b7c00021054116210a20044102470d190c180b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41144101101c000b41344101101c000b41144101101c000b41344101101c000b200341f8036a41086a22024200370300200342003703f80341e8b8c000411b200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b0020240024002400240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0220032802d00220076a201a4f0d010c030b410120076a201a490d020b418bb8c0002105411f210a20044102470d130c120b41fcf9c00041331030000b200341f8036a41086a22024200370300200342003703f803418a96c000410e200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002024002400240024002400240200341b0026a411041d889c200410041001000417f460d00200342103702fc032003200341b0026a3602f803200341d0026a200341f8036a103a20032802d0022206450d0220032802d402210941d6b8c00021054112210a0240200341d8026a280200220c201c4d0d0002402006201c4105746a2202200341c0036a460d002002200341c0036a41201097030d010b4183b9c00021054110210a200c201b4d0d002006201b4105746a220220034198046a460d02200220034198046a4120109703450d020b2009450d0a2006101920044102470d170c160b41d6b8c00021054112210a20044102470d160c150b200341e0036a20034198046a10a70120032802e803210220032802e003210a200341f8036a41086a22054200370300200342003703f80341eb96c0004112200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b0024100210502400240200341b0026a411041d889c200410041001000417f460d00200342103702fc032003200341b0026a3602f803200341d0026a200341f8036a103a20032802d0022225450d03200341d8026a280200210520032802d40221160c010b41012125410021160b02400240200541ffffff3f7122052002200220054b1b220b450d0041002105200341e8026a210d200341e0026a210e200341d8026a21082025210203400240200a20056a2d0000450d00200d4200370300200e420037030020084200370300200342003703d002200341d0026a2002460d002002200341d0026a4120109703450d00200341d0026a20021097014101211a20032802d0024101470d0020032802d40220074d0d030b200241206a2102200541016a2205200b490d000b0b4100211a0b02402016450d00202510190b024020032802e403450d00200a10190b2003200c3602d802200320093602d402200320063602d002200341c0036a20034198046a201a1b201c201b201a1b200341d0026a10a50142002123200341f8036a41086a22024200370300200342003703f8034192b7c0004112200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b002200341b0026a411041d889c200410041001000210202400240024002400240201a450d002002417f460d01200342003703d802200342003703d002200341b0026a4110200341d0026a4110410010002202417f460d072002410f4d0d07200341d8026a290300212320032903d00221240c020b2002417f460d02200342003703d802200342003703d002200341b0026a4110200341d0026a4110410010002202417f460d072002410f4d0d07200341d8026a290300211e20032903d00221230c030b42002124420021230b200341206a200341c0036a2024202310a801200341dd026a200341c8036a290300370000200341e5026a200341d0036a290300370000200341ed026a200341d8036a290300370000200341013a00d402200341063a00d002200320032903c0033700d502200341d0026a103d4100210520044102470d170c160b4200211e0b200341e8006a200341c0036a1045200341e8006a41086a290300212c20032903682124200341d8006a200341c0036a104402402003290358420020247d85200341d8006a41086a2903004200202c7d2024420052ad7d858450450d0041affac00021054122210a20044102470d160c150b200341c8006a20034198046a104420032903482124200341c8006a41086a290300212c200341386a200341c0036a1045200341c0036a202320242024202356202c201e56202c201e511b22021b222320032903387c222b201e202c20021b221e200341386a41086a2903007c202b202354ad7c104620034198046a202420237d202c201e7d2024202354ad7d1047200341dd026a20034198046a41086a290300370000200341e5026a20034198046a41106a290300370000200341ed026a20034198046a41186a290300370000200341f5026a20032903c003370000200341fd026a200341c0036a41086a29030037000020034185036a200341c0036a41106a2903003700002003418d036a200341c0036a41186a29030037000041002105200341003a00d402200341063a00d00220032003290398043700d502200341d0026a103d20044102470d150c140b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b20032802e00310190b20020d004101210241bde3c1002112411521130c010b200341e0036a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341f8036a41086a290300370300200341d0026a410d6a200341f8036a410d6a290000370000200320032f0190043b01e003200320032903f8033703d002410021020b200341cc026a41026a220a200341e0036a41026a2d00003a0000200341b0026a41086a2205200341d0026a41086a290300370300200341b0026a41106a200341d0026a41106a290300370300200320032f01e0033b01cc02200320032903d0023703b00202402002450d002013210a2012210520044102470d0e0c0d0b200341ab046a2005290300370000200341b0046a200341bd026a290000370000200320032f01cc023b0198042003201336009f042003201236009b04200320032903b0023700a3042003200a2d00003a009a04200341f8036a41086a22024200370300200342003703f803419397c0004111200341f8036a100120052002290300370300200320032903f8033703b00241002102024002400240024002400240024002400240024002400240024002400240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0120032802d00221020b0240024002400240024002400240024020022011470d00200341d0026a10930120032802dc022218450d0120032903e002211e41082116200341f8036a41086a22024200370300200342003703f803419896c0004118200341f8036a1001200341b0026a41086a2002290300370300200320032903f8033703b00241002112200341b0026a411041d889c200410041001000417f460d02200342103702fc032003200341b0026a3602f80320034188026a200341f8036a1068200328028802450d07200328028c022217ad221f421c88a70d0b201f420486a72202417f4c0d0b2002450d032002101b22160d0420024108101c000b41c9bbc00021054111210a20044102470d220c210b419cbbc0002105412d210a20044102470d210c200b4108212e410021020c020b410821160b024002402017450d00200341f8036a41086a280200211320032802fc03211920032802f8032114410021154100210a41002105201721120340200342003703d802200342003703d002410020142019200341d0026a41102013100022022002417f461b2202411020024110491b20136a21132002410f4d0d04200541016a2102200341d0026a41086a290300211f20032903d0022132024020052012470d002015200220022015491b2212ad4204862233422088a70d1b2033a722114100480d1b02402005450d002016200a2011101a22160d010c090b2011101b2216450d080b2016200a6a2205201f37030820052032370300201541026a2115200a41106a210a2002210520022017490d000b20034180046a201336020020160d010c040b41002102410021122016450d030b2016212e0b200341f8036a41086a22054200370300200342003703f803418a96c000410e200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b0024100211702400240200341b0026a411041d889c200410041001000417f460d00200342103702fc032003200341b0026a3602f803200341d0026a200341f8036a103a20032802d0022219450d0b200341d8026a280200212f20032802d40221170c010b410121194100212f0b4200211f200341f8036a41086a22054200370300200342003703f80341b5bdc000411c200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b00202400240200341b0026a411041d889c200410041001000417f460d00200342003703d802200342003703d002200341b0026a4110200341d0026a4110410010002205417f460d082005410f4d0d08200341d8026a290300211f20032903d00221320c010b420121320b200341e8016a2032201f202fad4200109903200341f8016a200341c0036a10450240024002400240024020032903f80120032903e801223454200341f8016a41086a2903002232200341e8016a41086a290300221f542032201f511b450d00418bbcc0002105412e210a20170d010c020b200341f8036a41086a22054200370300200342003703f80341c296c0004113200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b0020240024002400240200341b0026a411041d889c200410041001000417f460d00200342103702fc032003200341b0026a3602f803200341d0026a200341f8036a10950120032802d0022213450d12200341d0026a41086a2802002215450d1320032802d402211441b9bcc00021054123210a2013290300201054201341086a2903002232200f542032200f511b450d0341082135200341f8036a41086a22054200370300200342003703f803419993c0004115200341f8036a1001200341b0026a41086a2005290300370300200320032903f8033703b00241002136200341b0026a411041d889c200410041001000417f460d01200342103702fc032003200341b0026a3602f803200341d0026a200341f8036a105620032802d0022235450d14200341d8026a280200213720032802d40221360c020b41dabbc00021054131210a20170d030c040b410021370b2035203741286c6a2131203521054100211102400240024002400340203120056b419f014d0d01200520034198046a460d022011200520034198046a412010970322304100476a21112030450d02200541286a223020034198046a460d022011203020034198046a412010970322304100476a21112030450d02200541d0006a223020034198046a460d022011203020034198046a412010970322304100476a21112030450d02200541f8006a223020034198046a460d02200541a0016a21052011203020034198046a412010970322304100476a211120300d000c020b0b20312005460d012035203741286c6a2131034020034198046a2005460d012011200520034198046a412010970322304100476a21112030450d012031200541286a2205470d000c020b0b2011201e422088a74f0d010b02402036450d00203510190b200341d0026a20034198046a1097014192bdc000210520032802d0024101470d01200241ffffffff00712202202f41ffffff3f712205200520024b1b2230450d04200341d8026a280200213520032802d4022131201921054100210a420021384200213903404114101b2202450d0e200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d0f200220052900003700142002412c6a200541186a290000370000200241246a200541106a2900003700002002411c6a200541086a290000370000200341f8036a41086a22114200370300200342003703f80320024134200341f8036a1001200341b0026a41086a2011290300370300200320032903f8033703b002024002400240200341b0026a411041d889c200410041001000417f460d00200341003602d002200341b0026a4110200341d0026a41044100100041016a41044d0d0e20032802d002212f41002111200a41016a210a20021019202f20314f0d010c020b41012111200a41016a210a2002101941002031490d010b20110d00200341d0026a200510a70142002132420021330240200341d0026a41086a28020020354d0d00202e41086a290300420020032802d00220356a2d000022021b2133202e290300420020021b21320b024020032802d402450d0020032802d00210190b203320397c203220387c2238203254ad7c21390b200541206a2105202e41106a212e200a2030490d000c060b0b41dcbcc00021054136210a2036450d00203510190b02402014450d00201310190b2017450d010b201910190b02402012450d00201610190b201ea7450d122018101920044102470d1f0c1e0b42002138420021390b2013201541306c6a210a2013210202400240024002400340200a20026b41bf014d0d01200241106a220520034198046a460d02200520034198046a4120109703450d02200241c0006a220520034198046a460d02200520034198046a4120109703450d02200241f0006a220520034198046a460d02200520034198046a4120109703450d02200241a0016a220520034198046a460d02200241c0016a2102200520034198046a41201097030d000c020b0b02402002200a460d000340200241106a220220034198046a460d02200220034198046a4120109703450d02200241206a2202200a470d000b0b20382010852039200f85844200520d0120034198046a41086a290300211f20034198046a41106a290300213220034198046a41186a290300213320032903980421342013200f37030820132010370300200341d0026a41186a2033370300200341d0026a41106a2032370300200341d0026a41086a201f37030020132034370310201341186a201f370300201341206a2032370300201341286a2033370300200320343703d002201541144b0d024101213a201541014d0d1a417f213b2015417f6a213c4130213d2013201541306c6a213e4102213f41082140411021414128214241182143412021444103214541e80021464150214741782148417021494168214a4160214b4158214c4138214d410121020c180b200341b8016a200341c0036a2034201f10a9014116210a41d1bdc00021052014450d110c100b200341d0016a200341c0036a2034201f10a901410f210a41e7bdc000210520140d0f0c100b2015410176224ead42307e2223422088a70d052023a72202417f4c0d0541082107024002402002450d002002101b224f450d0f204f21500c010b4108214f410821500b4150210e201341506a215141302108201341306a2152201341f07e6a21534100215441042155417f21564101215742032124422021234103215841022159417d215a4158215b4128210d4120210c411821064110210b417e215c4174215d4164215e41a87f215f41a07f21604109216141e80021624178216341702164416821654160216641382167410a2168410421694100216a4100216b2015216c410221020c150b20034180046a20133602002012450d00201610190b41fcf9c00041331030000b41fcf9c00041331030000b20114108101c000b41fcf9c00041331030000b102b000b41fcf9c00041331030000b41144101101c000b41344101101c000b41fcf9c00041331030000b41fcf9c00041331030000b4198b4c20041004100104a000b41fcf9c00041331030000b20024108101c000b201310190b02402017450d00201910190b02402012450d00201610190b201ea7450d002018101920044102470d0d0c0c0b20044102470d0c0c0b0b20032802980410190b20020d00410121024115210a41bde3c10021050c010b20034198046a41026a20034190046a41026a2d00003a0000200341d0026a41086a200341f8036a41086a290300370300200341d0026a410d6a200341f8036a410d6a290000370000200320032f0190043b019804200320032903f8033703d002410021020b200341cc026a41026a221a20034198046a41026a2d00003a0000200341b0026a41086a2209200341d0026a41086a290300370300200341b0026a41106a200341d0026a41106a290300370300200320032f0198043b01cc02200320032903d0023703b00220020d08200341d3036a2009290300370000200341d8036a200341bd026a290000370000200320032f01cc023b01c0032003200a3600c703200320053600c303200320032903b0023700cb032003201a2d00003a00c203200341f8036a41086a22024200370300200342003703f803419993c0004115200341f8036a100120092002290300370300200320032903f8033703b0024100211d02400240024002400240024002400240200341b0026a411041d889c200410041001000417f460d002003421037029c042003200341b0026a36029804200341d0026a20034198046a105620032802d002221a450d0620032802d402211d4128210a200341d8026a280200221c41286c22090d010c020b4108211a4100211c4128210a410041286c2209450d010b410021050340200341d0026a41206a201a20056a220241206a290300370300200341d0026a41186a200241186a290300370300200341d0026a41106a200241106a290300370300200341d0026a41086a200241086a290300370300200320022903003703d002200341d0026a200341c0036a41201097030d0220092005200a6a2205470d000b0b4100212041082121201d450d01201a1019410021220c090b20034198046a41206a220a200341d0026a41206a29030037030020034198046a41186a2209200341d0026a41186a29030037030020034198046a41106a221b200341d0026a41106a29030037030020034198046a41086a2225200341d0026a41086a290300370300200320032903d002370398044128101b2221450d032021200329039804370300202141206a200a290300370300202141186a2009290300370300202141106a201b290300370300202141086a2025290300370300201c41286c41586a2005460d01200241286a212641282127201a201c41286c6a222841586a21294101212a41202109411821254110211b4108211c4228212b4220212c4100212d4101212241012120410021020c040b410021220c070b41012122410121200c050b41fcf9c00041331030000b41284108101c000b02400340024002400240024002400240024002400240024002400240024002400240024002400240024020020e03000102020b2026210202400340200341d0026a20096a2205200220096a290300370300200341d0026a20256a220a200220256a290300370300200341d0026a201b6a22112002201b6a290300370300200341d0026a201c6a222e2002201c6a290300370300200320022903003703d002200341d0026a200341c0036a20091097030d012028200220276a2202470d000c180b0b20034198046a20096a2226200529030037030020034198046a20256a222f200a29030037030020034198046a201b6a2230201129030037030020034198046a201c6a2231202e290300370300200320032903d0023703980420052026290300370300200a202f29030037030020112030290300370300202e203129030037030020032003290398043703d002024020202022470d002022202a6a22202022490d152022202a742226202020202026491b2220ad202b7e220f202c88a70d15200fa72226202d480d1502402022450d002021202220276c2026101a22210d010c040b2026101b2221450d030b200220276a21262021202220276c6a222f20032903d002370300202f20096a2005290300370300202f20256a200a290300370300202f201b6a2011290300370300202f201c6a202e2903003703002022202a6a212220292002470d070c160b2015203c2202203b6a223c490d0202402015203c6b220a203f490d0020132002203d6c6a22022903002013203c203d6c6a2205290300221f5a200220406a22112903002210200520406a222e290300220f5a2010200f511b0d0020052002290300370300202e201129030037030020052903102110200520416a200220416a290300370300200341d0026a20436a2230200520426a2211290300370300200341d0026a20416a2231200520446a222e290300370300200341d0026a20406a2235200520436a222f290300370300202f200220436a290300370300202e200220446a2903003703002011200220426a290300370300200320103703d002410121110240200a2045490d002005290360201f5a200520466a2903002210200f5a2010200f511b0d0041032111203e212e02400340202e220220476a2002290300370300200220486a200220426a290300370300200220496a200220446a2903003703002002204a6a200220436a2903003703002002204b6a200220416a2903003703002002204c6a200220406a2903003703002011222f200a4f0d01202f203a6a21112002203d6a222e290300201f5a2002204d6a2903002210200f5a2010200f511b450d000b0b202f203b6a21110b2002201f3703002002200f37030820052011203d6c6a220220426a2030290300370300200220446a2031290300370300200220436a2035290300370300200220032903d0023703100b203e20476a213e203c0d070c140b206c216d4100216c4101216e206d20566a2230450d0702400240024002400240024002402013203020086c6a22022903002013206d20086c222e6a220520606a290300221054200220076a290300221f2005205f6a290300220f54201f200f511b450d002053202e6a2102034020302057460d02201020022903002232542105200f200220076a290300221f51210a200f201f5421112002200e6a2102203020566a213020322110201f210f20052011200a1b0d000c030b0b206d205c6a212f2053202e6a21024100216c410021050340202f2005460d052010200229030022325a210a200f200220076a290300221f512111200f201f5a212e2002200e6a2102200520576a210520322110201f210f200a202e20111b0d000b200520576a216e206d20056b20566a22300d030c020b410021300b206d2030490d06206d20154b0d080240206d20306b226e205776220a450d002051202e6a21022013203020086c6a21050340200341d0026a200d6a22112005200d6a222e290300370300200341d0026a200c6a222f2005200c6a2231290300370300200341d0026a20066a2235200520066a2236290300370300200341d0026a200b6a22372005200b6a226f290300370300200341d0026a20076a2270200520076a2271290300370300200320052903003703d002200220076a2272290300210f2002200b6a22732903002110200220066a2274290300211f2002200c6a2275290300213220022903002133202e2002200d6a2276290300370300203120323703002036201f370300206f20103703002071200f37030020052033370300207620112903003703002075202f290300370300207420352903003703002073203729030037030020722070290300370300200220032903d002370300200520086a21052002200e6a2102200a20566a220a0d000b0b20300d010b2030216c206a206b460d0f0c100b206e20614b0d01206d20154b0d052052203020086c6a2177410021780c100b206d216e206a206b460d090c0a0b2030216c206a206b470d0b0c0a0b20264108101c000b203c20151027000b2030206d1027000b206d2030417f6a226c490d0d0b206d20151028000b410021020c0a0b410121020c090b410021020c070b410121020c060b410221020c050b410121020c040b410221020c030b410121020c020b410221020c010b410321020b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e0400010204040b206a206b470d10410121020c140b206a20576a2202206a490d16206a2057742205200220022005491b2202ad202486220f202388a70d16200fa722052054480d1602400240206a450d002069206a2058742005101a22690d010c030b2005101b2269450d020b2002216a410221020c130b2069206b2058746a2202206e3602042002206c360200206b20576a2279216b20792059490d02410121780c110b20054104101c000b0240024020780e020001010b206d203020566a226c490d130240206d206c6b226e2059490d002013203020086c6a22022903002013206c20086c6a2205290300221f5a200220076a220a2903002210200520076a2211290300220f5a2010200f511b0d00200520022903003703002011200a290300370300200529031021102005200b6a2002200b6a290300370300200341d0026a20066a222f2005200d6a220a290300370300200341d0026a200b6a22312005200c6a2211290300370300200341d0026a20076a2235200520066a222e290300370300202e200220066a29030037030020112002200c6a290300370300200a2002200d6a290300370300200320103703d0024101210a0240206e2058490d002005290360201f5a200520626a2903002210200f5a2010200f511b0d004103210a207721110240034020112202200e6a2002290300370300200220636a2002200d6a290300370300200220646a2002200c6a290300370300200220656a200220066a290300370300200220666a2002200b6a2903003703002002205b6a200220076a290300370300200a222e206e4f0d01202e20576a210a200220086a2211290300201f5a200220676a2903002210200f5a2010200f511b450d000b0b202e20566a210a0b2002201f3703002002200f3703082005200a20086c6a2202200d6a202f2903003703002002200c6a2031290300370300200220066a2035290300370300200220032903d0023703100b206c450d0c2077200e6a2177206c2130206e2068490d0a410021020c110b024002400240024020692079223520566a22792058746a2202280200450d00206920352058746a222e205d6a2802002211200228020422054d0d004102216b203541024d0d0420692035205a6a22022058746a280204220a200520116a4d0d014103216b203541034d0d04202e205e6a280200200a20116a4d0d010c050b20352058490d012002280204210520692035205a6a22022058746a280204210a0b200a2005490d010b2035205c6a21020b2035200220576a22714d0d03203520024d0d04206920022058746a2237280204227220372802006a2202206920712058746a226f2802002270490d05200220154b0d06203720556a21732013207020086c6a2231206f280204223620086c22056a216b200220086c210a02400240024002400240200220706b222e20366b220220364f0d00204f206b200220086c22051095031a205020056a211120362057480d0120022057480d012051200a6a210a206b21020340200a2002200e6a226b2011200e6a222e202e290300206b290300542011205b6a290300220f2002205b6a290300221054200f2010511b222f1b2205290300370300200a200d6a2005200d6a290300370300200a200c6a2005200c6a290300370300200a20066a200520066a290300370300200a200b6a2005200b6a290300370300200a20076a200520076a2903003703002011202e202f1b21112031206b2002202f1b22024f0d04200a200e6a210a2050210520502011490d000c050b0b204f203120051095031a205020056a211120362057480d01202e20364c0d012013200a6a212f205021052031210203402002206b2005206b290300200529030054206b20076a290300220f200520076a290300221054200f2010511b222e1b220a2903003703002002200d6a200a200d6a2903003703002002200c6a200a200c6a290300370300200220066a200a20066a2903003703002002200b6a200a200b6a290300370300200220076a200a20076a2903003703002005200520086a202e1b2105200220086a2102206b20086a206b202e1b226b202f4f0d04201120054b0d000c040b0b206b21020c010b203121020b205021050b20022005201120056b220a200a2008706b1095031a2073207220366a36020020372070360200206f206f20076a207120567320356a2058741096031a2079216b207920574b0d0a0b206c0d060c010b2035216b206c0d060b0240206a450d00206910190b204e450d11204f10190c110b41c4edc20020712035104a000b41c4edc20020022035104a000b207020021027000b200220151028000b410221020c090b410221020c080b410021780c030b410121780c030b410021020c040b410221020c030b410321020c020b410321020c010b410321020c000b0b0b206c206d1027000b101d000b200320153602d802200320143602d402200320133602d002200341133602b402200341c296c0003602b002200341d0026a200341b0026a10940102402014450d00201310190b02402017450d00201910190b02402012450d00201610190b410021050240201ea7450d00201810190b20044102470d050c040b201d450d00201a10190b200320223602d802200320203602d402200320213602d0022003411536029c042003419993c00036029804200341d0026a20034198046a1096012020450d00202110190b410021050b0c010b200141086a280200450d00200128020410190b2000200a36020420002005360200200341c0046a24000bf60402037f037e230041206b22032400024002400240024002402002280208220420014d0d0020022802002105200241086a2004417f6a2204360200200341106a41086a2004360200200520044105746a220429000021062004290008210720042900102108200520014105746a220141186a200441186a290000370000200120083700102001200737000820012006370000200320022902003703102003410e3602042003418a96c000360200200341106a200310980102402003280214450d00200328021010190b4113101b2202450d012002410f6a41002800b3b740360000200241086a41002900acb740370000200241002900a4b740370000200241134133101a2202450d02200220002900003700132002412b6a200041186a290000370000200241236a200041106a2900003700002002411b6a200041086a290000370000200341106a41086a220442003703002003420037031020024133200341106a1001200341086a200429030037030020032003290310370300200341101002200210194114101b2202450d03200241106a410028008eb740360000200241086a4100290086b740370000200241002900feb640370000200241144134101a2202450d04200220002900003700142002412c6a200041186a290000370000200241246a200041106a2900003700002002411c6a200041086a290000370000200341106a41086a220042003703002003420037031020024134200341106a1001200341086a20002903003703002003200329031037030020034110100220021019200341206a24000f0b41c0b4c20020012004104a000b41134101101c000b41334101101c000b41144101101c000b41344101101c000be30604027f017e027f017e230041206b220124000240024002400240410f101b2202450d00200241076a41002900fdbd40370000200241002900f6bd403700002002410f412f101a2202450d012002200029000037000f200241276a200041186a2900003700002002411f6a200041106a290000370000200241176a200041086a29000037000042002103200141106a41086a22044200370300200142003703102002412f200141106a1001200141086a220520042903003703002001200129031037030042002106024002400240024002402001411041d889c200410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d01200129031021060b200210192004420037030020014200370310419c82c000410d200141106a1001200520042903003703002001200129031037030002402001411041d889c200410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d02200129031021030b41f598c1002102024020062003560d004111101b2202450d07200241106a41002d00eb99413a0000200241086a41002900e39941370000200241002900db9941370000200241114131101a2202450d0820022000290000370011200241296a200041186a290000370000200241216a200041106a290000370000200241196a200041086a29000037000042002103200141106a41086a220042003703002001420037031020024131200141106a1001200141086a2000290300370300200120012903103703004200210602402001411041d889c200410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d04200129031021060b20021019200141106a41086a2200420037030020014200370310419c82c000410d200141106a1001200141086a20002903003703002001200129031037030002402001411041d889c200410041001000417f460d002001420037031020014110200141106a41084100100041016a41084d0d05200129031021030b41f598c100410020062003561b21020b200141206a240020020f0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b410f4101101c000b412f4101101c000b41114101101c000b41314101101c000bcc0201027f230041306b220224000240024002404113101b2203450d002003410f6a41002800b3b740360000200341086a41002900acb740370000200341002900a4b740370000200341134133101a2203450d01200320012900003700132003412b6a200141186a290000370000200341236a200141106a2900003700002003411b6a200141086a290000370000200241206a41086a220142003703002002420037032020034133200241206a1001200241086a200129030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a10aa0120022802202201450d0420002002290224370204200020013602000c010b20004100360208200042013702000b20031019200241306a24000f0b41134101101c000b41334101101c000b41fcf9c00041331030000bc90304017f027e027f057e230041c0006b22042400200420011044200120042903002205200220052005200256200441086a2903002206200356200620035122071b22081b22097d20062003200620081b220a7d2005200954ad7d10474200210b200441306a41086a220142003703002004420037033041a7fbc0004116200441306a1001200441206a41086a200129030037030020042004290330370320024002400240200441206a411041d889c200410041001000417f460d002004420037033820044200370330200441206a4110200441306a4110410010002201417f460d022001410f4d0d02200441386a290300210c2004290330210b0c010b4200210c0b0240200b20097d220d200b56200c200a7d200b200954ad7d220b200c56200b200c511b0d002004200d3703102004200b370318200441306a41086a220142003703002004420037033041a7fbc0004116200441306a1001200441206a41086a200129030037030020042004290330370320200441206a4110200441106a411010030b2000200220097d370308200041106a2003200a7d2002200954ad7d37030020002005200254200620035420071bad370300200441c0006a24000f0b41fcf9c00041331030000b8f0404017f027e027f057e230041e0006b22042400200441206a20011045200120042903202205200220052005200256200441206a41086a2903002206200356200620035122071b22081b22097d20062003200620081b220a7d2005200954ad7d10464200210b200441d0006a41086a220842003703002004420037035041a7fbc0004116200441d0006a1001200441c0006a41086a200829030037030020042004290350370340024002400240200441c0006a411041d889c200410041001000417f460d002004420037035820044200370350200441c0006a4110200441d0006a4110410010002208417f460d022008410f4d0d02200441d8006a290300210c2004290350210b0c010b4200210c0b0240200b20097d220d200b56200c200a7d200b200954ad7d220b200c56200b200c511b0d002004200d3703302004200b370338200441d0006a41086a220842003703002004420037035041a7fbc0004116200441d0006a1001200441c0006a41086a200829030037030020042004290350370340200441c0006a4110200441306a411010030b02400240200520025a200620035a20071b0d00200441086a2001200220097d2003200a7d2002200954ad7d10a801200441186a290300210320042903102102200429030821050c010b420021050b2000200237030820002005370300200041106a2003370300200441e0006a24000f0b41fcf9c00041331030000bf702010a7f230041106b22022400200220011068024002400240024002400240024002402002280200450d0020022802042203417f4c0d062003450d012003101b2204450d07200141046a2105200141086a21064100210741002108200321090340200241003a000f200128020020052802002002410f6a410120062802001000210a20062006280200200a41016a220a41014b6a360200200a4102490d04200841016a210a20022d000f210b024020082009470d002007200a200a2007491b22094100480d0602402008450d00200420082009101a22040d010c080b2009101b2204450d070b200420086a200b3a0000200741026a2107200a2108200a2003490d000c030b0b20004100360200200241106a24000f0b410121044100210a410021090b2000200936020420002004360200200041086a200a360200200241106a24000f0b2000410036020002402009450d00200410190b200241106a24000f0b101d000b20094101101c000b102b000b20034101101c000b13002000410b360204200041c0ccc2003602000bcb0201027f230041306b220224000240024002404115101b2203450d002003410d6a4100290092be40370000200341086a410029008dbe4037000020034100290085be40370000200341154135101a2203450d01200320012900003700152003412d6a200141186a290000370000200341256a200141106a2900003700002003411d6a200141086a290000370000200241206a41086a220142003703002002420037032020034135200241206a1001200241086a200129030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a103a20022802202201450d0420002002290224370204200020013602000c010b20004100360208200042013702000b20031019200241306a24000f0b41154101101c000b41354101101c000b41fcf9c00041331030000b130020004107360204200041d7c8c0003602000bda0201027f230041306b22022400024002400240411c101b2203450d00200341186a41002800fdcb40360000200341106a41002900f5cb40370000200341086a41002900edcb40370000200341002900e5cb403700002003411c413c101a2203450d012003200129000037001c200341346a200141186a2900003700002003412c6a200141106a290000370000200341246a200141086a290000370000200241206a41086a22014200370300200242003703202003413c200241206a1001200241086a200129030037030020022002290320370300024002402002411041d889c200410041001000417f460d002002421037021420022002360210200241206a200241106a103a20022802202201450d0420002002290224370204200020013602000c010b20004100360208200042013702000b20031019200241306a24000f0b411c4101101c000b413c4101101c000b41fcf9c00041331030000bce0a02057f037e230041306b22022400200241106a41086a220342003703002002420037031041e2c9c0004112200241106a1001200241206a41086a20032903003703002002200229031037032002400240024002400240024002400240200241206a411041d889c200410041001000417f460d00200242103702042002200241206a360200200241106a2002103a20022802102203450d02200228021421040240200320014105746a2205450d00200241186a280200220620014d0d0020002005460d02200520004120109703450d020b02402004450d00200310190b200241306a240041d8cbc0000f0b200241306a240041d8cbc0000f0b20032006417f6a22064105746a220529000021072005290008210820052900102109200320014105746a220141186a200541186a29000037000020012009370010200120083700082001200737000020022006360228200220043602242002200336022020024112360214200241e2c9c000360210200241206a200241106a10980102402004450d00200310190b411c101b2201450d01200141186a41002800a9ca40360000200141106a41002900a1ca40370000200141086a4100290099ca4037000020014100290091ca403700002001411c413c101a2201450d022001200029000037001c200141346a200041186a2900003700002001412c6a200041106a290000370000200141246a200041086a290000370000200241106a41086a22034200370300200242003703102001413c200241106a1001200241206a41086a200329030037030020022002290310370320200241206a41101002200110194112101b2201450d03200141106a41002f0082c9403b0000200141086a41002900fac840370000200141002900f2c840370000200141124132101a2201450d04200120002900003700122001412a6a200041186a290000370000200141226a200041106a2900003700002001411a6a200041086a290000370000200241106a41086a220342003703002002420037031020014132200241106a1001200241206a41086a2204200329030037030020022002290310370320200241206a41101002200110192003420037030020024200370310419c82c000410d200241106a1001200420032903003703002002200229031037032042002107024002400240200241206a411041d889c200410041001000417f460d0020024200370310200241206a4110200241106a41084100100041016a41084d0d01200229031021070b200241106a41086a220142003703002002420037031041c1cbc0004117200241106a1001200241206a41086a20012903003703002002200229031037032002400240200241206a411041d889c200410041001000417f460d0020024200370310200241206a4110200241106a41084100100041016a41084d0d0320022903102108410f2103410f101b2201450d010c090b42e8072108410f2103410f101b22010d080b20034101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b411c4101101c000b413c4101101c000b41124101101c000b41324101101c000b200141076a41002900fdbd40370000200141002900f6bd40370000024020012003412f101a2201450d002001200029000037000f200141276a200041186a2900003700002001411f6a200041106a290000370000200141176a200041086a2900003700002002200820077c370300200241106a41086a22004200370300200242003703102001412f200241106a1001200241206a41086a200029030037030020022002290310370320200241206a411020024108100320011019200241306a240041000f0b412f4101101c000b130020004117360204200041ecd2c2003602000b3201017f02404108101b2202450d0020004288808080800137020420002002360200200242003700000f0b41084101101c000b6101017f024002404110101b2202450d002002420037000820024200370000200241104120101a2202450d0120024200370010200042a0808080800437020420002002360200200241186a42003700000f0b41104101101c000b41204101101c000b7101017f230041306b220224002002420037031020024200370308200241033602182002410036022820024201370320200241186a200241206a105d2002200241086a36022c2002412c6a200241206a10b401200041086a200228022836020020002002290320370200200241306a24000b950a03017f027e057f230041e0006b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200028020022002903002203423f56200041086a290300220442005220045022051b0d00200141046a280200200141086a2802002200470d01200041016a22052000490d1120004101742206200520052006491b22064100480d112000450d05200128020020002006101a2205450d060c190b20034280800154410020051b450d01200141046a2802002205200141086a28020022006b41024f0d02200041026a22062000490d1020054101742200200620062000491b22004100480d102005450d08200128020020052000101a2205450d090c160b200128020021050c180b200342808080800454410020051b450d01200141046a2802002205200141086a28020022006b41044f0d04200041046a22062000490d0e20054101742200200620062000491b22004100480d0e2005450d08200128020020052000101a22050d090c120b200128020021050c140b411020047920037942c0007c20044200521ba74103766b22074104490d0e200141046a280200200141086a2802002206470d03200641016a22052006490d0c20064101742208200520052008491b22054100480d0c2006450d09200128020020062005101a22080d0a0c110b2006101b22050d130b20064101101c000b200128020021050c050b200128020021080c070b2000101b22050d0d0b20004101101c000b2000101b2205450d090b20012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a7410274410272360000200241e0006a24000f0b2005101b2208450d070b20012008360200200141046a2005360200200141086a28020021060b200141086a2205200641016a360200200820066a200741027441736a3a0000200029030021032002200041086a290300220437030820022003370300200141046a210803400240024002400240200828020020052802002200470d00200041016a22062000490d0520004101742209200620062009491b22094100480d052000450d01200128020020002009101a22060d020c060b200128020021060c020b2009101b2206450d040b2001200636020020082009360200200528020021000b2005200041016a360200200620006a2003a73a000020034208882004423886842103200442088821042007417f6a22070d000b200220033703002002200437030820022002360210200241a0c1c100360214200320048450450d03200241e0006a24000f0b101d000b20094101101c000b4198afc3001029000b200241c8006a41146a4100360200200241306a41146a41043602002002413c6a4108360200200241186a41146a4103360200200241d889c2003602582002420137024c20024180afc300360248200241083602342002420337021c200241fcd7c3003602182002200241c8006a3602402002200241146a3602382002200241106a3602302002200241306a360228200241186a41b0afc30010f201000b20004101101c000b20054101101c000b20012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b0000200241e0006a24000f0b20012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a0000200241e0006a24000b3301017f02404108101b2202450d0020004288808080800137020420002002360200200242e8073700000f0b41084101101c000b3401017f02404104101b2202450d0020004284808080c00037020420002002360200200241c0843d3600000f0b41044101101c000b3201017f02404104101b2202450d0020004284808080c000370204200020023602002002413c3600000f0b41044101101c000b3201017f02404104101b2202450d0020004284808080c00037020420002002360200200241043600000f0b41044101101c000ba10603027f017e027f230041206b220224000240024020012d0000417e6a2203410a4b0d0002400240024002400240024002400240024002400240024002400240024020030e0b000603040107080509020a000b200041023a0000200241206a24000f0b200041063a0000200041106a200141106a290300370300200041086a200141086a290300370300200041186a200141186a280200360200200041046a200141046a280200360200200241206a24000f0b2000410b3a0000200041046a200141046a280200360200200241206a24000f0b41012103200141046a2d00004101470d07200141086a28020021010c080b200041053a0000200041046a200141046a280200360200200241206a24000f0b200041093a0000200041046a200141046a280200360200200241206a24000f0b200041033a0000200041046a200141046a280200360200200241206a24000f0b200041073a0000200041086a200141086a290300370300200241206a24000f0b200041083a0000200041086a200141086a290300370300200241206a24000f0b2000410a3a0000200020012d00014100473a0001200241206a24000f0b2001410c6a2802002203ad2204421b88a70d052004420586a72205417f4c0d05200141046a28020021062005450d022005101b22010d0320054101101c000b2002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002101410021030b200041043a0000200041056a20022f011c3b0000200041046a20033a0000200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a280200360200200241206a24000f0b410121010b20012006200341057410950321012000410c6a2003360200200041086a2003360200200041046a20013602002000410c3a0000200241206a24000f0b41a0e3c2001029000b102b000bf30103017f017e017f230041c0006b2203240042002104200341306a41086a220542003703002003420037033020012002200341306a1001200341206a41086a20052903003703002003200329033037032002400240200341206a411041d889c200410041001000417f460d00200342103702342003200341206a360230200341186a200341306a10682003280218450d01200328021c21012003200341306a10f6012003290300a7450d01200341106a290300210420002003290308370308200041186a2001360200200041106a2004370300420121040b20002004370300200341c0006a24000f0b41fcf9c00041331030000bcb0302017f037e230041e0006b22032400200341206a20001045200341206a41086a290300210420032903202105200341106a2000104442002106024002402003290310420020057d85200341106a41086a290300420020047d2005420052ad7d8584500d0020032000104520002003290300220520017c2204200341086a29030020027c2004200554ad7c1046200341d0006a41086a220042003703002003420037035041a7fbc0004116200341d0006a1001200341c0006a41086a20002903003703002003200329035037034002400240200341c0006a411041d889c200410041001000417f460d002003420037035820034200370350200341c0006a4110200341d0006a4110410010002200417f460d032000410f4d0d03200341d8006a2903002105200329035021060c010b420021050b200620017c22012006542200200520027c2000ad7c220620055420062005511b0d002003200137033020032006370338200341d0006a41086a220042003703002003420037035041a7fbc0004116200341d0006a1001200341c0006a41086a200029030037030020032003290350370340200341c0006a4110200341306a411010030b200341e0006a24000f0b41fcf9c00041331030000b902f09247f047e0f7f017e087f027e107f027e1a7f230041d0026b2204240002400240024020014115490d0041012105410221064103210741322108413021094108210a4158210b4150210c417f210d4138210e410b210f4128211041202111411821124110211341afe000211441807f2115410021164160211741682118417021194178211a41c000211b41c800211c41d000211d41d800211e4101211f41012120410021210c010b410021230c010b410121230b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024020230e020001010b20014102490d0c41a07f2158200041a07f6a21594101215a4100215b4130215c4108215d4158215e4150215f417f21604128216141182162412021634110216441a87f2165418801216641d8002167418001216841d000216941f800216a41c800216b41f000216c41c000216d41e800216e4138216f41e000217041012171410121210c010b02400240024020210e03000d01010b201f20207121220c010b2049204c20096c6a212302400340204b204c200d6a224c4f0d012023290300212a2023200a6a21252023200c6a22242123202a2045542025290300222a204454202a2044511b0d000c100b0b2000204537030020002044370308203d2046290300370300203f204729030037030020412048290300370300200020042903003703102001204b20056a2223490d082000202320096c6a2100200120236b22014115490d020b2003450d090240201f2005710d002000200110ed012003200d6a21030b2001200676222320076c21242023200574212541002126024020012008490d00200620052000202320096c6a2227200c6a290300222820272903002229542027200b6a290300222a2027200a6a290300222b54202a202b511b222c1b202c20282029202c1b2228202720096a290300222954202a202b202c1b222a2027200e6a290300222b54202a202b511b222d1b200020232023200d6a222e202c1b222f20096c6a222729030020292028202d1b542027200a6a2903002228202b202a202d1b222a542028202a511b22306a2000202520096c6a2227200c6a290300222820272903002229542027200b6a290300222a2027200a6a290300222b54202a202b511b22316a2028202920311b222820002025200572223220096c6a2227290300222954202a202b20311b222a2027200a6a290300222b54202a202b511b22336a200020252025200d6a223420311b223520096c6a22272903002029202820331b542027200a6a2903002228202b202a20331b222a542028202a511b22366a2000202420096c6a2227200c6a290300222820272903002229542027200b6a290300222a2027200a6a290300222b54202a202b511b22376a2028202920371b2228202720096a290300222954202a202b20371b222a2027200e6a290300222b54202a202b511b22276a200020242024200d6a223820371b223920096c6a22262903002029202820271b542026200a6a2903002228202b202a20271b222a542028202a511b223a6a21262039202420056a2038202420371b20271b203a1b2124203520322034202520311b20331b20361b2125202f202320056a202e2023202c1b202d1b20301b21230b20262000202320096c6a222729030022282000202520096c6a222c2903002229542027200a6a290300222a202c200a6a290300222b54202a202b511b22276a2028202920271b22282000202420096c6a222c290300222954202a202b20271b222a202c200a6a290300222b54202a202b511b222c6a212602400240024020002025202320271b223920096c6a223129030020292028202c1b5a2031200a6a2903002228202b202a202c1b222a5a2028202a511b0d00202620056a2226200f4b0d0120264521230c020b20242023202520271b202c1b213920264521230c010b024020012005762224450d002000200120096c6a200c6a2123200021250340200441a0026a20106a2227202520106a222c290300370300200441a0026a20116a2226202520116a2231290300370300200441a0026a20126a2237202520126a222d290300370300200441a0026a20136a2233202520136a222e290300370300200441a0026a200a6a222f2025200a6a2230290300370300200420252903003703a0022023200a6a2232290300212a202320136a2234290300212b202320126a22352903002128202320116a223629030021292023290300213b202c202320106a223829030037030020312029370300202d2028370300202e202b3703002030202a3703002025203b370300203820272903003703002036202629030037030020352037290300370300203420332903003703002032202f290300370300202320042903a002370300202520096a21252023200c6a21232024200d6a22240d000b0b20012039200d736a2139410121230b02402022200d73202345722005710d002000200110ee010d0c0b024002402002450d00203920014f0d0a2000203920096c6a22232903002002290300542023200a6a2225290300222a2002200a6a290300222b54202a202b511b0d01200441a0026a20106a223c200020106a223d290300370300200441a0026a20116a223e200020116a223f290300370300200441a0026a20126a2240200020126a2241290300370300200441a0026a20136a2242200020136a2224290300370300200441a0026a200a6a22432000200a6a2227290300370300200420002903003703a0022025290300212a202320136a222c2903002144202320126a2226290300212b202320116a2231290300212820232903002145203d202320106a2237290300370300203f20283703002041202b370300202420443703002027202a370300200020453703002037203c2903003703002031203e29030037030020262040290300370300202c204229030037030020252043290300370300202320042903a0023703002027290300214420002903002145200420126a2246203d290300370300200420136a2247203f2903003703002004200a6a22482041290300370300200420242903003703002000200c6a2149200020096a214a4100214b41002001224c200d6a22254f0d040c100b2001450d070b203920014f0d05200441a0026a20106a2234200020106a224d290300370300200441a0026a20116a2235200020116a224e290300370300200441a0026a20126a2236200020126a224f290300370300200441a0026a20136a2238200020136a2250290300370300200441a0026a200a6a221f2000200a6a2251290300370300200420002903003703a0022000203920096c6a2223290300212a2023200a6a2225290300212b202320136a22242903002128202320126a22272903002129202320116a222c290300213b204d202320106a2226290300370300204e203b370300204f2029370300205020283703002051202b3703002000202a37030020262034290300370300202c203529030037030020272036290300370300202420382903003703002025201f290300370300202320042903a0023703002051290300212a2000290300212b200420126a2252204d290300370300200420136a2253204e2903003703002004200a6a2254204f29030037030020042050290300370300200020096a21314100212002402001200d6a2224450d00203121230340202b20232903005a202a2023200a6a29030022285a202a2028511b0d01202320096a2123202020056a22202024490d000b0b2000200120096c6a21232024212502400340202321272025223a20204d0d01203a200d6a2125202b2027200c6a222329030054202a2027200b6a290300222854202a2028511b450d000b0b203a2020490d042024203a490d034180012130410021264100212e4100212c4100213341800121322031202020096c6a225521310340202720316b222320096e21250240024002400240024002400240202320144b22390d00202520156a2025202e2026492033202c4922247222371b21232037450d012032202320241b21322023203020241b21300b2033202c470d020c010b2023202320057622326b21302033202c470d010b2032450d0141002125200441206a2233212c203121230340202c20253a0000202c202b20232903005a202a2023200a6a29030022285a202a2028511b6a212c202320096a21232032202520056a2225470d000b0b202e2026470d020c010b200441206a222c2133202e2026470d010b02402030450d002027200c6a212341002125200441a0016a222e21260340202620253a00002026202b202329030054202a2023200a6a290300222854202a2028511b6a21262023200c6a21232030202520056a2225470d000c020b0b200441a0016a2226212e0b02402026202e6b2223202c20336b2225202520234b1b222f450d002034203120332d000020096c6a222320106a2903003703002035202320116a2903003703002036202320126a2903003703002038202320136a290300370300201f2023200a6a290300370300200420232903003703a002203120332d000020096c6a22232027202e2d0000200d7320096c6a2225290300370300202320106a202520106a290300370300202320116a202520116a290300370300202320126a202520126a290300370300202320136a202520136a2903003703002023200a6a2025200a6a2903003703000240202f2005460d004100212403402027202e20246a22372d0000200d7320096c6a22232031203320246a20056a222d2d000020096c6a2225290300370300202320106a202520106a290300370300202320116a202520116a290300370300202320126a202520126a290300370300202320136a202520136a2903003703002023200a6a2025200a6a2903003703002031202d2d000020096c6a22232027203720056a2d0000200d7320096c6a2225290300370300202320106a202520106a290300370300202320116a202520116a290300370300202320126a202520126a290300370300202320136a202520136a2903003703002023200a6a2025200a6a290300370300202420066a2123202420056a222521242023202f490d000b202e20256a212e203320256a21330b2027202e2d0000200d7320096c6a222320042903a002370300202320106a2034290300370300202320116a2035290300370300202320126a2036290300370300202320136a20382903003703002023200a6a201f290300370300202e20056a212e203320056a21330b2031203220096c6a20312033202c461b21312027201620306b20096c6a2027202e2026461b212720390d000b024002402033202c4f0d00034020342031202c200d6a222c2d000020096c6a222520106a22242903003703002035202520116a22262903003703002036202520126a22372903003703002038202520136a222d290300370300201f2025200a6a222e290300370300200420252903003703a0022027200c6a222329030021282027200b6a222f2903002129202720176a2230290300213b202720186a22322903002156202720196a2239290300215720242027201a6a22272903003703002026205737030020372056370300202d203b370300202e20293703002025202837030020272034290300370300203920352903003703002032203629030037030020302038290300370300202f201f290300370300202320042903a002370300202321272033202c490d000c020b0b20312123202e20264f0d0003402026200d6a22262d000021252034202320106a22242903003703002035202320116a222c2903003703002036202320126a22312903003703002038202320136a2237290300370300201f2023200a6a222d290300370300200420232903003703a00220272025200d7320096c6a222529030021282025200a6a22332903002129202520136a222f290300213b202520126a22302903002156202520116a223229030021572024202520106a2239290300370300202c2057370300203120563703002037203b370300202d202937030020232028370300203920342903003703002032203529030037030020302036290300370300202f20382903003703002033201f290300370300202520042903a002370300202320096a2123202e2026490d000b0b2000202a3703082000202b370300204d2052290300370300204e2053290300370300204f2054290300370300200020042903003703100240024002402001202320556b20096e20206a22254d0d002034204d2903003703002035204e2903003703002036204f29030037030020382050290300370300201f2051290300370300200420002903003703a0022000202520096c6a2223290300212a2023200a6a2224290300212b202320136a22272903002128202320126a222c2903002129202320116a2226290300213b204d202320106a2231290300370300204e203b370300204f2029370300205020283703002051202b3703002000202a3703002031203429030037030020262035290300370300202c2036290300370300202720382903003703002024201f290300370300202320042903a002370300200120256b2224450d0120242025202520244b1b21272001200776212c202320096a21260240024020252024200d6a22014f0d00200020252002200310bc0120232102202621000c010b202620012023200310bc01202521010b2027202c4f211f203a20204d2120200141154f0d02410021230c160b419890c30020252001104a000b41a890c3001029000b41002121410121230c130b410121230c120b410021230c110b41022121410121230c100b203a20241028000b2020203a1027000b419890c30020392001104a000b418890c30041004100104a000b202320011027000b41c090c30020392001104a000b2000200110ef01200441d0026a24000f0b2071205a6a2127024020002071205c6c6a2224205f6a2223290300202429030022285a2024205e6a290300222b2024205d6a2225290300222a5a202b202a511b0d00200420626a2231202420616a222c290300370300200420646a2237202420636a22262903003703002004205d6a222d202420626a2233290300370300200420242903103703002024202329030037030020252023205d6a290300370300202420646a202320646a2903003703002033202320626a2903003703002026202320636a290300370300202c202320616a2903003703002000207120606a222c205c6c6a21260240024002400240202c450d00205b212520592123202420586a29030020285a202420656a290300222b202a5a202b202a511b0d030340202320666a202320676a290300370300202320686a202320696a2903003703002023206a6a2023206b6a2903003703002023206c6a2023206d6a2903003703002023206e6a2023206f6a290300370300202320706a2023205c6a2903003703002025205a460d022023290300212b2023205d6a2124202520606a21252023205f6a2123202b2028542024290300222b202a54202b202a511b0d000c030b0b4100212c0c020b410021250b20002025205c6c6a21262025212c0b202620283703002026202a3703082000202c205c6c6a222320616a2031290300370300202320636a2037290300370300202320626a202d290300370300202320042903003703100b205b205a6a215b2059205c6a21592027217120272001470d010b200441d0026a24000f0b41012121410121230c060b203c204a204b20096c6a222320106a2225290300370300203e202320116a22272903003703002040202320126a222c2903003703002042202320136a222629030037030020432023200a6a2231290300370300200420232903003703a002202420096a2237290300212a2024200e6a222d290300212b2024201b6a223329030021282024201c6a222e29030021292024201d6a222f290300213b20252024201e6a22242903003703002027203b370300202c2029370300202620283703002031202b3703002023202a3703002024203c290300370300202f203e290300370300202e204029030037030020332042290300370300202d2043290300370300203720042903a002370300204b20056a224b204c200d6a22254f0d010b204a204b20096c6a212302400340202329030020455a2023200a6a290300222a20445a202a2044511b450d01202320096a2123204b20056a224b2025490d000b410221210c020b410221210c020b410221210c020b410121230c020b410121230c010b410121230c000b0b9b0b03017f017e087f230041306b220224000240024002400240024002400240024002400240024002402001ad2203421b88a70d002003420586a72204417f4c0d00024002402004450d002004101b22050d0120044101101c000b410121050b20052000200141057422061095032104200220013602102002200136020c200220043602082002411236022c20024181fcc000360228200241086a200241286a109801024002402001450d002004101920064100480d032006101b2207450d04200641606a4105762108410021040340200720046a2205200020046a2209290000370000200541186a200941186a290000370000200541106a200941106a290000370000200541086a200941086a2900003700002006200441206a2204470d000b200841016a21000c010b41002100410121070b2002410636022c200241e481c000360228200241086a41fbd7c100200241286a103b4100210902400240200228020822042002280210220541d889c200410041001000417f460d002002410036022820042005200241286a41044100100041016a41044d0d01200228022821090b0240200228020c450d00200410190b02402009450d002009ad4205862203422088a70d032003a722044100480d032004101b2208450d0541002105200821040340200241086a20051033200441186a200241086a41186a290000370000200441106a200241086a41106a290000370000200441086a200241086a41086a29000037000020042002290008370000200441206a21042009200541016a2205470d000b20092000470d070c060b4101210820092000460d050c060b41fcf9c00041331030000b102b000b101d000b20064101101c000b20044101101c000b024020082007460d002000450d0041002106200821042007210503402004200541201097030d02200441206a2104200541206a2105200641016a22062000490d000b0b2009450d012008101920010d020c030b200241086a41086a220a20093602002002200936020c20022008360208200241086a103f4100210b4100210902402000450d0020004105742100410021092007210503402002410636022c200241e481c000360228200241086a2009200241286a1034200a2802002108200228020821064120101b2204450d0620042005290000370000200441186a200541186a290000370000200441106a200541106a290000370000200441086a200541086a29000037000020062008200441201003200410190240200228020c450d00200610190b200541206a2105200941016a2109200041606a22000d000b0b2002410636022c200241e481c000360228200241086a41fbd7c100200241286a103b0240200228020822042002280210220541d889c200410041001000417f460d002002410036022820042005200241286a41044100100041016a41044d0d062002280228210b0b0240200228020c450d00200410190b0240200b20094d0d00200241106a21082009210403402002410636022c200241e481c000360228200241086a41fbd7c100200241286a103b410021060240200228020822052008280200220041d889c200410041001000417f460d002002410036022820052000200241286a41044100100041016a41044d0d06200228022821060b0240200228020c450d00200510190b200441016a21050240200620044d0d002002410636022c200241e481c000360228200241086a2004200241286a10342002280208220420082802001002200228020c450d00200410190b20052104200b2005470d000b0b2002410636022c200241e481c000360228200241086a41fbd7c100200241286a103b20022802102105200228020821042002200936022820042005200241286a41041003200228020c450d00200410190b2001450d010b200710190b200241306a24000f0b41fcf9c00041331030000b41204101101c000b41fcf9c00041331030000bd60403017f017e0c7f230041d0006b22022400024002400240024002402001450d002001ad42287e2203422088a70d032003a722044100480d032004101b2205450d04200241086a2106200241306a41186a2107200241306a41106a2108200521044100210903402002410e360234200241edd7c10036023020022009200241306a10340240024002402002280200220a2006280200220b41d889c200410041001000417f470d00420021032007420037030020084200370300200241306a41086a420037030020024200370330200941016a210920022802040d010c020b2007420037030020084200370300200241306a41086a220c420037030020024200370330200a200b200241306a412041001000220d417f460d05200d411f4d0d05200241106a41186a220d2007290300370300200241106a41106a220e2008290300370300200241106a41086a220f200c2903003703002002200229033037031020024200370330200a200b200241306a41084120100041016a41084d0d05200229033021032007200d2903003703002008200e290300370300200c200f29030037030020022002290310370330200941016a21092002280204450d010b200a10190b20042002290330370300200441186a2007290300370300200441106a2008290300370300200441086a200241306a41086a290300370300200441206a2003370300200441286a210420012009470d000b200121040c010b41002104410821050b200020043602082000200136020420002005360200200241d0006a24000f0b41fcf9c00041331030000b101d000b20044108101c000be30301047f230041d0006b22022400024002404112101b2203450d00200341106a41002f00f3de403b0000200341086a41002900ebde40370000200341002900e3de40370000200341124132101a2203450d01200320012900003700122003412a6a200141186a290000370000200341226a200141106a2900003700002003411a6a200141086a290000370000200241306a41086a220142003703002002420037033020034132200241306a1001200241206a41086a200129030037030020022002290330370320024002400240200241206a411041d889c200410041001000417f460d00200241306a41186a4200370300200241306a41106a4200370300200241386a420037030020024200370330200241206a4110200241306a4120410010002201417f460d022001411f4d0d02200241186a2201200241306a41186a290300370300200241106a2204200241306a41106a290300370300200241086a2205200241306a41086a29030037030020022002290330370300200041013a000020002002290300370001200041096a2005290300370000200041116a2004290300370000200041196a20012903003700000c010b200041003a00000b20031019200241d0006a24000f0b41fcf9c00041331030000b41124101101c000b41324101101c000bd40101027f230041106b22022400024002404115101b2203450d002003410d6a4100290092be40370000200341086a410029008dbe4037000020034100290085be40370000200341154135101a2203450d01200320002900003700152003412d6a200041186a290000370000200341256a200041106a2900003700002003411d6a200041086a2900003700002002413536020c200220033602082001200241086a109801200310190240200141046a280200450d00200128020010190b200241106a24000f0b41154101101c000b41354101101c000b130020004105360204200041c0e5c2003602000b13002000410d36020420004195e3c0003602000b130020004108360204200041fce7c2003602000b3201017f02404108101b2202450d0020004288808080800137020420002002360200200242033700000f0b41084101101c000bc91c04027f027e047f037e23004190016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d000240024020030e0d002c05080c0a0607040b030901000b200241206a200141086a1073200041013a0000200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a28020022034102460d0b20034103470d2b41012103200141086a2d00004101470d142001410c6a28020021010c150b200141086a2903004202520d2b200041003a0000200041086a4202370300200041106a200141106a29030037030020024190016a24000f0b200141086a280200417e6a220341044b0d2b024020030e05001e1c1d1b000b200141386a2903002104200141306a2903002105410121032001410c6a2d00004101470d25200141106a28020021010c260b200141046a2d000022034102460d094103210620034103470d2b200241f2006a200141076a2d00003a0000200241206a41086a200141186a2900003703002002412d6a2001411d6a2900003700002002200141056a2f00003b01702002200141106a290000370320200141256a2d00004100472107200141286a28020021082001410c6a2800002103200141086a28000021090c0a0b200141086a28020022034102460d0a20034103470d2b410121062001410c6a2d00004101470d13200141106a28020021070c140b200241206a200141086a10a301200041073a0000200041c0006a200241206a41386a290300370300200041386a200241206a41306a290300370300200041306a200241206a41286a290300370300200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141086a2d0000417e6a220341044b0d2a024020030e0500201d1e1c000b41d800101b2203450d3020032001410c6a28020010c501410221010c200b41022103200141086a2d000022064102460d0b4103210320064103460d0a4104210320064104470d2a200141096a2d000041004721010c0c0b200241206a200141086a10c601200041086a200241206a41d0001095031a2000410c3a000020024190016a24000f0b200241206a200141086a10c701200041063a0000200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a2802004102470d28200141106a2802002203417f4c0d29200141086a28020021012003450d052003101b22060d0620034101101c000b200241206a200141086a10b901200041053a0000200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b41d800101b2203450d282003200141086a28020010c801410221060c0a0b200141086a280200210941d800101b2203450d2820032001410c6a28020010c901410221060b200041093a0000200041056a20022f01703b0000200041046a20063a00002000410c6a2003360200200041086a2009360200200041106a2002290320370200200041286a2008360200200041256a20073a0000200041076a200241f2006a2d00003a0000200041186a200241206a41086a2903003702002000411d6a2002412d6a29000037000020024190016a24000f0b410121062001410c6a2d00004101470d0a200141106a28020021070c0b0b410121060b2006200120031095032101200041106a20033602002000410c6a2003360200200041086a2001360200200041046a41023602002000410a3a000020024190016a24000f0b200141106a29030021040c010b200241f4006a2001410e6a2f00003b0100200241206a41086a200141206a290000370300200241206a41106a200141286a2d00003a000020022001410a6a2800003602702002200141186a290000370320200141106a2900002104200141096a2d000021010b200041043a0000200041096a20013a0000200041086a20033a00002000410a6a2002280270360100200041106a2004370300200041186a20022903203703002000410e6a200241f0006a41046a2f01003b0100200041206a200241206a41086a290300370300200041286a200241206a41106a29030037030020024190016a24000f0b200241206a41086a200141186a290000370300200241206a41106a200141206a290000370300200241206a41186a200141286a2d00003a00002002200141106a290000370320200141096a2f00002001410b6a2d00004110747221062001410c6a2800002101410021030b200241f0006a41186a200241206a41186a280200360200200241f0006a41106a200241206a41106a290300370300200241f0006a41086a200241206a41086a2903003703002002200229032037037020032006410874722103410321060b2000410d3a00002000410c6a2001360200200041086a2003360200200041046a2006360200200041106a2002290370370200200041186a200241f0006a41086a290300370200200041206a200241f0006a41106a290300370200200041286a200241f0006a41186a28020036020020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241f0006a41086a290300370300200241086a41106a200241f0006a41106a28020036020020022002290370370308200141c8006a2903002105200141c0006a290300210a200141386a290300210b200141306a290300210c410321010c020b200241286a2001411c6a290000370300200241206a41106a200141246a2800003602002002200141146a290000370320200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241206a41086a290300370300200241086a41106a200241206a41106a28020036020020022002290320370308200141386a290300210b200141306a290300210c410221010b200041033a00002000410f6a20034110763a00002000410d6a20033b0000200041c8006a2005370300200041c0006a200a370300200041386a200b370300200041306a200c370300200041106a20073602002000410c6a20063a0000200041086a2001360200200041146a2002290308370200200041286a20043702002000411c6a200241086a41086a290300370200200041246a200241086a41106a28020036020020024190016a24000f0b2001410c6a28020022034108762106410621010c030b200241206a41106a200141206a2903003703002002200141186a2903003703282002200141106a2802003602202001410c6a28020022034108762106200141286a290300210a410421010c0b0b2001410c6a28020022034108762106410521010c010b2002200141186a2903003703282002200141106a29030037032041032101410021030b0c080b200141106a2903002104410621010c020b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141106a29000021042001410c6a2800002103410421010c030b200141106a2903002104410521010b0c010b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141296a2d00004100472106200141106a29000021042001410c6a2800002103410321010b200041096a20022f01083b0000200041086a20013a0000200041106a20043703002000410c6a2003360200200041186a2002290320370300200041296a20063a00002000412a6a20022801703601002000410b6a2002410a6a2d00003a0000200041206a200241206a41086a290300370300200041286a200241206a41106a2d00003a00002000412e6a200241f4006a2f01003b0100200041083a000020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a31000042208684210a2001410d6a2f00002001410f6a2d0000411074722106200141106a2800002101410021030b2002412c6a200241f8006a290300370200200241346a20024180016a2802003602002002200229037037022420022001360220410221010b2000410b3a0000200041386a2004370300200041306a2005370300200041086a2001360200200041106a2002290320370300200041286a200a3703002000410c6a2006410874200341ff017172360200200041186a200241206a41086a290300370300200041206a200241206a41106a29030037030020024190016a24000f0b10ca01000b41dceec2001029000b41f895c3001029000b41f0fcc2001029000b41d0aec3001029000b41a080c3001029000b41a8e5c2001029000b418880c3001029000b41f4c1c3001029000b102b000b41d8004108101c000b41d8004108101c000b41d8004108101c000ba90803047f037e017f230041306b220224000240024020012d0000417e6a220341034b0d00024002400240024002400240024002400240024020030e0400030102000b200041023a0000200041c0006a200141c0006a280200360200200041386a200141386a290300370300200041306a200141306a290300370300200041286a200141286a290300370300200041206a200141206a290300370300200041186a200141186a290300370300200041106a200141106a290300370300200041086a200141086a290300370300200241306a24000f0b41012104200141046a2d00004101470d02200141086a28020021050c030b200141386a2903002106200141306a2903002107200141c0006a2903002108200241286a200141196a290000370300200241206a200141116a290000370300200241186a200141096a290000370300200220012900013703102001412c6a2802002203417f4c0d08200141246a28020021012003450d032003101b22040d0420034101101c000b2001410c6a2802002203417f4c0d07200141046a2802002104200141106a29030021062003450d042003101b22010d0520034101101c000b2002410e6a200141076a2d00003a0000200241106a41086a200141146a290000370300200241206a2001411c6a290000370300200241286a200141246a2d00003a00002002200141056a2f00003b010c20022001410c6a290000370310200141086a2800002105410021040b200141306a2802002203417f4c0d05200141c0006a2903002106200141386a2903002107200141286a2802002109200141c8006a2903002108024002402003450d002003101b22010d0120034101101c000b410121010b2001200920031095032101200041c0006a2006370300200041386a2007370300200041046a20043a0000200041086a2005360200200041c8006a2008370300200041306a20033602002000412c6a2003360200200041286a2001360200200041056a20022f010c3b0000200041076a2002410e6a2d00003a00002000410c6a2002290310370200200041146a200241106a41086a2903003702002000411c6a200241206a290300370200200041246a200241286a280200360200200041043a0000200241306a24000f0b410121040b2004200120031095032101200041386a2006370300200041306a2007370300200041c0006a20083703002000412c6a2003360200200041286a2003360200200041246a2001360200200041053a000020002002290310370001200041096a200241186a290300370000200041116a200241206a290300370000200041196a200241286a290300370000200241306a24000f0b410121010b20012004200310950321012000410c6a2003360200200041086a2003360200200041046a2001360200200041106a2006370300200041033a0000200241306a24000f0b41e4d4c3001029000b102b000bd70201017f02400240024020012d0000417e6a220241054b0d0002400240024002400240024020020e06000402030105000b41d800101b2202450d062002200141046a280200108b02200041046a2002360200200041106a200141106a290300370300200041086a200141086a290300370300200041023a00000f0b200041046a200141046a280200360200200041063a00000f0b200020012d00013a0001200041046a200141046a280200360200200041043a00000f0b41d800101b2202450d042002200141046a280200108b02200041046a2002360200200041086a200141086a290300370300200020012d00013a0001200041053a00000f0b200041046a200141046a280200360200200041033a00000f0b200041086a200141086a290300370300200041046a200141046a280200360200200041073a00000f0b41ecaac3001029000b41d8004108101c000b41d8004108101c000bd31d04037f027e037f027e23004180016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d000240024020030e0d002c05080c0a0607040b030901000b200241106a200141086a1073200041013a0000200041106a200241106a41086a290300370300200041086a200229031037030020024180016a24000f0b200141046a28020022034102460d0b20034103470d2b41012103200141086a2d00004101470d142001410c6a2802002101410021040c150b200141086a2903004202520d2b200041003a0000200041086a4202370300200041106a200141106a29030037030020024180016a24000f0b200141086a280200417e6a220341044b0d2b024020030e05001e1c1d1b000b200141386a2903002105200141306a2903002106410121032001410c6a2d00004101470d25200141106a28020021010c260b200141046a2d000022034102460d094103210420034103470d2b200241e2006a200141076a2d00003a0000200241106a41086a200141186a2900003703002002411d6a2001411d6a2900003700002002200141056a2f00003b01602002200141106a290000370310200141256a2d00004100472107200141286a28020021082001410c6a2800002103200141086a28000021090c0a0b200141086a28020022034102460d0a20034103470d2b410121032001410c6a2d00004101470d13200141106a28020021040c140b200241106a200141086a10a301200041073a0000200041c0006a200241106a41386a290300370300200041386a200241106a41306a290300370300200041306a200241106a41286a290300370300200041286a200241106a41206a290300370300200041206a200241106a41186a290300370300200041186a200241106a41106a290300370300200041106a200241106a41086a290300370300200041086a200229031037030020024180016a24000f0b200141086a2d0000417e6a220341044b0d2a024020030e0500201d1e1c000b41d800101b2203450d3020032001410c6a28020010c501410221010c200b41022103200141086a2d000022044102460d0b4103210320044103460d0a4104210320044104470d2a200141096a2d000041004721010c0c0b200241106a200141086a10c601200041086a200241106a41d0001095031a2000410c3a000020024180016a24000f0b200241106a200141086a10c701200041063a0000200041186a200241106a41106a290300370300200041106a200241106a41086a290300370300200041086a200229031037030020024180016a24000f0b200141046a2802004102470d28200141106a2802002203417f4c0d29200141086a28020021012003450d052003101b22040d0620034101101c000b200241106a200141086a10b901200041053a0000200041286a200241106a41206a290300370300200041206a200241106a41186a290300370300200041186a200241106a41106a290300370300200041106a200241106a41086a290300370300200041086a200229031037030020024180016a24000f0b41d800101b2203450d282003200141086a28020010c801410221040c0a0b200141086a280200210941d800101b2203450d2820032001410c6a28020010c901410221040b200041093a0000200041056a20022f01603b0000200041046a20043a00002000410c6a2003360200200041086a2009360200200041106a2002290310370200200041286a2008360200200041256a20073a0000200041076a200241e2006a2d00003a0000200041186a200241106a41086a2903003702002000411d6a2002411d6a29000037000020024180016a24000f0b410121032001410c6a2d00004101470d0a200141106a28020021040c0b0b410121040b2004200120031095032101200041106a20033602002000410c6a2003360200200041086a2001360200200041046a41023602002000410a3a000020024180016a24000f0b200141106a29030021050c010b200241e4006a2001410e6a2f00003b0100200241106a41086a200141206a290000370300200241106a41106a200141286a2d00003a000020022001410a6a2800003602602002200141186a290000370310200141106a2900002105200141096a2d000021010b200041043a0000200041096a20013a0000200041086a20033a00002000410a6a2002280260360100200041106a2005370300200041186a20022903103703002000410e6a200241e0006a41046a2f01003b0100200041206a200241106a41086a290300370300200041286a200241106a41106a29030037030020024180016a24000f0b200241106a41086a200141186a290000370300200241106a41106a200141206a290000370300200241106a41186a200141286a2d00003a00002002200141106a290000370310200141096a2f00002001410b6a2d00004110747241087421042001410c6a2800002101410021030b200241e0006a41186a200241106a41186a280200360200200241e0006a41106a200241106a41106a290300370300200241e0006a41086a200241106a41086a2903003703002002200229031037036020032004722103410321040b2000410d3a00002000410c6a2001360200200041086a2003360200200041046a2004360200200041106a2002290360370200200041186a200241e0006a41086a290300370200200041206a200241e0006a41106a290300370200200041286a200241e0006a41186a28020036020020024180016a24000f0b200241fe006a2001410f6a2d00003a0000200241186a2001411c6a290000370300200241106a41106a200141246a290000370300200241286a2001412c6a2d00003a000020022001410d6a2f00003b017c2002200141146a290000370310200141106a2800002104410021030b2002410c6a41026a200241fc006a41026a2d00003a0000200241e0006a41086a200241106a41086a290300370300200241e0006a41106a200241106a41106a290300370300200241e0006a41186a200241106a41186a280200360200200220022f017c3b010c20022002290310370360200141c8006a2903002105200141c0006a2903002106200141386a290300210a200141306a290300210b410321070c020b200241fe006a2001410f6a2d00003a0000200241186a2001411c6a290000370300200241106a41106a200141246a290000370300200241286a2001412c6a2d00003a000020022001410d6a2f00003b017c2002200141146a290000370310200141106a2800002104410021030b410221072002410c6a41026a200241fc006a41026a2d00003a0000200241e0006a41086a200241106a41086a290300370300200241e0006a41106a200241106a41106a290300370300200241e0006a41186a200241106a41186a280200360200200220022f017c3b010c20022002290310370360200141386a290300210a200141306a290300210b0b200041033a0000200041c8006a2005370300200041c0006a2006370300200041386a200a370300200041306a200b3703002000410c6a20033a0000200041086a20073602002000410d6a20022f010c3b0000200041106a2004360200200041146a20022903603702002000410f6a2002410e6a2d00003a00002000411c6a200241e0006a41086a290300370200200041246a200241e0006a41106a2903003702002000412c6a200241f8006a28020036020020024180016a24000f0b2001410c6a28020022034108762104410621010c030b200241106a41106a200141206a2903003703002002200141186a2903003703182002200141106a2802003602102001410c6a28020022034108762104200141286a290300210a410421010c0b0b2001410c6a28020022034108762104410521010c010b2002200141186a2903003703182002200141106a29030037031041032101410021030b0c080b200141106a2903002105410621010c020b200241fe006a2001410b6a2d00003a0000200241186a200141206a290000370300200241106a41106a200141286a2d00003a00002002200141096a2f00003b017c2002200141186a290000370310200141106a29000021052001410c6a2800002103410421010c030b200141106a2903002105410521010b0c010b200241fe006a2001410b6a2d00003a0000200241186a200141206a290000370300200241106a41106a200141286a2d00003a00002002200141096a2f00003b017c2002200141186a290000370310200141296a2d00004100472104200141106a29000021052001410c6a2800002103410321010b200041096a20022f017c3b0000200041086a20013a0000200041106a20053703002000410c6a2003360200200041186a2002290310370300200041296a20043a00002000412a6a20022801603601002000410b6a200241fe006a2d00003a0000200041206a200241106a41086a290300370300200041286a200241106a41106a2d00003a00002000412e6a200241e4006a2f01003b0100200041083a000020024180016a24000f0b200241e8006a2001411c6a290000370300200241e0006a41106a200141246a2800003602002002200141146a290000370360200141286a3500002001412c6a31000042208684210a2001410d6a2f00002001410f6a2d0000411074722104200141106a2800002101410021030b2002411c6a200241e8006a290300370200200241246a200241f0006a2802003602002002200229036037021420022001360210410221010b2000410b3a0000200041386a2005370300200041306a2006370300200041086a2001360200200041106a2002290310370300200041286a200a3703002000410c6a2004410874200341ff017172360200200041186a200241106a41086a290300370300200041206a200241106a41106a29030037030020024180016a24000f0b10ca01000b41dceec2001029000b41f895c3001029000b41f0fcc2001029000b41d0aec3001029000b41a080c3001029000b41a8e5c2001029000b418880c3001029000b41f4c1c3001029000b102b000b41d8004108101c000b41d8004108101c000b41d8004108101c000bc91c04027f027e047f037e23004190016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d000240024020030e0d002c05080c0a0607040b030901000b200241206a200141086a1073200041013a0000200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a28020022034102460d0b20034103470d2b41012103200141086a2d00004101470d142001410c6a28020021010c150b200141086a2903004202520d2b200041003a0000200041086a4202370300200041106a200141106a29030037030020024190016a24000f0b200141086a280200417e6a220341044b0d2b024020030e05001e1c1d1b000b200141386a2903002104200141306a2903002105410121032001410c6a2d00004101470d25200141106a28020021010c260b200141046a2d000022034102460d094103210620034103470d2b200241f2006a200141076a2d00003a0000200241206a41086a200141186a2900003703002002412d6a2001411d6a2900003700002002200141056a2f00003b01702002200141106a290000370320200141256a2d00004100472107200141286a28020021082001410c6a2800002103200141086a28000021090c0a0b200141086a28020022034102460d0a20034103470d2b410121062001410c6a2d00004101470d13200141106a28020021070c140b200241206a200141086a10a301200041073a0000200041c0006a200241206a41386a290300370300200041386a200241206a41306a290300370300200041306a200241206a41286a290300370300200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141086a2d0000417e6a220341044b0d2a024020030e0500201d1e1c000b41d800101b2203450d3020032001410c6a28020010c501410221010c200b41022103200141086a2d000022064102460d0b4103210320064103460d0a4104210320064104470d2a200141096a2d000041004721010c0c0b200241206a200141086a10c601200041086a200241206a41d0001095031a2000410c3a000020024190016a24000f0b200241206a200141086a10c701200041063a0000200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a2802004102470d28200141106a2802002203417f4c0d29200141086a28020021012003450d052003101b22060d0620034101101c000b200241206a200141086a10b901200041053a0000200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b41d800101b2203450d282003200141086a28020010c801410221060c0a0b200141086a280200210941d800101b2203450d2820032001410c6a28020010c901410221060b200041093a0000200041056a20022f01703b0000200041046a20063a00002000410c6a2003360200200041086a2009360200200041106a2002290320370200200041286a2008360200200041256a20073a0000200041076a200241f2006a2d00003a0000200041186a200241206a41086a2903003702002000411d6a2002412d6a29000037000020024190016a24000f0b410121062001410c6a2d00004101470d0a200141106a28020021070c0b0b410121060b2006200120031095032101200041106a20033602002000410c6a2003360200200041086a2001360200200041046a41023602002000410a3a000020024190016a24000f0b200141106a29030021040c010b200241f4006a2001410e6a2f00003b0100200241206a41086a200141206a290000370300200241206a41106a200141286a2d00003a000020022001410a6a2800003602702002200141186a290000370320200141106a2900002104200141096a2d000021010b200041043a0000200041096a20013a0000200041086a20033a00002000410a6a2002280270360100200041106a2004370300200041186a20022903203703002000410e6a200241f0006a41046a2f01003b0100200041206a200241206a41086a290300370300200041286a200241206a41106a29030037030020024190016a24000f0b200241206a41086a200141186a290000370300200241206a41106a200141206a290000370300200241206a41186a200141286a2d00003a00002002200141106a290000370320200141096a2f00002001410b6a2d00004110747221062001410c6a2800002101410021030b200241f0006a41186a200241206a41186a280200360200200241f0006a41106a200241206a41106a290300370300200241f0006a41086a200241206a41086a2903003703002002200229032037037020032006410874722103410321060b2000410d3a00002000410c6a2001360200200041086a2003360200200041046a2006360200200041106a2002290370370200200041186a200241f0006a41086a290300370200200041206a200241f0006a41106a290300370200200041286a200241f0006a41186a28020036020020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241f0006a41086a290300370300200241086a41106a200241f0006a41106a28020036020020022002290370370308200141c8006a2903002105200141c0006a290300210a200141386a290300210b200141306a290300210c410321010c020b200241286a2001411c6a290000370300200241206a41106a200141246a2800003602002002200141146a290000370320200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241206a41086a290300370300200241086a41106a200241206a41106a28020036020020022002290320370308200141386a290300210b200141306a290300210c410221010b200041033a00002000410f6a20034110763a00002000410d6a20033b0000200041c8006a2005370300200041c0006a200a370300200041386a200b370300200041306a200c370300200041106a20073602002000410c6a20063a0000200041086a2001360200200041146a2002290308370200200041286a20043702002000411c6a200241086a41086a290300370200200041246a200241086a41106a28020036020020024190016a24000f0b2001410c6a28020022034108762106410621010c030b200241206a41106a200141206a2903003703002002200141186a2903003703282002200141106a2802003602202001410c6a28020022034108762106200141286a290300210a410421010c0b0b2001410c6a28020022034108762106410521010c010b2002200141186a2903003703282002200141106a29030037032041032101410021030b0c080b200141106a2903002104410621010c020b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141106a29000021042001410c6a2800002103410421010c030b200141106a2903002104410521010b0c010b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141296a2d00004100472106200141106a29000021042001410c6a2800002103410321010b200041096a20022f01083b0000200041086a20013a0000200041106a20043703002000410c6a2003360200200041186a2002290320370300200041296a20063a00002000412a6a20022801703601002000410b6a2002410a6a2d00003a0000200041206a200241206a41086a290300370300200041286a200241206a41106a2d00003a00002000412e6a200241f4006a2f01003b0100200041083a000020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a31000042208684210a2001410d6a2f00002001410f6a2d0000411074722106200141106a2800002101410021030b2002412c6a200241f8006a290300370200200241346a20024180016a2802003602002002200229037037022420022001360220410221010b2000410b3a0000200041386a2004370300200041306a2005370300200041086a2001360200200041106a2002290320370300200041286a200a3703002000410c6a2006410874200341ff017172360200200041186a200241206a41086a290300370300200041206a200241206a41106a29030037030020024190016a24000f0b10ca01000b41dceec2001029000b41f895c3001029000b41f0fcc2001029000b41d0aec3001029000b41a080c3001029000b41a8e5c2001029000b418880c3001029000b41f4c1c3001029000b102b000b41d8004108101c000b41d8004108101c000b41d8004108101c000b0a00418495c3001029000bf277090f7f057e017f017e367f017e247f017e047f230041a0026b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00002204417e6a220541044b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e050005020301000b200141046a2802002106200241096a2800002105200241056a280000210720022d0001210820022d00002109200341386a41086a220a200241156a290000370300200341386a410d6a220b2002411a6a2900003700002003200241046a2d00003a00ca012003200241026a2f01003b01c80120032002410d6a2900003703382009450d09410121020c0a0b20022d000120022d0000720d022003200141086a290300370338200341b0016a41086a22024200370300200342003703b0014188e6c000411a200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c801200341c8016a4110200341386a410810030c480b200341186a200141196a290000370300200341106a200141116a290000370300200341086a200141096a29000037030020032001290001370300200241096a2800002105200241056a280000210720022d0001210c20022d0000210d200341386a41086a220e200241156a290000370300200341386a410d6a220f2002411a6a2900003700002003200241046a2d00003a00ca012003200241026a2f01003b01c80120032002410d6a290000370338200d450d03410121020c040b20022d000120022d000072450d050b41e580c00021074128210520044102470d47200141046a28020022021043200210190c470b200141216a2d0000210f200341a8016a200141196a290000370300200341a0016a200141116a29000037030020034190016a41086a200141096a2900003703002003200129000137039001200241096a2800002105200241056a280000210720022d0001210c20022d0000210d200341386a41086a220e200241156a290000370300200341386a410d6a22102002411a6a2900003700002003200241046a2d00003a00ca012003200241026a2f01003b01c80120032002410d6a290000370338200d450d07410121020c080b200341286a41026a20032d00ca013a0000200341b0016a41086a200e290300370300200341b0016a410d6a200f290000370000200320032f01c8013b0128200320032903383703b00141012102200c41ff01714101470d0020034180026a41026a200341286a41026a2d00003a0000200341386a41086a200341b0016a41086a290300370300200341386a410d6a200341b0016a410d6a290000370000200320032f01283b018002200320032903b001370338410021020c010b412a2105418d81c00021070b200341246a41026a220d20034180026a41026a2d00003a0000200341d8016a41086a220c200341386a41086a290300370300200341d8016a41106a200341386a41106a290300370300200320032f0180023b0124200320032903383703d80120020d34200341a3016a200c290300370000200341a8016a200341e5016a290000370000200320032f01243b01900120032005360097012003200736009301200320032903d80137009b012003200d2d00003a00920120034190016a10cc01450d07411c101b2202450d22200241186a41002800ece640360000200241106a41002900e4e640370000200241086a41002900dce640370000200241002900d4e6403700002002411c413c101a2202450d232002200329030037001c200241346a200341186a2903003700002002412c6a200341106a290300370000200241246a200341086a290300370000200341b0016a41086a22054200370300200342003703b0012002413c200341b0016a1001200341d8016a41086a2005290300370300200320032903b0013703d801200341d8016a4110100c2105200210192005450d0b200341386a200310cd0120032802402211450d104100210220032902442212422088a72205450d11024020054101460d004100210203402005410176220720026a220d20022011200d4105746a20034190016a41201097034101481b2102200520076b220541014b0d000b0b201120024105746a20034190016a41201097032205450d162005411f7620026a21020c110b2003200141086a290300370338200341b0016a41086a22024200370300200342003703b0014193e8c000411b200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c801200341c8016a4110200341386a410810030c400b200341286a41026a20032d00ca013a0000200341b0016a41086a200a290300370300200341b0016a410d6a200b290000370000200320032f01c8013b0128200320032903383703b00141012102200841ff01714101470d0020034180026a41026a200341286a41026a2d00003a0000200341386a41086a200341b0016a41086a290300370300200341386a410d6a200341b0016a410d6a290000370000200320032f01283b018002200320032903b001370338410021020c010b418d81c0002107412a21050b200341246a41026a220920034180026a41026a2d00003a0000200341d8016a41086a2208200341386a41086a290300370300200341d8016a41106a200341386a41106a290300370300200320032f0180023b0124200320032903383703d80120020d3c200341a3016a2008290300370000200341a8016a200341d8016a410d6a290000370000200320032f01243b01900120032005360097012003200736009301200320032903d80137009b01200320092d00003a009201200341b0016a41086a22024200370300200342003703b001419c82c000410d200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c801420021130240200341c8016a411041d889c200410041001000417f460d0020034200370338200341c8016a4110200341386a41084100100041016a41084d0d1b200329033821130b200341b0016a41086a22024200370300200342003703b0014188e6c000411a200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c801200341c8016a411041d889c200410041001000417f460d0520034200370338200341c8016a4110200341386a41084100100041016a41084d0d1b200329033821140c060b200341286a41026a20032d00ca013a0000200341b0016a41086a200e290300370300200341b0016a410d6a2010290000370000200320032f01c8013b0128200320032903383703b00141012102200c41ff01714101470d00200341026a200341286a41026a2d00003a0000200341386a41086a200341b0016a41086a290300370300200341386a410d6a200341b0016a410d6a290000370000200320032f01283b0100200320032903b001370338410021020c010b418d81c0002107412a21050b200341246a41026a220d200341026a2d00003a0000200341d8016a41086a220c200341386a41086a290300370300200341d8016a41106a200341386a41106a290300370300200320032f01003b0124200320032903383703d80120020d2d20034193026a200c29030037000020034180026a41186a2202200341e5016a290000370000200320032f01243b01800220032005360087022003200736008302200320032903d80137008b022003200d2d00003a00820220034180026a10cc01450d01200341386a41186a20034190016a41186a290300370300200341386a41106a20034190016a41106a290300370300200341386a41086a20034190016a41086a290300370300200341e0006a20034180026a41086a290300370300200341e8006a20034180026a41106a290300370300200341f0006a200229030037030020032003290390013703382003200329038002370358411b101b2202450d1d200241176a41002800f3df40360000200241106a41002900ecdf40370000200241086a41002900e4df40370000200241002900dcdf403700002002411b413b101a2202450d1e2002200329033837001b200241336a200341386a41186a2903003700002002412b6a200341386a41106a290300370000200241236a200341386a41086a2903003700002002413b41f600101a2202450d1f2002200341d8006a220529000037003b200241d3006a200541186a290000370000200241cb006a200541106a290000370000200241c3006a200541086a290000370000200341b0016a41086a22054200370300200342003703b001200241db00200341b0016a1001200341c8016a41086a2005290300370300200320032903b0013703c801410221050240200341c8016a411041d889c200410041001000417f460d00200341003a00d801200341c8016a4110200341d8016a41014100100041016a41014d0d2320032d00d80121050b20021019200541ff01714102470d2c200341d8016a41186a20034190016a41186a290300370300200341d8016a41106a20034190016a41106a290300370300200341d8016a41086a20034190016a41086a29030037030020032003290390013703d801411c101b2202450d24200241186a41002800ece640360000200241106a41002900e4e640370000200241086a41002900dce640370000200241002900d4e6403700002002411c413c101a2202450d25200220032903d80137001c200241346a200341f0016a2903003700002002412c6a200341d8016a41106a290300370000200241246a200341d8016a41086a290300370000200341b0016a41086a22054200370300200342003703b0012002413c200341b0016a1001200341c8016a41086a2005290300370300200320032903b0013703c801200341c8016a411041d889c200410041001000417f460d0b200342103702042003200341c8016a360200200341386a2003103a20032802382207450d262003200329023c2215370204200320073602002015422088a7210d2015a721050c0c0b41c8e7c0002107412b210520044102460d3a0c3b0b41f0e6c0002107412e210520044102460d390c3a0b420321140b4108210942002116200341b0016a41086a22024200370300200342003703b001419993c0004115200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c8010240200341c8016a411041d889c200410041001000417f460d00200342103702dc012003200341c8016a3602d801200341386a200341d8016a105620032802382209450d17200329023c21160b201420137c211320092016422088a7220841286c6a2107200921020340200720026b419f014d0d02200220034190016a460d03200220034190016a4120109703450d03200241286a220520034190016a460d04200520034190016a4120109703450d04200241d0006a220520034190016a460d04200520034190016a4120109703450d04200241f8006a220520034190016a460d04200241a0016a2102200520034190016a41201097030d000c040b0b41f3e7c00021074120210520044102460d360c370b4102210520072002460d022009200841286c6a2107034020034190016a2002460d01200220034190016a4120109703450d012007200241286a2202470d000c030b0b200221050b200541206a29030020135621050b2005410247200571210202402016a7450d00200910190b024002402002450d0020034100360240200342013703382006200341386a1064200328023c21082003280240210a20032802382109200341386a41186a22024200370300200341386a41106a22054200370300200341386a41086a22074200370300200342003703382009200a200341386a100520034180026a41186a220a200229030037030020034180026a41106a220b200529030037030020034180026a41086a22172007290300370300200320032903383703800202402008450d00200910190b2002200a2903003703002005200b2903003703002007201729030037030020032003290380023703384118101b2202450d19200241106a410029008ae240370000200241086a4100290082e240370000200241002900fae140370000200241184138101a2202450d1a20022003290338370018200241306a200341386a41186a290300370000200241286a200341386a41106a290300370000200241206a200341386a41086a290300370000200341b0016a41086a22054200370300200342003703b00120024138200341b0016a1001200341d8016a41086a2005290300370300200320032903b0013703d801200341d8016a4110100c2105200210192005450d0141f9c4c1002107411f21050c320b41a2e6c0002107412021050c310b200341386a20034180026a10cd01024020032802402202450d00200328024421052003290338211442002116200341b0016a41086a22074200370300200342003703b001419c82c000410d200341b0016a1001200341c8016a41086a2007290300370300200320032903b0013703c8010240200341c8016a411041d889c200410041001000417f460d00200342003703d801200341c8016a4110200341d8016a41084100100041016a41084d0d1220032903d80121160b02402005450d00200210190b201620145a0d0041c2e6c0002107411221050c310b41082108200341b0016a41086a22024200370300200342003703b00141e3e1c0004117200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c80141002109200341c8016a411041d889c200410041001000417f460d07200342103702dc012003200341c8016a3602d801200341386a200341d8016a105320032802382208450d1e2003200329023c221637022c200320083602282016422088a721092016a721020c080b4100210241012111420021120b200341386a41186a20034190016a41186a290300370300200341386a41106a20034190016a41106a290300370300200341386a41086a20034190016a41086a290300370300200320032903900137033820022012422088a722054b0d1820052012a7470d28200541016a22072005490d2a2005410174220d20072007200d491bad22124205862218422088a70d2a2018a722074100480d2a2005450d02201120054105742007101a2211450d030c280b410021052003410036020820034201370300410121074100210d0b20021019200341386a41186a220e20034180026a41186a290300370300200341386a41106a221020034180026a41106a290300370300200341386a41086a221a20034180026a41086a290300370300200320032903800237033802402005200d470d00200541016a22022005490d292005410174220c20022002200c491b220cad4205862215422088a70d292015a722024100480d292005450d06200720054105742002101a2207450d070c1e0b2005210c0c1e0b2007101b22110d250b20074101101c000b419ee7c0002107412a21052012a7450d1d2011101920044102460d2b0c2c0b2003410036023020034208370328410021020b200341386a41186a220520034180026a41186a290300370300200341386a41106a220720034180026a41106a290300370300200341386a41086a220a20034180026a41086a290300370300200320032903800237033820022009470d17200941016a22022009490d232009410174220b20022002200b491b2202ad42287e2216422088a70d232016a7220b4100480d232009450d022008200941286c200b101a2208450d030c160b2002101b22070d170b20024101101c000b200b101b22080d130b200b4108101c000b41d4edc2001029000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b411c4101101c000b413c4101101c000b411b4101101c000b413b4101101c000b41f6004101101c000b41184101101c000b41384101101c000b41fcf9c00041331030000b41fcd5c3001029000b411c4101101c000b413c4101101c000b41fcf9c00041331030000b41fcf9c00041331030000b2003200236022c200320083602280b2008200941286c6a2202201337030020022003290338370308200241206a2005290300370300200241186a2007290300370300200241106a200a290300370300200341286a41086a200941016a220a3602000240200a41144b0d0041022126200941016a4102490d0d412821272008200941286c6a41d0006a2128417f2129410a212a410b212b410f212c4120212d200341c5006a212e411b212f410821304113213141182132411021334103213441502135417821364148213741702138414021394168213a41b87f213b4160213c41b07f213d4158213e4101213f410121020c0b0b02400240200a4101762242ad42287e2215422088a70d002015a72202417f4c0d0041082110024002402002450d002002101b2243450d03204321440c010b41082143410821440b41582147200841586a2148200841d0006a2149200841887f6a214a4104214b4100214c417f214d4101214e4203214f422021154103215041022151417d215241282153412021464118215441102145417e2155417421564164215741b07f215841092159410a215a410b215b410f215c200341c5006a215d411b215e4113215f41502160417821614148216241702163414021644168216541b87f21664160216741002168410021694104216a200a216b410221020c0c0b102b000b20024108101c000b2003200c360204200320073602000b2007200d4105746a22022003290338370000200241186a200e290300370000200241106a2010290300370000200241086a201a290300370000200341086a200d41016a360200411c101b2202450d05200241186a41002800ece640360000200241106a41002900e4e640370000200241086a41002900dce640370000200241002900d4e6403700002002411c413c101a2202450d06200220032903d80137001c200241346a200341d8016a41186a2903003700002002412c6a200341d8016a41106a290300370000200241246a200341d8016a41086a2903003700002003413c36023c200320023602382003200341386a10980120021019200c450d00200710190b200341386a41186a20034190016a41186a290300370300200341386a41106a20034190016a41106a290300370300200341386a41086a20034190016a41086a290300370300200341e0006a20034180026a41086a290300370300200341e8006a20034180026a41106a290300370300200341f0006a20034180026a41186a290300370300200320032903900137033820032003290380023703582003200f3a00d801411b101b2202450d01200241176a41002800f3df40360000200241106a41002900ecdf40370000200241086a41002900e4df40370000200241002900dcdf403700002002411b413b101a2202450d022002200329033837001b200241336a200341386a41186a2903003700002002412b6a200341386a41106a290300370000200241236a200341386a41086a2903003700002002413b41f600101a2202450d032002200341d8006a220529000037003b200241d3006a200541186a290000370000200241cb006a200541106a290000370000200241c3006a200541086a290000370000200341b0016a41086a22054200370300200342003703b001200241db00200341b0016a1001200341c8016a41086a2005290300370300200320032903b0013703c801200341c8016a4110200341d8016a4101100320021019410021070b20044102470d0e0c0d0b411b4101101c000b413b4101101c000b41f6004101101c000b411c4101101c000b413c4101101c000b201120024105746a220741206a2007200520026b4105741096031a200741186a200341386a41186a290300370000200741106a200341386a41106a290300370000200741086a200341386a41086a29030037000020072003290338370000200341b0016a41086a22024200370300200342003703b001419c82c000410d200341b0016a1001200341c8016a41086a22072002290300370300200320032903b0013703c801420021180240024002400240200341c8016a411041d889c200410041001000417f460d0020034200370338200341c8016a4110200341386a41084100100041016a41084d0d01200329033821180b20024200370300200342003703b0014193e8c000411b200341b0016a100120072002290300370300200320032903b0013703c80102400240200341c8016a411041d889c200410041001000417f460d0020034200370338200341c8016a4110200341386a41084100100041016a41084d0d032003290338211641012107411c210d411c101b2202450d010c040b42e807211641012107411c210d411c101b22020d030b200d2007101c000b41fcf9c00041331030000b41fcf9c00041331030000b200241186a41002800aae240360000200241106a41002900a2e240370000200241086a410029009ae24037000020024100290092e24037000002400240024002402002200d413c101a2219450d002019200329030037001c201941346a200341186a2903003700002019412c6a200341106a290300370000201941246a200341086a29030037000020034100360240200342013703384108101b2202450d012002201620187c37000020034288808080800137023c200320023602382003200520076a22023602d801200341d8016a200341386a105d0240024002402002450d00200541057441206a210e4100200341386a41086a28020022056b210d2003280238210f200328023c210c2011210203400240200c200d6a411f4b0d00200541206a22072005490d0a200c410174221a20072007201a491b22074100480d0a02400240200c450d00200f200c2007101a220f0d010c060b2007101b220f450d050b2007210c0b200f20056a22072002290000370000200741186a200241186a290000370000200741106a200241106a290000370000200741086a200241086a290000370000200d41606a210d200541206a2105200241206a2102200e41606a220e0d000b200341c0006a20053602002003200c36023c2003200f3602380c010b200341c0006a2802002105200328023c210c2003280238210f0b2012a72102200341b0016a41086a22074200370300200342003703b0012019413c200341b0016a1001200341d8016a41086a2007290300370300200320032903b0013703d801200341d8016a4110200f200510030240200c450d00200f10190b2019101902402002450d00201110190b4108211b200341b0016a41086a22024200370300200342003703b00141e3e1c0004117200341b0016a1001200341c8016a41086a2002290300370300200320032903b0013703c8014100211c0240024002400240200341c8016a411041d889c200410041001000417f460d00200342103702dc012003200341c8016a3602d801200341386a200341d8016a10532003280238221b450d07200328023c211c4128210d200341c0006a280200220e41286c220c0d010c020b4100210e4128210d410041286c220c450d010b200341386a41086a2102410021070340200341386a41206a201b20076a220541206a290300370300200341386a41186a200541186a290300370300200341386a41106a200541106a2903003703002002200541086a2903003703002003200529030037033820034180026a41186a200241186a29000037030020034180026a41106a200241106a29000037030020034180026a41086a200241086a290000370300200320022900003703800220034180026a200341201097030d02200c2007200d6a2207470d000b0b4100211d20034100360240200342083703384108211e201c450d0a201b10190c0a0b200341d8016a41206a2202200341386a41206a290300370300200341d8016a41186a220d200341386a41186a290300370300200341d8016a41106a220c200341386a41106a290300370300200341d8016a41086a220f200341386a41086a290300370300200320032903383703d8014128101b221e450d04201e20032903d801370300201e41206a2002290300370300201e41186a200d290300370300201e41106a200c290300370300201e41086a200f2903003703000240200e41286c41586a2007460d00200541286a211f41282111201b200e41286c6a221941586a21204108211a200341386a41086a210d410121214120210f4118210e4110210c422821184220211241002122410121234101211d410021020c060b410121234101211d0c080b20074101101c000b413c4101101c000b41084101101c000b41fcf9c00041331030000b41284108101c000b0240034002400240024002400240024002400240024002400240024002400240024002400240024020020e03000102020b201f210202400340200341386a200f6a22052002200f6a290300370300200341386a200e6a22072002200e6a290300370300200341386a200c6a220b2002200c6a290300370300200d2002201a6a2903003703002003200229030037033820034180026a200e6a200d200e6a29000037030020034180026a200c6a200d200c6a29000037030020034180026a201a6a200d201a6a2900003703002003200d2900003703800220034180026a2003200f1097030d012019200220116a2202470d000c170b0b200341d8016a200f6a221f2005290300370300200341d8016a200e6a22172007290300370300200341d8016a200c6a2224200b290300370300200341d8016a201a6a2225200d290300370300200320032903383703d8012005201f29030037030020072017290300370300200b2024290300370300200d2025290300370300200320032903d8013703380240201d2023470d00202320216a221d2023490d142023202174221f201d201d201f491b221dad20187e2216201288a70d142016a7221f2022480d1402402023450d00201e202320116c201f101a221e0d010c080b201f101b221e450d070b200220116a211f201e202320116c6a221720032903383703002017200f6a20052903003703002017200e6a20072903003703002017200c6a200b2903003703002017201a6a200d290300370300202320216a212320202002470d070c150b200a2009220220296a2209490d010240200a20096b220b2026490d002008200220276c6a22072903002008200920276c6a220529030022135a0d00200320052f01083b01c80120032005202a6a2d00003a00ca012005202b6a28000021252005202c6a2800002140202e2005202d6a2202290000370000200341386a20306a22412005202f6a290000370300200520316a290000211620022007202d6a290300370300200520326a200720326a290300370300200520336a200720336a2903003703002003201637033820052007290300370300200520306a200720306a290300370300410121020240200b2034490d00200529035020135a0d00410321172028210202400340200220356a200220366a290300370300200220376a200220386a290300370300200220396a2002203a6a2903003703002002203b6a2002203c6a2903003703002002203d6a2002203e6a220729030037030020172224200b4f0d012024203f6a211720022903002116200220276a210220162013540d000b0b202420296a21020b200720133703002005200220276c6a220220032f01c8013b010820032d00ca0121052002202c6a20403600002002202b6a20253600002002202a6a20053a00002002202d6a202e2900003700002002202f6a2041290300370000200220316a20032903383700000b2028203e6a212820090d070c130b206b216c4100216b4101216d206c204d6a2225450d0702400240024002400240024002402008202520536c6a2903002008206c20536c22176a20586a29030022165a0d00204a20176a210203402025204e460d022025204d6a2125201620022903002213542105200220476a21022013211620050d000c030b0b206c20556a210b204a20176a21054100216b410021020340200b2002460d052002204e6a21022016200529030022135a2107200520476a21052013211620070d000b206c20026b204d6a21252002204e6a226d20594d0d030c020b410021250b206c2025490d05206c200a4b0d070240206c20256b226d204e762207450d002008202520536c6a2102204820176a21050340200341386a20466a220b200220466a2217290300370300200341386a20546a2224200220546a2240290300370300200341386a20456a2241200220456a226e290300370300200341386a20106a226f200220106a227029030037030020032002290300370338200520106a22712903002116200520456a22722903002113200520546a22732903002114200529030021742017200520466a227529030037030020402014370300206e201337030020702016370300200220743703002075200b29030037030020732024290300370300207220412903003703002071206f29030037030020052003290338370300200220536a2102200520476a21052007204d6a22070d000b0b206d20594d0d010b2025216b20692068460d0e0c0f0b2025450d01206c200a4b0d042049202520536c6a2176410021770c0f0b206c216d20692068460d090c0a0b2025216b20692068460d0a410221020c0e0b2009200a1027000b2025206c1027000b206c2025417f6a226b490d0d0b206c200a1028000b201f4108101c000b410021020c090b410121020c080b410021020c060b410121020c050b410221020c040b410121020c030b410121020c020b410221020c010b410321020b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e0400010204040b20692068470d10410121020c160b2068204e6a22022068490d182068204e742205200220022005491b2269ad204f862216201588a70d182016a72202204c480d1802402068450d00206a20682050742002101a226a0d110c020b2002101b226a0d110c010b206a20682050746a2202206d3602042002206b3602002068204e6a2278216820782051490d02410121770c130b20024104101c000b0240024020770e020001010b206c2025204d6a226b490d150240206c206b6b226d2051490d002008202520536c6a22072903002008206b20536c6a220529030022135a0d00200320052f01083b01c80120032005205a6a2d00003a00ca012005205b6a28000021242005205c6a2800002140205d200520466a2202290000370000200341386a20106a22412005205e6a2900003703002005205f6a29000021162002200720466a290300370300200520546a200720546a290300370300200520456a200720456a2903003703002003201637033820052007290300370300200520106a200720106a290300370300410121020240206d2050490d00200529035020135a0d004103210b2076210202400340200220606a200220616a290300370300200220626a200220636a290300370300200220646a200220656a290300370300200220666a200220676a290300370300200220586a200220476a2207290300370300200b2217206d4f0d012017204e6a210b20022903002116200220536a210220162013540d000b0b2017204d6a21020b200720133703002005200220536c6a220220032f01c8013b010820032d00ca0121052002205c6a20403600002002205b6a20243600002002205a6a20053a0000200220466a205d2900003700002002205e6a20412903003700002002205f6a20032903383700000b206b450d0c207620476a2176206b2125206d205a490d0a410021020c130b0240024002400240206a20782241204d6a22782050746a2202280200450d00206a20412050746a221720566a280200220b200228020422054d0d0041022168204141024d0d04206a204120526a22022050746a28020422072005200b6a4d0d0141032168204141034d0d04201720576a2802002007200b6a4d0d010c050b20412050490d0120022802042105206a204120526a22022050746a28020421070b20072005490d010b204120556a21020b20412002204e6a22724d0d03204120024d0d04206a20022050746a226f2802042273206f2802006a2202206a20722050746a22702802002271490d052002200a4b0d06206f204b6a21752008207120536c6a22402070280204226e20536c22056a2168200220536c210702400240024002400240200220716b2217206e6b2202206e4f0d0020432068200220536c22051095031a204420056a210b206e204e480d012002204e480d01204820076a21072068210203402007200220476a2268200b20476a2217201729030020682903005422241b2205290300370300200720466a200520466a290300370300200720546a200520546a290300370300200720456a200520456a290300370300200720106a200520106a290300370300200b201720241b210b20402068200220241b22024f0d04200720476a2107204421052044200b490d000c050b0b2043204020051095031a204420056a210b206e204e480d012017206e4c0d01200820076a212420442105204021020340200220682005206829030020052903005422171b2207290300370300200220466a200720466a290300370300200220546a200720546a290300370300200220456a200720456a290300370300200220106a200720106a2903003703002005200520536a20171b2105200220536a2102206820536a206820171b226820244f0d04200b20054b0d000c040b0b206821020c010b204021020b204421050b20022005200b20056b220720072053706b1095031a20752073206e6a360200206f20713602002070207020106a2072204d7320416a2050741096031a207821682078204e4b0d0a0b206b0d060c010b20412168206b0d060b02402069450d00206a10190b2042450d13204310190c130b41c4edc20020722041104a000b41c4edc20020022041104a000b207120021027000b2002200a1028000b410221020c0b0b410221020c0a0b410021770c050b410121770c050b410021020c060b410221020c050b410221020c040b410221020c030b410321020c020b410321020c010b410321020c000b0b0b206b206c1027000b101d000b2003411736023c200341e3e1c000360238200341286a200341386a1054200341d8016a41186a20034180026a41186a290300370300200341d8016a41106a20034180026a41106a290300370300200341d8016a41086a20034180026a41086a29030037030020032003290380023703d801200341386a200641d8001095031a024002400240024002400240024002404118101b2202450d00200241106a410029008ae240370000200241086a4100290082e240370000200241002900fae140370000200241184138101a2202450d01200220032903d801370018200241306a200341d8016a41186a290300370000200241286a200341d8016a41106a290300370000200241206a200341d8016a41086a2903003700002003410036020820034201370300200341386a20031064200328020421052003280208210720032802002101200341b0016a41086a220d4200370300200342003703b00120024138200341b0016a1001200341c8016a41086a200d290300370300200320032903b0013703c801200341c8016a411020012007100302402005450d00200110190b20021019200341386a1043200341386a41186a20034180026a41186a290300370300200341386a41106a20034180026a41106a290300370300200341386a41086a20034180026a41086a29030037030020032003290380023703384120101b2202450d0220034190016a41086a290300211520034190016a41106a290300214f2003290390012112200241186a20034190016a41186a290300370000200241106a204f370000200241086a20153700002002201237000020034281808080103702dc01200320023602d801411c101b2201450d03200141186a41002800ece640360000200141106a41002900e4e640370000200141086a41002900dce640370000200141002900d4e6403700002001411c413c101a2201450d042001200329033837001c200141346a200341386a41186a22052903003700002001412c6a200341386a41106a2207290300370000200141246a200341386a41086a220d2903003700002003413c36020420032001360200200341d8016a20031098012001101920021019200520034180026a41186a290300370300200720034180026a41106a290300370300200d20034180026a41086a290300370300200341e0006a20034190016a41086a290300370300200341e8006a20034190016a41106a290300370300200341f0006a20034190016a41186a29030037030020032003290380023703382003200329039001370358200341013a00d801411b101b2202450d05200241176a41002800f3df40360000200241106a41002900ecdf40370000200241086a41002900e4df40370000200241002900dcdf403700002002411b413b101a2202450d062002200329033837001b200241336a200341386a41186a2903003700002002412b6a200341386a41106a290300370000200241236a200341386a41086a2903003700002002413b41f600101a2202450d072002200341d8006a220129000037003b200241d3006a200141186a290000370000200241cb006a200141106a290000370000200241c3006a200141086a290000370000200341b0016a41086a22014200370300200342003703b001200241db00200341b0016a1001200341c8016a41086a2001290300370300200320032903b0013703c801200341c8016a4110200341d8016a41011003200210190240200328022c450d00200328022810190b20061019410021070c0d0b41184101101c000b41384101101c000b41204101101c000b411c4101101c000b413c4101101c000b411b4101101c000b413b4101101c000b41f6004101101c000b0240201c450d00201b10190b200320233602402003201d36023c2003201e3602380b200341173602dc01200341e3e1c0003602d801200341386a200341d8016a10540240201d450d00201e10190b200341386a41186a200341186a290300370300200341386a41106a200341106a290300370300200341386a41086a200341086a2903003703002003200329030037033802400240024002400240411c101b2202450d00200241186a41002800ece640360000200241106a41002900e4e640370000200241086a41002900dce640370000200241002900d4e6403700002002411c413c101a2202450d012002200329033837001c200241346a200341386a41186a22052903003700002002412c6a200341386a41106a2207290300370000200241246a200341386a41086a220d290300370000200341b0016a41086a220c4200370300200342003703b0012002413c200341b0016a1001200341d8016a41086a200c290300370300200320032903b0013703d801200341d8016a41101002200210192005200341186a2903003703002007200341106a290300370300200d200341086a290300370300200320032903003703384118101b2202450d02200241106a410029008ae240370000200241086a4100290082e240370000200241002900fae140370000200241184138101a2202450d0320022003290338370018200241306a200341d0006a290300370000200241286a200341386a41106a29030037000041082145200241206a200341386a41086a29030037000042002115200341b0016a41086a22054200370300200342003703b00120024138200341b0016a1001200341d8016a41086a2005290300370300200320032903b0013703d801200341d8016a411010022002101920054200370300200342003703b001419993c0004115200341b0016a1001200341c8016a41086a2005290300370300200320032903b0013703c8010240200341c8016a411041d889c200410041001000417f460d00200342103702dc012003200341c8016a3602d801200341386a200341d8016a105620032802382245450d05200329023c21150b02400240024002402015422088a72202450d00200241286c210d200341d8006a210720452105034020072005290000370000200341386a41186a220c200341186a290300370300200341386a41106a220e200341106a290300370300200341386a41086a2210200341086a290300370300200741086a220f200541086a290000370000200741106a221a200541106a290000370000200741186a2246200541186a29000037000020032003290300370338411b101b2202450d02200241176a41002800f3df40360000200241106a41002900ecdf40370000200241086a41002900e4df40370000200241002900dcdf403700002002411b413b101a2202450d032002200329033837001b200241336a200c2903003700002002412b6a200e290300370000200241236a20102903003700002002413b41f600101a2202450d04200541286a21052002200729000037003b200241d3006a2046290000370000200241cb006a201a290000370000200241c3006a200f290000370000200341b0016a41086a220c4200370300200342003703b001200241db00200341b0016a1001200341d8016a41086a200c290300370300200320032903b0013703d801200341d8016a4110100220021019200d41586a220d0d000b0b2015a7450d09204510190c090b411b4101101c000b413b4101101c000b41f6004101101c000b411c4101101c000b413c4101101c000b41184101101c000b41384101101c000b41fcf9c00041331030000b20061043200610190c020b4100210720044102470d010b200141046a28020022021043200210190b2000200536020420002007360200200341a0026a24000b8a0303027f017e057f230041306b220124004108210242002103200141206a41086a2204420037030020014200370320419993c0004115200141206a1001200141086a200429030037030020012001290320370300024002402001411041d889c200410041001000417f460d002001421037021420012001360210200141206a200141106a105620012802202202450d01200129022421030b20022003422088a7220541286c6a210620022104024002400340200620046b419f014d0d014101210720042000460d02200420004120109703450d02200441286a22082000460d02200820004120109703450d02200441d0006a22082000460d02200820004120109703450d02200441f8006a22082000460d02200441a0016a21042008200041201097030d000c020b0b024020062004460d002002200541286c6a210803404101210720002004460d02200420004120109703450d022008200441286a2204470d000b0b410021070b02402003a7450d00200210190b200141306a240020070f0b41fcf9c00041331030000b960302027f017e230041306b2202240002400240411c101b2203450d00200341186a41002800aae240360000200341106a41002900a2e240370000200341086a410029009ae24037000020034100290092e2403700002003411c413c101a2203450d012003200129000037001c200341346a200141186a2900003700002003412c6a200141106a290000370000200341246a200141086a290000370000200241206a41086a22014200370300200242003703202003413c200241206a1001200241086a2001290300370300200220022903203703000240024002402002411041d889c200410041001000417f460d002002200236021020024110360214200242003703202002410020024110200241206a41084100100022012001417f461b2201410820014108491b360218200141074d0d0220022903202104200241206a200241106a103a20022802202201450d022000200229022437020c200020043703000c010b410021010b2000200136020820031019200241306a24000f0b41fcf9c00041331030000b411c4101101c000b413c4101101c000be70801067f230041f0006b22022400200241003a005020012802002001280204200241d0006a410120012802081000210320012001280208200341016a220341014b6a220436020802400240024020034102490d0020022d0050220341f0014f0d01410121010c020b200041023a0000200241f0006a24000f0b024002400240024002400240200341847e6a220341034b0d0002400240024020030e0400040102000b200141046a2802002103200241003b0150200141086a2205410020012802002003200241d0006a41022004100022012001417f461b2203410220034102491b20052802006a36020041012101200341014d0d0641ef01210320022f015041ef014b0d08200041023a0000200241f0006a24000f0b200141046a280200210320024100360250200141086a2205410020012802002003200241d0006a41042004100022012001417f461b2201410420014104491b20052802006a360200200041023a0000200241f0006a24000f0b200241d0006a41186a4200370300200241d0006a41106a4200370300200241d0006a41086a42003703002002420037035041002105200141086a220341002001280200200141046a280200200241d0006a41202004100022012001417f461b2201412020014120491b20032802006a3602002001411f4d0d022002412e6a20022d00523a0000200241106a41086a200241df006a290000370300200241106a41106a200241e7006a290000370300200241106a41186a200241d0006a411f6a2d00003a0000200220022f01503b012c2002200229005737031020022800532103410121050c030b200041023a0000200241f0006a24000f0b200141046a280200210320024100360250200141086a2205410020012802002003200241d0006a41042004100022012001417f461b2201410420014104491b20052802006a360200200141034d0d0341ffff03210341012101200228025041ffff034b0d04200041023a0000200241f0006a24000f0b0b200241cc006a41026a22012002412c6a41026a2d00003a0000200241306a41086a2204200241106a41086a290300370300200241306a41106a2206200241106a41106a290300370300200241306a41186a2207200241106a41186a2d00003a0000200220022f012c3b014c2002200229031037033002402005450d002002410c6a41026a20012d00003a0000200241d0006a41086a2004290300370300200241d0006a41106a2006290300370300200241d0006a41186a20072d00003a0000200220022f014c3b010c20022002290330370350410021010c030b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200041023a0000200241f0006a24000f0b200020022f010c3b0001200020013a0000200041046a2003360200200041086a2002290350370200200041036a2002410e6a2d00003a0000200041106a200241d0006a41086a290300370200200041186a200241d0006a41106a290300370200200041206a200241d0006a41186a280200360200200241f0006a24000b8e0a01037f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00004101470d00200041046a280200220241ffff034d0d01200141046a280200200141086a2802002200470d03200041016a22032000490d1820004101742204200320032004491b22044100480d182000450d09200128020020002004101a2203450d0a0c160b200141046a280200200141086a2802002202470d01200241016a22032002490d1720024101742204200320032004491b22044100480d172002450d04200128020020022004101a2203450d050c130b200241ef014b0d02200141046a280200200141086a2802002200470d05200041016a22032000490d1620004101742204200320032004491b22044100480d162000450d09200128020020002004101a22030d0a0c0f0b200128020021030c120b200128020021030c130b200141046a280200200141086a2802002200470d03200041016a22032000490d1320004101742204200320032004491b22044100480d132000450d09200128020020002004101a22030d0a0c0d0b2004101b22030d0e0b20044101101c000b200128020021030c050b200128020021030c070b2004101b22030d0c0b20044101101c000b2004101b2203450d050b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b2004101b2203450d030b20012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a00000240024002400240200141046a2802002203200428020022006b41024f0d00200041026a22042000490d0b20034101742200200420042000491b22004100480d0b2003450d01200128020020032000101a22030d020c060b200128020021030c020b2000101b2203450d040b20012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b20044101101c000b20044101101c000b20004101101c000b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41ff013a000002400240024002400240200141046a2802002203200428020022026b41204f0d00200241206a22042002490d0720034101742202200420042002491b22024100480d072003450d01200128020020032002101a2203450d020c030b200128020021030c030b2002101b22030d010b20024101101c000b20012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000f0b20012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a0000024002400240200141046a2802002203200428020022006b41044f0d00200041046a22042000490d0320034101742200200420042000491b22004100480d032003450d01200128020020032000101a2203450d020c040b200128020021030c040b2000101b22030d020b20004101101c000b101d000b20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000be30904077f027e017f027e23004180016b22022400200241e0006a41186a22034200370300200241e0006a41106a22044200370300200241e0006a41086a2205420037030020024200370360410021062001410020012802002001280204200241e0006a41202001280208100022072007417f461b2207412020074120491b20012802086a220836020802402007411f4d0d00200241c0006a41186a22072003290300370300200241c0006a41106a22062004290300370300200241c0006a41086a2203200529030037030020022002290360370340200241206a41186a2007290300370300200241206a41106a2006290300370300200241206a41086a200329030037030020022002290340370320410121060b200241e0006a41186a2207200241206a41186a290300370300200241e0006a41106a2203200241206a41106a290300370300200241e0006a41086a2204200241206a41086a2903003703002002200229032037036002400240024002402006450d00200241186a2007290300370300200241106a2003290300370300200241086a2004290300370300200220022903603703002002420037036820024200370360200141086a220641002001280200200141046a2203280200200241e0006a41102008100022072007417f461b2207411020074110491b20062802006a22063602002007410f4d0d01200241e0006a41086a220529030021092002290360210a200241e0006a41186a22084200370300200241e0006a41106a220b42003703002005420037030020024200370360200141086a2204410020012802002003280200200241e0006a41202006100022072007417f461b2207412020074120491b20042802006a22063602002007411f4d0d02200241c0006a41186a22072008290300370300200241c0006a41106a2203200b290300370300200241c0006a41086a2208200529030037030020022002290360370340200241206a41186a2007290300370300200241206a41106a2003290300370300200241206a41086a2008290300370300200220022903403703202002420037036820024200370360200441002001280200200141046a280200200241e0006a41102006100022012001417f461b2201411020014110491b20042802006a3602002001410f4d0d03200241e0006a41086a2201290300210c2002290360210d200241e0006a41186a2207200241186a290300370300200241e0006a41106a2206200241106a2903003703002001200241086a290300370300200241c0006a41086a2203200241206a41086a290300370300200241c0006a41106a2204200241206a41106a290300370300200241c0006a41186a2205200241206a41186a2903003703002002200229030037036020022002290320370340200041206a200c370300200041186a200d370300200041106a20093703002000200a370308200041286a2002290360370300200041306a2001290300370300200041386a2006290300370300200041c0006a2007290300370300200041c8006a2002290340370300200041d0006a2003290300370300200041d8006a2004290300370300200041e0006a20052903003703002000420137030020024180016a24000f0b2000420037030020024180016a24000f0b2000420037030020024180016a24000f0b2000420037030020024180016a24000f0b2000420037030020024180016a24000b130020004102360204200041b8f1c2003602000b130020004104360204200041b8edc0003602000b130020004101360204200041c0f2c2003602000b970101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120101b2206450d0020062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000f0b41204101101c000b1300200041053602042000419cf3c2003602000b13002000410836020420004191f2c0003602000b130020004108360204200041f8f6c2003602000b3201017f02404108101b2202450d0020004288808080800137020420002002360200200242013700000f0b41084101101c000b940301087f230041c0006b2202240041002103200141086a2104200141046a210541002106024002400240024002400340200341204f0d012005280200220720042802002208460d02200841016a21092008417f460d0420072009490d05200128020020086a2d0000210820042009360200200841ff00712003411f71742006722106200341076a21032008418001710d000b20034120490d0220086741686a41ff017141034b0d02200041013602002000410d3a0004200241c0006a24000f0b200041013602002000410f3a0004200241c0006a24000f0b200241013a000f200241346a41013602002002410136023c20024201370224200241c4d6c30036022020022002410f6a3602382002200241386a360230200241106a200241206a10242002412b6a200241186a28020036000020022002290310370023200041053a000420004101360200200020022900203700052000410c6a200241276a290000370000200241c0006a24000f0b2000410036020020002006360204200241c0006a24000f0b417f20091027000b200920071028000bc90202077f017e024002400240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b220641d8006d22074f0d00200320076a22082003490d0320024101742203200820082003491b2203ad42d8007e2209422088a70d032009a722084100480d032002450d012000280200200241d8006c2008101a2202450d020c040b200028020021020c040b2008101b22020d020b20084108101c000b101d000b20002002360200200041046a2003360200200041086a28020021030b2002200341d8006c6a200520061095031a200141086a22022004360200200041086a2200200028020020076a36020041002100024003402000450d012002200441d8006a2203360200200041a87f6a210020042d000021072003210420074105470d000b0b02402001280204450d00200128020010190b0b910202077f017e024002400240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b220641f8006d22074f0d00200320076a22082003490d0320024101742203200820082003491b2203ad42f8007e2209422088a70d032009a722084100480d032002450d012000280200200241f8006c2008101a2202450d020c040b200028020021020c040b2008101b22020d020b20084108101c000b101d000b20002002360200200041046a2003360200200041086a28020021030b2002200341f8006c6a200520061095031a200141086a2004360200200041086a2200200028020020076a36020002402001280204450d00200128020010190b0be60601097f230041206b22022400200241003602182002420137031020002802002103024002404104101b2204450d0020024284808080c000370214200220043602102004200336000020002802042103200441044108101a2204450d012002428880808080013702142004200336000420022004360210200041086a28020021042002200041106a28020022033602002002200241106a105d02400240024002402003450d0020034105742105200241106a41086a220628020021032002280214210703400240024002400240200720036b41204f0d00200341206a22082003490d0620074101742209200820082009491b220a4100480d062007450d0120022802102007200a101a22090d020c070b200341206a2108200228021021090c020b200a101b2209450d050b2002200a36021420022009360210200a21070b20062008360200200920036a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a2900003700002003200429000037000020082103200441206a2104200541606a22050d000b0b200041146a280200210420022000411c6a28020022033602002002200241106a105d024002402003450d002003410574210a4100200241106a41086a220628020022036b21082002280214210703400240024002400240200720086a41204f0d00200341206a22092003490d0720074101742205200920092005491b22054100480d072007450d01200228021020072005101a22090d020c090b200228021021090c020b2005101b2209450d070b2002200536021420022009360210200521070b2006200341206a2205360200200920036a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a29000037000020032004290000370000200841606a210820052103200441206a2104200a41606a220a0d000c020b0b200241186a280200210520022802142107200228021021090b2001280204210420012802002103200241106a41086a220842003703002002420037031020032004200241106a1001200241086a2008290300370300200220022903103703002002411020092005100302402007450d00200910190b200241206a24000f0b101d000b200a4101101c000b20054101101c000b41044101101c000b41084101101c000bb10101037f024002400240024002400240200041046a280200200041086a2802002201470d00200141016a22022001490d0320014101742203200220022003491b22034100480d032001450d01200028020020012003101a2202450d020c040b200028020021020c040b2003101b22020d020b20034101101c000b101d000b20002002360200200041046a2003360200200041086a28020021010b200041086a200141016a360200200220016a41023a00000b941605027f017e127f017e0b7f23004190026b22022400200241086a2001102d0240024002400240024002400240024002400240024002400240024002402002280208450d00200228020c2203ad42287e2204422088a70d0b2004a72205417f4c0d0b2005450d012005101b2206450d032003450d020c040b2000410036020020024190026a24000f0b4108210620030d020b41002115410021120c020b20054108101c000b200241b8016a41106a2105200241b8016a4101722107200241f8006a41116a2108200241c7016a2109200241106a410172210a200141046a210b2002418c026a41026a210c20024180026a210d200241b8016a41076a210e4100210f4100211041002111200321120340200b2802002113200241003a00b801200241b8016a20012802002214201341004722151095031a20132015490d05200b201320156b22163602002001201420156a22153602002013450d0320022d00b801221341034b0d030240024002400240024002400240024020130e0400030102000b20022001102d2002280200450d0a20022802042213417f4c0d0e2013450d03201310df012215450d1020152001280200200b2802002216201320162013491b22161095031a200b28020022142016490d11200b201420166b3602002001200128020020166a36020020162013460d040c090b200241b8016a2016412020164120491b22136a41004100412020136b2013411f4b1b1094031a200241b8016a201520131095031a200b201620136b3602002001201520136a3602002016411f4d0d09200241f8006a41086a200941086a290000370300200241f8006a41106a200941106a2d00003a0000200220022f00b8013b01b001200220092900003703782002200241b8016a41026a2d00003a00b201200241b8016a41036a2800002115200e29000021172008411f6a200241b8016a411f6a290000370000200841186a200241b8016a41186a290000370000200841106a2005290000370000200841086a200241b8016a41086a290000370000200820022900b801370000410121140c040b200242003703b801200241b8016a20152016410820164108491b22131095031a200b201620136b22143602002001201520136a2215360200201641074d0d0820022903b8012104200241b8016a201441c000201441c000491b22136a4100410041c00020136b2013413f4b1b1094031a200241b8016a201520131095031a200b201420136b3602002001201520136a3602002014413f4d0d08200241f8006a41086a200941086a290000370300200241f8006a41106a200941106a290000370300200241f8006a41186a200941186a290000370300200241f8006a41206a200941206a290000370300200241f8006a41286a200941286a290000370300200241f8006a41306a200941306a2d00003a0000200220022f00b8013b01b00120022009290000370378410221142002200241b8016a41026a2d00003a00b201200241b8016a41036a2800002115200e29000021170c040b200241b8016a200110e00120022802b8012215450d0720022902bc012117200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2005290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a2903003703002002200c2d00003a00b201200220022f008c023b01b001200220022903b801370378410021140c020b4101211541002013470d050b200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a2005290300370300200241f8006a41186a200241b8016a41186a290300370300200241f8006a41206a200241b8016a41206a290300370300200241f8006a41286a200241b8016a41286a290300370300200241f8006a41306a200241b8016a41306a290300370300200220022f008c023b01b001200220022903b8013703782002200c2d00003a00b2012013ad22044220862004842117410321140b0b200c20022d00b2013a0000200241b8016a41086a2213200241f8006a41086a22182903003703002005200241f8006a41106a2219290300370300200241b8016a41186a2216200241f8006a41186a221a290300370300200241b8016a41206a221b200241f8006a41206a290300370300200241b8016a41286a221c200241f8006a41286a290300370300200241b8016a41306a221d200241f8006a41306a290300370300200220022f01b0013b018c02200220022903783703b801200241f4006a41026a221e200c2d00003a0000200241386a41086a221f2013290300370300200241386a41106a22202005290300370300200241386a41186a22212016290300370300200241386a41206a2222201b290300370300200241386a41286a221b201c290300370300200241386a41306a221c201d290300370300200220022f018c023b0174200220022903b80137033820132017370300200720022f01743b0000200741026a201e2d00003a000020052002290338370000200541086a201f290300370000200541106a2020290300370000200541186a2021290300370000200541206a2022290300370000200541286a201b290300370000200541306a201c290300370000200220143a00b801200220153602bc01200d2004370300200241106a200241b8016a10e10120022d00102114200241b8016a411f6a221b200a411f6a2900003700002016200a41186a2900003703002005200a41106a2900003703002013200a41086a2900003703002002200a2900003703b80120144103460d04201141016a2115200241f8006a411f6a221c201b290000370000201a20162903003703002019200529030037030020182013290300370300200220022903b801370378024020112012470d00200f20152015200f491b2212ad42287e2204422088a70d072004a722134100480d0702402011450d00200620102013101a22060d010c0a0b2013101b2206450d090b200620106a221320143a0000201341206a201c290000370000201341196a201a290300370000201341116a2019290300370000201341096a2018290300370000201341016a2002290378370000200f41026a210f201041286a21102015211120152003490d000b0b2000201236020420002006360200200041086a201536020020024190026a24000f0b2013450d00201510190b2002418e026a20022d00b2013a0000200241b8016a41086a2205200241f8006a41086a290300370300200241b8016a41106a2213200241f8006a41106a290300370300200241b8016a41186a2201200241f8006a41186a290300370300200241b8016a41206a200241f8006a41206a290300370300200241b8016a41286a200241f8006a41286a290300370300200241b8016a41306a200241f8006a41306a290300370300200220022f01b0013b018c02200220022903783703b801200241033a0010200241b8016a411f6a200a411f6a2900003700002001200a41186a2900003703002013200a41106a2900003703002005200a41086a2900003703002002200a2900003703b8010b2000410036020002402011450d00200621050340024020052d00002213450d00024020134101470d00200541086a280200450d01200541046a2802001019200541286a2105201041586a22100d020c030b200541146a280200450d00200541106a28020010190b200541286a2105201041586a22100d000b0b02402012450d00200610190b20024190026a24000f0b201520131027000b101d000b102b000b20134108101c000b20134101101c000b201620141027000b070020001086030bd60403027f017e0e7f230041d0006b22022400200241086a2001102d02400240024002400240024002400240024002402002280208450d00200228020c2203ad2204421b88a70d032004420586a72205417f4c0d032005450d012005101b2206450d042003450d020c050b20004100360200200241d0006a24000f0b4101210620030d030b410021054100210e0c030b102b000b20054101101c000b200241306a41186a2107200241306a41106a2108200241306a41086a2109200141046a210a4100210b4100210c4100210d2003210e034020074200370300200842003703002009420037030020024200370330200241306a2001280200220f200a28020022054120200541204922101b22111095031a200a200520116b3602002001200f20116a36020020100d02200d41016a2105200241106a41186a22112007290300370300200241106a41106a220f2008290300370300200241106a41086a22102009290300370300200220022903303703100240200d200e470d00200b20052005200b491b220ead4205862204422088a70d042004a722124100480d040240200d450d002006200c2012101a22060d010c060b2012101b2206450d050b2006200c6a220d2002290310370000200d41186a2011290300370000200d41106a200f290300370000200d41086a2010290300370000200b41026a210b200c41206a210c2005210d20052003490d000b0b2000200e36020420002006360200200041086a2005360200200241d0006a24000f0b200041003602000240200e450d00200610190b200241d0006a24000f0b101d000b20124101101c000b9f0e06057f017e017f027e0b7f017e230041e0006b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00002203450d0020034101470d02200041003a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a29000037000020030d014101450d150c140b200241cb006a2001410c6a280000360000200041013a00002002200141046a29000037004320002002290040370001200041086a200241c7006a2900003700002003450d020b20034101460d1320030d0d200141086a280200450d13200141046a2802001019200241e0006a24000f0b20034103470d0e20022001410c6a280200220436021c2002200141046a2802002205360218200241003a0040200241c0006a2005200441004722061095031a20042006490d032002200420066b220336021c2002200520066a22063602182004450d0e20022d004022044102460d0220044101460d0120040d0e200241003a0040200241c0006a2006200341004722051095031a20032005490d052002200320056b220436021c2002200620056a22053602182003450d0e20022d00400d0e41002106200241c0006a2004412020044120491b22036a41004100412020036b2003411f4b1b1094031a200241c0006a200520031095031a2002200420036b36021c2002200520036a3602182004411f4d0d0e200241146a41026a200241c0006a41026a2d00003a0000200220022f00403b01142002280043210320022900472107200228004f210820022900532109200228005b2104200231005f210a0c0b0b41000d100c110b200241003a0040200241c0006a2006200341004722041095031a20032004490d042002200320046b36021c2002200620046a3602182003450d0c20022d00400d0c200241c0006a200241186a10e00120022802402203450d0c20022902442107200241146a41026a200241c0006a41026a2d00003a0000200220022f00403b0114410121060c090b200241003a0040200241c0006a2006200341004722051095031a20032005490d042002200320056b220436021c2002200620056a22063602182003450d0b20022d00400d0b20024200370340200241c0006a20062004410820044108491b22031095031a2002200420036b36021c2002200620036a360218200441074d0d0b20022903402107200241086a200241186a102d2002280208450d0b200228020c220bad42287e220a422088a70d01200aa72203417f4c0d01024002402003450d002003101b2208450d07200b450d010c080b41082108200b0d070b4100210f4200210a2008450d0b0c070b200620041027000b102b000b200520031027000b200420031027000b200520031027000b20034108101c000b2002280218210c200228021c21044200210a4100210d4100210e41002105200b210f0340200241c0006a2004412020044120491b22036a41004100412020036b2003411f4b1b1094031a200241c0006a200c20031095031a2002200420036b220636021c2002200c20036a22033602182004411f4d0d04200241206a41186a2210200241c0006a41186a2211290000370300200241206a41106a2212200241c0006a41106a2213290000370300200241206a41086a2214200241c0006a41086a22152900003703002002200229004037032020024200370340200241c0006a20032006410820064108491b220c1095031a20022006200c6b220436021c20022003200c6a220c360218200641074d0d04200541016a2106200229034021092011201029030037030020132012290300370300201520142903003703002002200229032037034002402005200f470d00200d20062006200d491b220fad42287e2216422088a70d072016a722034100480d0702402005450d002008200e2003101a22080d010c090b2003101b2208450d080b2008200e6a22032002290340370300200341186a2011290300370300200341106a2013290300370300200341086a2015290300370300200341206a2009370300200a4280808080107c210a200d41026a210d200e41286a210e200621052006200b490d000b2008450d040b200a200fad84210941022106200241146a41026a200241c0006a41026a2d00003a0000200220022f00403b01140b200241c0006a41026a2205200241146a41026a2d00003a0000200220022f01143b0140200020063a0000200041206a200a3700002000411c6a2004360000200041146a2009370000200041106a2008360000200041086a2007370000200041046a2003360000200020022f01403b0001200041036a20052d00003a00000b200141086a280200450d05200141046a28020010190c050b200f450d00200810190b41c9d6c100411e1030000b101d000b20034108101c000b200141086a280200450d00200141046a2802001019200241e0006a24000f0b200241e0006a24000b920101027f230041106b2202240002400240410f101b2203450d00200341076a41002900f39941370000200341002900ec99413700002003410f411e101a2203450d012003200036000f2002411336020c200220033602082001200241086a109801200310190240200141046a280200450d00200128020010190b200241106a24000f0b410f4101101c000b411e4101101c000bf70609047f017e017f017e037f017e047f017e017f23004180066b22022400200241c8026a200110e401200241d8026a280200210320022802d402210420022802d002210520022903c802210620024190056a200241dc026a41e4001095031a024002400240024002400240024002400240024002402005450d00200241086a20024190056a41e4001095031a20022001102d2002280200450d0820022802042207ad42e0017e2208422088a70d032008a72209417f4c0d032009450d012009101b220a450d042007450d020c050b2000410036020820024180066a24000f0b4108210a20070d030b4100210f4200210c200a450d050c030b102b000b20094108101c000b200241c8026a41f8006a210b4200210c4100210d410021094100210e2007210f0340200241c8026a2001103520024190056a200241c8026a41f0001095031a200241c8026a41f0006a2903002108200241a8046a200b41e8001095031a20084203510d02200e41016a2110200241d8016a20024190056a41f0001095031a200241f0006a200241a8046a41e8001095031a0240200e200f470d00200d20102010200d491b220fad42e0017e2211422088a70d052011a722124100480d050240200e450d00200a20092012101a220a0d010c070b2012101b220a450d060b200a20096a200241d8016a41f000109503220e41f0006a2008370300200e41f8006a200241f0006a41e8001095031a200c4280808080107c210c200d41026a210d200941e0016a21092010210e20102007490d000b200a450d020b200241c8026a200241086a41e4001095031a200041106a20033602002000200436020c2000200536020820002006370300200041146a200241c8026a41e4001095031a200041fc006a200c200fad84370200200041f8006a200a36020020024180066a24000f0b0240200e450d00200a4188016a2110034020101043201041e0016a2110200941a07e6a22090d000b0b200f450d00200a10190b2000410036020802402003450d00200341286c2110200521090340024020092d0000220e450d000240200e4101470d00200941086a280200450d01200941046a2802001019200941286a2109201041586a22100d020c030b200941146a280200450d00200941106a28020010190b200941286a2109201041586a22100d000b0b02402004450d00200510190b20024180066a24000f0b101d000b20124108101c000bb80b05077f017e037f017e017f230041d0016b22022400200241b0016a41186a22034200370300200241b0016a41106a22044200370300200241b0016a41086a22054200370300200242003703b001200241b0016a2001280200220620012802042207412020074120491b22081095031a2001200720086b3602042001200620086a360200024002402007411f4d0d0020024190016a41186a2207200329030037030020024190016a41106a2208200429030037030020024190016a41086a22062005290300370300200220022903b00137039001200241f0006a41186a2007290300370300200241f0006a41106a2008290300370300200241f0006a41086a20062903003703002002200229039001370370410121070c010b410021070b200241b0016a41186a2208200241f0006a41186a290300370300200241b0016a41106a2206200241f0006a41106a290300370300200241b0016a41086a2203200241f0006a41086a290300370300200220022903703703b001024002400240024002402007450d00200241306a41186a2008290300370300200241306a41106a2006290300370300200241306a41086a2003290300370300200220022903b0013703302002200110372002290300a7450d0120022903082109200241b0016a41186a22054200370300200241b0016a41106a220a4200370300200241b0016a41086a220b4200370300200242003703b001200241b0016a20012802002204200141046a22032802002207412020074120491b22081095031a2003200720086b22063602002001200420086a22083602002007411f4d0d0220024190016a41186a2207200529030037030020024190016a41106a2204200a29030037030020024190016a41086a2205200b290300370300200220022903b00137039001200241d0006a41186a2007290300370300200241d0006a41106a2004290300370300200241d0006a41086a20052903003703002002200229039001370350200241b0016a2006412020064120491b22076a41004100412020076b2007411f4b1b1094031a200241b0016a200820071095031a2003200620076b3602002001200820076a3602002006411f4d0d0320024190016a41186a2207200241b0016a41186a220329030037030020024190016a41106a2208200241b0016a41106a220429030037030020024190016a41086a2206200241b0016a41086a2205290300370300200220022903b00137039001200241f0006a41186a220a2007290300370300200241f0006a41106a220b2008290300370300200241f0006a41086a220c20062903003703002002200229039001370370200241b0016a200110de0120022802b0012201450d0420022902b401210d2003200241306a41186a2903003703002004200241306a41106a2903003703002005200241306a41086a2903003703002006200241d0006a41086a2903003703002008200241d0006a41106a2903003703002007200241d0006a41186a290300370300200241106a41086a220e200c290300370300200241106a41106a220c200b290300370300200241106a41186a220b200a290300370300200220022903303703b0012002200229035037039001200220022903703703102000200d37020c2000200136020820002009370300200041146a20022903b0013702002000411c6a2005290300370200200041246a20042903003702002000412c6a2003290300370200200041346a2002290390013702002000413c6a2006290300370200200041c4006a2008290300370200200041cc006a2007290300370200200041ec006a200b290300370200200041e4006a200c290300370200200041dc006a200e290300370200200041d4006a2002290310370200200241d0016a24000f0b20004100360208200241d0016a24000f0b20004100360208200241d0016a24000f0b20004100360208200241d0016a24000f0b20004100360208200241d0016a24000f0b20004100360208200241d0016a24000bf60404017f017e027f017e230041d0006b2205240042002106200541c0006a41086a220742003703002005420037034041dadbc1004111200541c0006a1001200541206a41086a220820072903003703002005200529034037032042002109024002400240200541206a411041d889c200410041001000417f460d0020054200370340200541206a4110200541c0006a41084100100041016a41084d0d01200529034021090b200520024200200320041099032005200920017c20027d370330200742003703002005420037034041dadbc1004111200541c0006a10012008200729030037030020052005290340370320200541206a4110200541306a41081003200541106a2000104520002005290300220920052903107c2202200541086a2903002201200541106a41086a2903007c2002200954ad7c1046200742003703002005420037034041a7fbc0004116200541c0006a1001200541306a41086a20072903003703002005200529034037033002400240200541306a411041d889c200410041001000417f460d002005420037034820054200370340200541306a4110200541c0006a4110410010002207417f460d032007410f4d0d03200541c8006a2903002102200529034021060c010b420021020b0240200620097c22092006542207200220017c2007ad7c220620025420062002511b0d002005200937033020052006370338200541c0006a41086a220742003703002005420037034041a7fbc0004116200541c0006a1001200541206a41086a200729030037030020052005290340370320200541206a4110200541306a411010030b200541d0006a24000f0b41fcf9c00041331030000b41fcf9c00041331030000bd20a02027f097e230041f0006b22032400200341e0006a41086a220442003703002003420037036041fcdbc1004116200341e0006a1001200341d0006a41086a2004290300370300200320032903603703500240024002400240024002400240200341d0006a411041d889c200410041001000417f460d0020034200370360200341d0006a4110200341e0006a41084100100041016a41084d0d02200329036021050c010b42c0843d21050b42002106200341e0006a41086a220442003703002003420037036041dadbc1004111200341e0006a1001200341c0006a41086a2004290300370300200320032903603703400240200341c0006a411041d889c200410041001000417f460d0020034200370360200341c0006a4110200341e0006a41084100100041016a41084d0d02200329036021060b02400240200520067d20025a0d00200041e2e2c100360204200041086a411b360200410121040c010b42002105200341e0006a41086a220442003703002003420037036041ebdbc1004111200341e0006a1001200341d0006a41086a20042903003703002003200329036037035002400240200341d0006a411041d889c200410041001000417f460d002003420037036820034200370360200341d0006a4110200341e0006a4110410010002204417f460d052004410f4d0d05200341e8006a2903002105200329036021060c010b420121060b42002107200341106a2005420020024200109903200341206a200242002006420010990320034200420020064200109903200341306a2001104502402003290308200329031884420052200341206a41086a2903002208200329030020032903107c7c220920085472450d002000418880c100360204200041086a4127360200410121040c010b200341306a41086a290300210a2003290320210b20032903302108200341e0006a41086a220442003703002003420037036041e6fbc000411b200341e0006a1001200341d0006a41086a20042903003703002003200329036037035002400240200341d0006a411041d889c200410041001000417f460d002003420037036820034200370360200341d0006a4110200341e0006a4110410010002204417f460d062004410f4d0d06200341e8006a290300210c200329036021070c010b4200210c0b02402008200b7d220d200856200a20097d2008200b54ad7d2208200a562008200a511b200d2007542008200c542008200c511b72450d00200041af80c100360204200041086a4124360200410121040c010b2001200d2008104642002108200341e0006a41086a220442003703002003420037036041a7fbc0004116200341e0006a1001200341d0006a41086a20042903003703002003200329036037035002400240200341d0006a411041d889c200410041001000417f460d002003420037036820034200370360200341d0006a4110200341e0006a4110410010002204417f460d072004410f4d0d07200341e8006a290300210a200329036021080c010b4200210a0b02402008200b7d2207200856200a20097d2008200b54ad7d2208200a562008200a511b0d002003200737035020032008370358200341e0006a41086a220442003703002003420037036041a7fbc0004116200341e0006a1001200341c0006a41086a200429030037030020032003290360370340200341c0006a4110200341d0006a411010030b200041206a2005370300200041186a2006370300200041106a2002370300200041086a2002370300410021040b20002004360200200341f0006a24000f0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b130020004103360204200041d080c3003602000b130020004107360204200041fd83c1003602000b130020004108360204200041bc82c3003602000b1300200041023602042000419488c3003602000b1300200041083602042000419a89c1003602000b130020004107360204200041f489c3003602000b86090b107f017e017f017e017f017e017f017e017f017e017f230041306b22022400024002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d032001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200241286a22082000200441306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e2903003703002013201029030037030020052002290300370300200320014f0d022006410d7420067322044111762004732204410574200473220620077122044100200120042001491b6b220520014f0d01200241286a22082000200341306c6a220441286a2209290300370300200241206a220a200441206a220b290300370300200241186a220c200441186a220d290300370300200241106a220e200441106a220f290300370300200241086a2210200441086a2211290300370300200220042903003703002000200541306c6a22052903002112200541086a22132903002114200541106a22152903002116200541186a22172903002118200541206a2219290300211a2009200541286a221b290300370300200b201a370300200d2018370300200f20163703002011201437030020042012370300201b20082903003703002019200a2903003703002017200c2903003703002015200e29030037030020132010290300370300200520022903003703002003410172220420014f0d032006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200241286a22032000200441306c6a220141286a2204290300370300200241206a2206200141206a2207290300370300200241186a2208200141186a2209290300370300200241106a220a200141106a220b290300370300200241086a220c200141086a220d290300370300200220012903003703002000200541306c6a22002903002112200041086a22052903002114200041106a220e2903002116200041186a220f2903002118200041206a2210290300211a2004200041286a22112903003703002007201a37030020092018370300200b2016370300200d2014370300200120123703002011200329030037030020102006290300370300200f2008290300370300200e200a2903003703002005200c290300370300200020022903003703000b200241306a24000f0b419890c30020052001104a000b200321040b418890c30020042001104a000bf30b05087f027e107f017e017f230041306b22022400200041c07e6a2103200041506a21044100210520014132492106410121070240024002400340024002400240200720014f0d002004200741306c6a210803402008290300200841306a220929030054200841086a290300220a200841386a290300220b54200a200b511b0d0220092108200741016a22072001490d000b0b410021082007200146210920060d030c010b410121082007200146210920060d020b20072001460d012007417f6a220920014f0d022008450d032000200941306c6a2208290300210a20082000200741306c220c6a2209290300370300200241286a220d200841286a220e290300370300200241206a220f200841206a2210290300370300200241186a2211200841186a2212290300370300200241106a2213200841106a2214290300370300200241086a2215200841086a22162903003703002016200941086a22172903003703002014200941106a22182903003703002012200941186a22192903003703002010200941206a221a290300370300200e200941286a221b2903003703002002200a370300201b200d290300370300201a200f29030037030020192011290300370300201820132903003703002017201529030037030020092002290300370300024020074102490d0020002007417e6a220f41306c6a220d2903002008290300221c5a200d41086a221d290300220b2016290300220a5a200b200a511b0d002008200d2903003703002016201d2903003703002008290310210b2014200d41106a2903003703002011200e29030037030020132010290300370300201520122903003703002012200d41186a2903003703002010200d41206a290300370300200e200d41286a2903003703002002200b3703000240024002400240200f450d0020002007417d6a221641306c6a2208290300201c5a200841086a290300220b200a5a200b200a511b0d032003200c6a2108034020084188016a200841d8006a29030037030020084180016a200841d0006a290300370300200841f8006a200841c8006a290300370300200841f0006a200841c0006a290300370300200841e8006a200841386a290300370300200841e0006a200841306a2903003703002016450d022008290300210b200841086a210d200841506a21082016417f6a2116200b201c54200d290300220b200a54200b200a511b0d000b201641016a210f0c020b4100210f0c020b4100210f0b2000200f41306c6a210d0b200d201c370300200d200a3703082000200f41306c6a22082002290300370310200841286a2011290300370300200841206a2013290300370300200841186a20152903003703000b200541016a21050240200120076b220e4102490d002009290300221c20092903305a2017290300220a200941386a290300220b5a200a200b511b0d002009200941306a22162903003703002017201641086a2903003703002009290310210b2018201641106a2903003703002011201b2903003703002013201a290300370300201520192903003703002019201641186a290300370300201a201641206a290300370300201b201641286a2903003703002002200b370300410121100240200e4103490d00201c20092903605a200a200941e8006a290300220b5a200a200b511b0d00200941e0006a21084103210d41022117034020092017221041306c6a221641786a200841286a290300370300201641706a200841206a290300370300201641686a200841186a290300370300201641606a200841106a290300370300201641586a200841086a290300370300201641506a2008290300370300200d200e4f0d01200d41306c2108200d2117200d41016a210d201c200920086a220829030054200a200841086a290300220b54200a200b511b0d000b0b2016201c3703002016200a3703082009201041306c6a22082002290300370310200841286a2011290300370300200841206a2013290300370300200841186a20152903003703000b20054105490d000b410021090b200241306a240020090f0b418890c30020092001104a000b419890c30020072001104a000bdd0b09167f017e037f017e017f017e017f027e0c7f230041306b2202240002400240024020014101762203450d00417f210441022105413021064108210741282108412021094118210a4110210b4100210c0c010b4100210d0c010b4101210d0b03400240024002400240024002400240024002400240024002400240200d0e020001010b4102212420014102490d01417f2125412821264120212741182128411021294108212a4130212b4101212c2001212d4101210c0c0b0b02400240200c0e020001010b200320046a2203210d0340200d410174221a41017221230240201a20056a221a20014f0d00202320014f0d06201a20232000201a20066c6a22172903002000202320066c6a221929030054201720076a2903002218201920076a290300221c542018201c511b1b21230b0240202320014f0d00200d20014f0d042000202320066c6a221a2903002000200d20066c6a220d2903005a201a20076a22192903002218200d20076a2217290300221c5a2018201c511b0d00200220086a220e200d20086a220f290300370300200220096a2210200d20096a22112903003703002002200a6a2212200d200a6a22132903003703002002200b6a2214200d200b6a2215290300370300200220076a221620172903003703002002200d29030037030020192903002118201a200b6a221b290300211c201a200a6a221d290300211e201a20096a221f2903002120201a2903002121200f201a20086a2222290300370300201120203703002013201e3703002015201c37030020172018370300200d20213703002022200e290300370300201f2010290300370300201d2012290300370300201b201429030037030020192016290300370300201a20022903003703002023210d0c010b0b20030d074100210d0c0c0b202d20256a222d20014f0d05200220266a220e200020266a221a290300370300200220276a220f200020276a2223290300370300200220286a2210200020286a2217290300370300200220296a2211200020296a22192903003703002002202a6a22122000202a6a2213290300370300200220002903003703002000202d202b6c6a220d2903002118200d202a6a2214290300211c200d20296a2215290300211e200d20286a22162903002120200d20276a221b2903002121201a200d20266a221d29030037030020232021370300201720203703002019201e3703002013201c37030020002018370300201d200e290300370300201b200f290300370300201620102903003703002015201129030037030020142012290300370300200d20022903003703004100210d0340200d202c74221a202c7221230240201a20246a221a202d4f0d002023202d4f0d06201a20232000201a202b6c6a221729030020002023202b6c6a2219290300542017202a6a29030022182019202a6a290300221c542018201c511b1b21230b02402023202d4f0d00200d202d4f0d0420002023202b6c6a221a2903002000200d202b6c6a220d2903005a201a202a6a22192903002218200d202a6a2217290300221c5a2018201c511b0d00200e200d20266a2213290300370300200f200d20276a22142903003703002010200d20286a22152903003703002011200d20296a2216290300370300201220172903003703002002200d29030037030020192903002118201a20296a221b290300211c201a20286a221d290300211e201a20276a221f2903002120201a29030021212013201a20266a2222290300370300201420203703002015201e3703002016201c37030020172018370300200d20213703002022200e290300370300201f200f290300370300201d2010290300370300201b201129030037030020192012290300370300201a20022903003703002023210d0c010b0b202d202c4b0d070b200241306a24000f0b41e090c300200d2001104a000b41e090c300200d202d104a000b41d090c30020232001104a000b41d090c3002023202d104a000b419890c300202d2001104a000b4100210c0c010b4101210c0c010b4101210d0c020b4101210d0c010b4101210d0c000b0b1c00200128021841fba4c200410e2001411c6a28020028020c1100000b1100200120002802002000280204108f030b4b02017f017e230041206b2202240020012902002103200241146a20012902083702002002200337020c2002200036020820024184d9c300360204200241d889c2003602002002108203000b820101017f230041c0006b220424002004200136020c2004200036020820042003360214200420023602102004413c6a41093602002004412c6a4102360200200441033602342004420237021c200441d4d8c3003602182004200441106a3602382004200441086a3602302004200441306a360228200441186a41e4d8c30010f201000bc90801127f230041306b220224002000280204210320002802002104410121050240200128021841222001411c6a2802002802101104000d00024002402003450d00200420036a21062002410c6a2107200241086a2108200141186a21092001411c6a210a2004210b4100210c4100210d02400340200b210e200b41016a21000240024002400240200b2c0000220f4100480d00200f41ff0171210f0c010b02400240024020002006460d0020002d0000413f712110200b41026a220b2100200f411f712111200f41ff0171220f41e001490d010c020b410021102006210b200f411f712111200f41ff0171220f41e0014f0d010b2010201141067472210f0c010b02400240200b2006460d00200b41016a22002112200b2d0000413f712010410674722110200f41f001490d010c030b2006211241002010410674722110200f41f0014f0d020b20102011410c7472210f0b2000210b0c010b0240024020122006460d00201241016a210b20122d0000413f71210f0c010b4100210f2000210b0b20104106742011411274418080f0007172200f72220f418080c400460d020b2002200f1085020240200228020022004101460d00024020004103470d00200828020020072d00006a4101460d010b20022003360214200220043602102002200c3602182002200d36021c0240200d200c490d000240200c450d00200c2003460d00200c20034f0d012004200c6a2c000041bf7f4c0d010b0240200d450d00200d2003460d00200d20034f0d012004200d6a2c000041bf7f4c0d010b024020092802002004200c6a200d200c6b200a28020028020c1100000d0020072d000021102008280200211220022802042111034002400240024002400240024020004101460d0041dc00210c024020004102460d0020004103470d05201041ff01712100410421102000417f6a221341044b0d0541032100024020130e050004050307000b4100211041fd00210c0c060b410121000c050b410021002011210c2011418080c400460d030c040b4103211041f500210c410321000c030b20112012410274411c7176410f71220c413072200c41d7006a200c410a491b210c4102410120121b21102012417f6a410020121b21120c020b4102211041fb00210c0c010b410121000240200f418001490d0041022100200f418010490d0041034104200f41808004491b21000b2000200d6a210c0c040b2009280200200c200a280200280210110400450d000b0b200241306a240041010f0b20022002411c6a3602282002200241186a3602242002200241106a360220200241206a108602000b200d200e6b200b6a210d2006200b470d000b0b200c450d01200c2003460d010240200c20034f0d002004200c6a2c000041bf7f4a0d020b20042003200c2003108702000b4100210c0b200141186a22002802002004200c6a2003200c6b2001411c6a220b28020028020c1100000d0020002802004122200b28020028021011040021050b200241306a240020050b1c00200128021841f0a4c200410b2001411c6a28020028020c1100000bcd0603047f037e037f230041206b22022400200241003a001020012802002001280204200241106a410120012802081000210320012001280208200341016a41014b22036a22043602080240024002402003450d0002400240024002400240024020022d001022054103712203450d0020034101460d0120034102470d0220024100360210200220053a0010200141086a220341002001280200200141046a280200200241106a41017241032004100022012001417f461b22014103200141034922011b20032802006a36020020010d062002280210410276ad21060c030b2005410276ad21060c020b200241003b0110200220053a00102001280200200141046a280200200241106a4101724101200410002103200141086a22012001280200200341016a220141014b6a36020020014102490d0420022f0110410276ad21060c010b0240024020054102762203450d0020034104460d012003410c470d04420021072002420037031820024200370310200141086a220341002001280200200141046a280200200241106a41102004100022012001417f461b22014110200141104922011b20032802006a36020020010d06200241106a41086a2903002108200229031021060c030b200141046a280200210320024100360210200141086a2205410020012802002003200241106a41042004100022012001417f461b22014104200141044922011b20052802006a36020020010d04200235021021060c010b4200210720024200370310200141086a220341002001280200200141046a280200200241106a41082004100022012001417f461b22014108200141084922011b20032802006a36020020010d04200229031021060b420021080b420121070c030b200341046a220941104b0d00200141046a210a200141086a21054200210642002108410021030340200241003a00102001280200200a280200200241106a410120041000210420052005280200200441016a41014b220b6a2204360200200b450d01200220023100104200200341037441f80071109a03200241086a29030020088421082002290300200684210642012107200341016a220341ff01712009490d000c030b0b420021070b0b2000200637030820002007370300200041106a2008370300200241206a24000b130020004100360204200041d889c2003602000b13002000410736020420004189a2c1003602000b130020004102360204200041e896c3003602000b1300200041063602042000419098c3003602000b130020004109360204200041afa6c1003602000b13002000410f360204200041d09cc3003602000b4901017f230041106b2202240020024100360208200242013703002002410036020c2002410c6a2002105d200041086a200228020836020020002002290300370200200241106a24000b130020004101360204200041bca7c3003602000b130020004109360204200041e0b5c1003602000b130020004103360204200041c0a8c3003602000bcd0202027f017e23004180016b22022400200028020021000240024002400240200128020022034110710d002000290300210420034120710d0120042001108202210020024180016a240020000f0b200029030021044180012100024003402000450d01200220006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b0b20004181014f0d012001410141b68cc2004102200220006a41800120006b108302210020024180016a240020000f0b4180012100024003402000450d01200220006a417f6a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b0b20004181014f0d012001410141b68cc2004102200220006a41800120006b108302210020024180016a240020000f0b20004180011027000b20004180011027000bdd0203037f017e027f230041306b220224004127210302400240024020004290ce00540d00412721030340200241096a20036a2204417c6a200020004290ce0080220542f0b17f7e7ca7220641e4006e2207410174418a8ac2006a2f00003b00002004417e6a2007419c7f6c20066a410174418a8ac2006a2f00003b00002003417c6a2103200042ffc1d72f5621042005210020040d000b41e40021062005a7220441e400480d020c010b41e400210620002205a7220441e400480d010b200241096a2003417e6a22036a2005a7220741ffff037120066e2204419c7f6c20076a41ffff0371410174418a8ac2006a2f00003b00000b02400240200441094a0d00200241096a2003417f6a22036a200441306a3a00000c010b200241096a2003417e6a22036a2004410174418a8ac2006a2f00003b00000b2001410141d889c2004100200241096a20036a412720036b1083022103200241306a240020030bee0b01087f230041106b220624000240024002402001450d00412b418080c4002000280200220741017122011b2108200120056a21094102210a2007410471220b450d020c010b200541016a2109412d21084102210a20002802002207410471220b450d010b4100210c02402003450d002003210d200221010340200c20012d000041c00171418001466a210c200141016a2101200d417f6a220d0d000b0b200920036a200c6b21090b200b200a76210a02400240024002400240024002400240024002400240024002400240024002400240024020002802084101470d002000410c6a280200220c20094d0d0120074108710d02200c20096b210d410120002d0030220120014103461b4103712201450d0320014102460d04410021090c050b02402008418080c400460d0041012101200028021820082000411c6a2802002802101104000d100b0240200a450d00410121012000280218200220032000411c6a28020028020c1100000d100b2000280218200420052000411c6a28020028020c1100002101200641106a240020010f0b02402008418080c400460d0041012101200028021820082000411c6a2802002802101104000d0f0b0240200a450d00410121012000280218200220032000411c6a28020028020c1100000d0f0b2000280218200420052000411c6a28020028020c1100002101200641106a240020010f0b41012101200041013a00302000413036020402402008418080c400460d00200028021820082000411c6a2802002802101104000d0e0b0240200a450d002000280218200220032000411c6a28020028020c1100000d0e0b200c20096b210d4101200041306a2d0000220120014103461b4103712201450d0420014102460d03410021030c050b200d21094100210d0c010b200d41016a4101762109200d410176210d0b2006410036020c02402000280204220141ff004b0d00200620013a000c4101210c0c050b0240200141ff0f4b0d0020062001413f71418001723a000d20062001410676411f7141c001723a000c4102210c0c050b200141ffff034b0d0320062001413f71418001723a000e20062001410676413f71418001723a000d20062001410c76410f7141e001723a000c4103210c0c040b200d41016a4101762103200d410176210d0c010b200d21034100210d0b200641003602080240200041046a280200220141ff004b0d00200620013a00084101210c0c060b200141ff0f4b0d0220062001413f71418001723a000920062001410676411f7141c001723a00084102210c0c050b20062001413f71418001723a000f2006200141127641f001723a000c20062001410676413f71418001723a000e20062001410c76413f71418001723a000d4104210c0b417f210102400340200141016a2201200d4f0d01200041186a2802002006410c6a200c2000411c6a28020028020c110000450d000c060b0b02402008418080c400460d00200041186a28020020082000411c6a2802002802101104000d050b0240200a450d00200041186a280200200220032000411c6a28020028020c1100000d050b200041186a220d280200200420052000411c6a220028020028020c1100000d04417f21010340200141016a220120094f0d02200d2802002006410c6a200c200028020028020c110000450d000c050b0b200141ffff034b0d0120062001413f71418001723a000a20062001410676413f71418001723a000920062001410c76410f7141e001723a00084103210c0c020b200641106a240041000f0b20062001413f71418001723a000b2006200141127641f001723a000820062001410676413f71418001723a000a20062001410c76413f71418001723a00094104210c0b417f210102400340200141016a2201200d4f0d01200041186a280200200641086a200c2000411c6a28020028020c110000450d000c020b0b200041186a220d280200200420052000411c6a220028020028020c1100000d00417f21010340200141016a220120034f0d03200d280200200641086a200c200028020028020c110000450d000b0b410121010b200641106a240020010f0b200641106a240041000b950605027f027e017f027e027f230041a0016b22022400200028020021000240024002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0120054290ce005441002004501b0d0241272100200241186a21060340200241106a200520044290ce0042001098032002200229031022072006290300220842f0b17f427f109903200241206a20006a2203417c6a200520022903007ca7220941e4006e220a410174418a8ac2006a2f00003b00002003417e6a200a419c7f6c20096a410174418a8ac2006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000b41e40021092007a7220341e4004e0d030c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d032001410141b68cc2004102200241206a20006a41800120006b1083022100200241a0016a240020000f0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d032001410141b68cc2004102200241206a20006a41800120006b1083022100200241a0016a240020000f0b4127210041e40021092005a7220341e400480d030b200241206a2000417e6a22006a2003200341ffff037120096e2209419c7f6c6a41ffff0371410174418a8ac2006a2f00003b0000200941094a0d030c040b20004180011027000b20004180011027000b2003220941094c0d010b200241206a2000417e6a22006a2009410174418a8ac2006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141d889c2004100200241206a20006a412720006b1083022100200241a0016a240020000b9f0b03037f017e167f4102210202400240024002400240024002400240024002400240024002400240024002400240200141776a2203411e4b0d0041f4002104024020030e1f110002020302020202020202020202020202020202020202020f020202020f110b41ee0021040c030b200141dc00460d0d0b20014180104f0d02200141037641f8ffffff017141b0dbc3006a21040c030b41f20021040b0c0c0b02402001418080044f0d00200141067641606a220441e0074f0d02200441c8ddc3006a2d0000220441c9004b0d03200441037441f097c2006a21040c010b2001410c7641706a22044180024f0d03200441a8e5c3006a2d00004106742001410676413f7172220441ff034b0d04200441c09cc2006a2d0000220441364b0d05200441037441c0a0c2006a21040b0240200429030042012001413f71ad8683500d00200141017267410276410773ad4280808080d0008421050c080b0240200141ffff034b0d0020014180fe0371410876210641b88dc2002107410021084102210941b002210a41888ec200210b41888ec200210c417f210d4101210e200141ff0171210f410021040c060b0240200141ffff074b0d0020014180fe0371410876211241f392c20021134100211441022115419f01211641b593c200211741b593c2002118417f21194101211a200141ff0171211b410121040c060b200141ef83384b0d06200141e28b746a41e28d2c490d062001419fa8746a419f18490d06200141dee2746a410e490d06200141feffff0071419ef00a460d06200141a9b2756a4129490d06200141cb91756a410a4d0d06410121020c080b41a8e7c300200441e007104a000b41b8e7c300200441ca00104a000b41c8e7c3002004418002104a000b41d8e7c3002004418004104a000b41e8e7c30020044137104a000b03400240024020040e020001010b200720096a2110200820072d000122046a2111024002400240024002400240024020072d000022022006470d0020112008490d062011200a4f0d052008200b6a210203402004450d022004200d6a210420022d000021032002200e6a21022003200f470d000c0a0b0b200220064b0d0120112108201021072010200c470d030c010b20112108201021072010200c470d010b200141ffff0371210241b790c20021044101210302400340200441016a210f0240024020042d0000220e411874411875220d417f4c0d00200f21042002200e6b22024100480d030c010b0240200f41f392c200460d00200441016a210f200441026a21042002200d41ff0071410874200f2d0000726b220241004e0d010c030b41acdac3001029000b20034101732103200441f392c200470d000b0b410121022003410171450d060c080b410021040c040b410021040c030b201141af021028000b200820111027000b201320156a2110201420132d000122046a21110240024002400240024002400240024020132d000022022012470d0020112014490d03201120164f0d04201420176a210203402004450d02200420196a210420022d000021032002201a6a21022003201b470d000c0a0b0b200220124b0d01201121142010211320102018470d050c010b201121142010211320102018470d050b200141ffff0371210241d394c20021044101210302400340200441016a210f0240024020042d0000220e411874411875220d417f4c0d00200f21042002200e6b220241004e0d010c030b200f41d097c200460d05200441016a210f200441026a21042002200d41ff0071410874200f2d0000726b22024100480d020b20034101732103200441d097c200470d000b0b410121022003410171450d060c080b201420111027000b2011419e011028000b41acdac3001029000b410121040c010b410121040c000b0b200141017267410276410773ad4280808080d0008421050b410321020c010b0b200121040b2000200436020420002002360200200041086a20053702000b2701017f20002802002201280200200128020420002802042802002000280208280200108702000bd60801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b21074180022108024003400240200820014f0d00200020086a2c000041bf7f4a0d020b2008417f6a21064100210520084101460d02200720086a21092006210820094101470d000c020b0b41002105200821060b200420063602142004200036021020044100410520051b36021c200441d889c20041b88cc20020051b360218024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b20042002360220024002402002450d0020022001460d00200141016a210903400240200220014f0d00200020026a2c000041404e0d020b2002417f6a210820024101460d0220092002462106200821022006450d000c020b0b200221080b20082001460d02410121064100210502400240200020086a22092c000022024100480d002004200241ff0171360224200441286a21020c010b200020016a220621010240200941016a2006460d00200941026a2101200941016a2d0000413f7121050b2002411f712109024002400240200241ff017141e001490d004100210020062107024020012006460d00200141016a210720012d0000413f7121000b20002005410674722101200241ff017141f001490d0141002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d060c020b200520094106747221010c010b20012009410c747221010b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441ec006a4103360200200441e4006a4103360200200441c8006a41146a410a360200200441d4006a410b360200200441306a41146a4105360200200420023602582004410236024c20044205370234200441c4dac3003602302004200441186a3602682004200441106a3602602004200441246a3602502004200441206a3602482004200441c8006a360240200441306a41ecdac30010f201000b20042002200320081b360228200441c8006a41146a4103360200200441d4006a4103360200200441306a41146a41033602002004410236024c20044203370234200441d4d9c3003602302004200441186a3602582004200441106a3602502004200441286a3602482004200441c8006a360240200441306a41ecd9c30010f201000b200441e4006a4103360200200441c8006a41146a4103360200200441d4006a4102360200200441306a41146a41043602002004410236024c20044204370234200441fcd9c3003602302004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a3602482004200441c8006a360240200441306a419cdac30010f201000b41acdac3001029000bc50201037f23004180016b22022400200028020021000240024002400240200128020022034110710d0020034120710d0120002001108902210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441d7006a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141b68cc2004102200220006a4180016a410020006b108302210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441376a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141b68cc2004102200220006a4180016a410020006b108302210020024180016a240020000f0b20034180011027000b20034180011027000be20201067f230041306b2202240041272103024002400240024002400240200028020022004190ce00490d00412721030340200241096a20036a2204417c6a200020004190ce006e220541f0b17f6c6a220641e4006e2207410174418a8ac2006a2f00003b00002004417e6a20062007419c7f6c6a410174418a8ac2006a2f00003b00002003417c6a2103200041ffc1d72f4b21042005210020040d000b41e4002104200541e400480d010c020b41e40021042000220541e4004e0d010b2005220441094a0d010c020b200241096a2003417e6a22036a200541ffff037120046e2204419c7f6c20056a41ffff0371410174418a8ac2006a2f00003b0000200441094c0d010b200241096a2003417e6a22006a2004410174418a8ac2006a2f00003b00000c010b200241096a2003417f6a22006a200441306a3a00000b2001410141d889c2004100200241096a20006a412720006b1083022100200241306a240020000bcf0101047f200020014105746a210320002104024002400340200320046b41ff004d0d014101210520042002460d02200420024120109703450d02200441206a22062002460d02200620024120109703450d02200441c0006a22062002460d02200620024120109703450d02200441e0006a22062002460d0220044180016a21042006200241201097030d000c020b0b024020042003460d00200020014105746a210603404101210520022004460d02200420024120109703450d022006200441206a2204470d000b0b41000f0b20050bc91c04027f027e047f037e23004190016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d000240024020030e0d002c05080c0a0607040b030901000b200241206a200141086a1073200041013a0000200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a28020022034102460d0b20034103470d2b41012103200141086a2d00004101470d142001410c6a28020021010c150b200141086a2903004202520d2b200041003a0000200041086a4202370300200041106a200141106a29030037030020024190016a24000f0b200141086a280200417e6a220341044b0d2b024020030e05001e1c1d1b000b200141386a2903002104200141306a2903002105410121032001410c6a2d00004101470d25200141106a28020021010c260b200141046a2d000022034102460d094103210620034103470d2b200241f2006a200141076a2d00003a0000200241206a41086a200141186a2900003703002002412d6a2001411d6a2900003700002002200141056a2f00003b01702002200141106a290000370320200141256a2d00004100472107200141286a28020021082001410c6a2800002103200141086a28000021090c0a0b200141086a28020022034102460d0a20034103470d2b410121062001410c6a2d00004101470d13200141106a28020021070c140b200241206a200141086a10a301200041073a0000200041c0006a200241206a41386a290300370300200041386a200241206a41306a290300370300200041306a200241206a41286a290300370300200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141086a2d0000417e6a220341044b0d2a024020030e0500201d1e1c000b41d800101b2203450d3020032001410c6a28020010c501410221010c200b41022103200141086a2d000022064102460d0b4103210320064103460d0a4104210320064104470d2a200141096a2d000041004721010c0c0b200241206a200141086a10c601200041086a200241206a41d0001095031a2000410c3a000020024190016a24000f0b200241206a200141086a10c701200041063a0000200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b200141046a2802004102470d28200141106a2802002203417f4c0d29200141086a28020021012003450d052003101b22060d0620034101101c000b200241206a200141086a10b901200041053a0000200041286a200241206a41206a290300370300200041206a200241206a41186a290300370300200041186a200241206a41106a290300370300200041106a200241206a41086a290300370300200041086a200229032037030020024190016a24000f0b41d800101b2203450d282003200141086a28020010c801410221060c0a0b200141086a280200210941d800101b2203450d2820032001410c6a28020010c901410221060b200041093a0000200041056a20022f01703b0000200041046a20063a00002000410c6a2003360200200041086a2009360200200041106a2002290320370200200041286a2008360200200041256a20073a0000200041076a200241f2006a2d00003a0000200041186a200241206a41086a2903003702002000411d6a2002412d6a29000037000020024190016a24000f0b410121062001410c6a2d00004101470d0a200141106a28020021070c0b0b410121060b2006200120031095032101200041106a20033602002000410c6a2003360200200041086a2001360200200041046a41023602002000410a3a000020024190016a24000f0b200141106a29030021040c010b200241f4006a2001410e6a2f00003b0100200241206a41086a200141206a290000370300200241206a41106a200141286a2d00003a000020022001410a6a2800003602702002200141186a290000370320200141106a2900002104200141096a2d000021010b200041043a0000200041096a20013a0000200041086a20033a00002000410a6a2002280270360100200041106a2004370300200041186a20022903203703002000410e6a200241f0006a41046a2f01003b0100200041206a200241206a41086a290300370300200041286a200241206a41106a29030037030020024190016a24000f0b200241206a41086a200141186a290000370300200241206a41106a200141206a290000370300200241206a41186a200141286a2d00003a00002002200141106a290000370320200141096a2f00002001410b6a2d00004110747221062001410c6a2800002101410021030b200241f0006a41186a200241206a41186a280200360200200241f0006a41106a200241206a41106a290300370300200241f0006a41086a200241206a41086a2903003703002002200229032037037020032006410874722103410321060b2000410d3a00002000410c6a2001360200200041086a2003360200200041046a2006360200200041106a2002290370370200200041186a200241f0006a41086a290300370200200041206a200241f0006a41106a290300370200200041286a200241f0006a41186a28020036020020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241f0006a41086a290300370300200241086a41106a200241f0006a41106a28020036020020022002290370370308200141c8006a2903002105200141c0006a290300210a200141386a290300210b200141306a290300210c410321010c020b200241286a2001411c6a290000370300200241206a41106a200141246a2800003602002002200141146a290000370320200141286a3500002001412c6a3100004220868421042001410d6a2f00002001410f6a2d0000411074722103200141106a2800002107410021060b200241086a41086a200241206a41086a290300370300200241086a41106a200241206a41106a28020036020020022002290320370308200141386a290300210b200141306a290300210c410221010b200041033a00002000410f6a20034110763a00002000410d6a20033b0000200041c8006a2005370300200041c0006a200a370300200041386a200b370300200041306a200c370300200041106a20073602002000410c6a20063a0000200041086a2001360200200041146a2002290308370200200041286a20043702002000411c6a200241086a41086a290300370200200041246a200241086a41106a28020036020020024190016a24000f0b2001410c6a28020022034108762106410621010c030b200241206a41106a200141206a2903003703002002200141186a2903003703282002200141106a2802003602202001410c6a28020022034108762106200141286a290300210a410421010c0b0b2001410c6a28020022034108762106410521010c010b2002200141186a2903003703282002200141106a29030037032041032101410021030b0c080b200141106a2903002104410621010c020b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141106a29000021042001410c6a2800002103410421010c030b200141106a2903002104410521010b0c010b2002410a6a2001410b6a2d00003a0000200241286a200141206a290000370300200241206a41106a200141286a2d00003a00002002200141096a2f00003b01082002200141186a290000370320200141296a2d00004100472106200141106a29000021042001410c6a2800002103410321010b200041096a20022f01083b0000200041086a20013a0000200041106a20043703002000410c6a2003360200200041186a2002290320370300200041296a20063a00002000412a6a20022801703601002000410b6a2002410a6a2d00003a0000200041206a200241206a41086a290300370300200041286a200241206a41106a2d00003a00002000412e6a200241f4006a2f01003b0100200041083a000020024190016a24000f0b200241f8006a2001411c6a290000370300200241f0006a41106a200141246a2800003602002002200141146a290000370370200141286a3500002001412c6a31000042208684210a2001410d6a2f00002001410f6a2d0000411074722106200141106a2800002101410021030b2002412c6a200241f8006a290300370200200241346a20024180016a2802003602002002200229037037022420022001360220410221010b2000410b3a0000200041386a2004370300200041306a2005370300200041086a2001360200200041106a2002290320370300200041286a200a3703002000410c6a2006410874200341ff017172360200200041186a200241206a41086a290300370300200041206a200241206a41106a29030037030020024190016a24000f0b10ca01000b41dceec2001029000b41f895c3001029000b41f0fcc2001029000b41d0aec3001029000b41a080c3001029000b41a8e5c2001029000b418880c3001029000b41f4c1c3001029000b102b000b41d8004108101c000b41d8004108101c000b41d8004108101c000bf40403037f027e067f230041206b220224000240024002404113101b2203450d002003410f6a41002800bf9f41360000200341086a41002900b89f41370000200341002900b09f41370000200341134126101a2204450d01200420003600132002410036021820024201370310200141086a2903002105200129030021064110101b2203450d02200320063700002003200537000820024290808080800237021420022003360210200128021021072002200141186a28020022033602002002200241106a105d02400240024002402003450d0020034105742108200241106a41086a2802002100200228021021092002280214210a2007210303400240024002400240200a20006b41204f0d00200041206a220b2000490d07200a410174220c200b200b200c491b220c4100480d07200a450d012009200a200c101a22090d020c080b200041206a210b0c020b200c101b2209450d060b200c210a0b200920006a22002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200b2100200341206a2103200841606a22080d000b200241186a200b3602002002200a360214200220093602100c010b200241186a280200210b2002280214210a200228021021090b200241106a41086a220342003703002002420037031020044117200241106a1001200241086a200329030037030020022002290310370300200241102009200b10030240200a450d00200910190b200410190240200141146a280200450d00200710190b200241206a24000f0b101d000b200c4101101c000b41134101101c000b41264101101c000b41104101101c000bae0901097f230041106b2202240020024100360208200242013703002002410436020c2002410c6a2002105d0240024002400240024002400240024020022802042203200228020822046b41044f0d00200441046a22052004490d0520034101742206200520052006491b22064100480d052003450d01200228020020032006101a2203450d020c030b200441046a2105200228020021030c030b2006101b22030d010b20064101101c000b20022006360204200220033602000b200241086a22062005360200200320046a41eede91ab063600002002410e36020c2002410c6a2002105d0240024002400240024020022802042203200628020022066b410e4f0d002006410e6a22052006490d0520034101742204200520052004491b22074100480d052003450d01200228020020032007101a2204450d020c030b2006410e6a2105200228020021040c030b2007101b22040d010b20074101101c000b2002200736020420022004360200200721030b200241086a22072005360200200420066a220641066a4100290087cd4137000020064100290081cd413700000240200320056b41034b0d00200541046a22062005490d0120034101742208200620062008491b22064100480d010240024002402003450d00200420032006101a2204450d010c020b2006101b22040d010b20064101101c000b20022006360204200220043602000b2007200541046a360200200420056a410a360000024020022802042203200728020022056b41034b0d00200541046a22062005490d0120034101742207200620062007491b22064100480d010240024002402003450d00200420032006101a2204450d010c020b2006101b22040d010b20064101101c000b20022006360204200220043602000b200241086a2203200541046a360200200420056a411d3600000240024002400240024020022802042205200328020022046b41044f0d00200441046a22032004490d0520054101742206200320032006491b22034100480d052005450d01200228020020052003101a2205450d020c030b200228020021050c030b2003101b22050d010b20034101101c000b20022003360204200220053602000b200241086a2208200441046a360200200520046a411f3600002002410636020c2002410c6a2002105d200828020021064190cdc10021072002280204210503400240024002400240200520066b41084f0d00200641086a22042006490d0520054101742203200420042003491b22094100480d052005450d01200228020020052009101a22030d020c060b200641086a2104200228020021030c020b2009101b2203450d040b2002200936020420022003360200200921050b20082004360200200320066a2007290000370000200741086a28020021090240200520046b41034b0d00200441046a22062004490d022005410174220a20062006200a491b22064100480d02024002402005450d00200320052006101a22030d010c060b2006101b2203450d050b2002200636020420022003360200200621050b2008200441046a2206360200200320046a20093600002007410c6a220741d8cdc100470d000b200241106a24002006ad4220862003ad840f0b101d000b20094101101c000b20064101101c000ba80503047f017e077f230041306b220224002002410636020c200241e481c000360208200241106a41fbd7c100200241086a103b41002103024002400240200228021022042002280218220541d889c200410041001000417f460d002002410036020820042005200241086a41044100100041016a41044d0d01200228020821030b02402002280214450d00200410190b02400240024002402003450d002003ad4205862206422088a70d022006a722044100480d022004101b2207450d0541002105200721040340200241106a20051033200441186a200241106a41186a290000370000200441106a200241106a41106a290000370000200441086a200241106a41086a29000037000020042002290010370000200441206a21042003200541016a2205470d000c020b0b410121070b200241003602182002420137031020022003360208200241086a200241106a105d024002402003450d00200341057421084100200241106a41086a28020022096b210a2002280210210b2002280214210c4100210403400240200c200a6a411f4b0d00200920046a220d41206a2205200d490d04200c410174220d20052005200d491b22054100480d0402400240200c450d00200b200c2005101a220b0d010c070b2005101b220b450d060b2005210c0b200b20096a20046a2205200720046a220d290000370000200541186a200d41186a290000370000200541106a200d41106a290000370000200541086a200d41086a290000370000200a41606a210a2008200441206a2204470d000b200241186a200920046a22043602002002200c3602142002200b3602102003450d01200710190c010b200241186a28020021042002280210210b0b200241306a24002004ad422086200bad840f0b101d000b20054101101c000b41fcf9c00041331030000b20044101101c000bd31403027f017e087f230041d0086b22022400024002402001450d00200220003602000c010b200241d889c2003602000b20022001360204200241f0066a200210e301024002400240024002400240024020022802f806450d00200241086a200241f0066a4188011095031a20024190016a200241086a4188011095031a200229039001200241a4016a2201200241e4016a2203106602400240024002402002290390012204500d00200241f0066a2004427f7c1060200241f0066a200141201097030d0041002105200228028802210002400240024020024190026a280200220141e0016c41e001490d002001410c6c2206101b2207450d0b2001210820010d010c020b41042107410021082001450d010b200141e0016c2106200141057441606a21092007210103402002200036028004200241f0066a20024180046a109002200141086a200241f0066a41086a280200360200200120022903f0063702002001410c6a2101200041e0016a2100200641a07e6a22060d000b200941057641016a21050b4104210a410021064100210b02402005410c6c2201410c490d002001410c6e220b41037422004100480d0a2000101b220a450d0b0b0240200720016a220c2007460d0041002106200a210120072100034020002802002109200141046a200041086a28020036020020012009360200200141086a2101200641016a21062000410c6a2200200c470d000b0b200241f0066a200a20061091020240200b450d00200a10190b02402005450d002005410c6c21002007210103400240200141046a280200450d00200128020010190b2001410c6a2101200041746a22000d000b0b02402008450d00200710190b02402003200241f0066a4120109703450d0041c984c200410e100420034120100e200241f0066a4120100e0b2003200241f0066a41201097030d052002418c026a280200210520024190016a41f8006a280200210720024190026a280200210620024198026a20024190016a41f8001095031a2007200641e0016c6a210020072101024002400240024002402006450d0020024180046a41f8006a2109200241f0066a41086a210c20072101034020024190036a200141f0001095031a200141f0006a290300210420024188066a200141f8006a41e8001095031a20044203510d0220024180046a20024190036a41f0001095031a20024180046a41f0006a2004370300200920024188066a41e8001095031a200220024180046a3602e005200241f0066a200241e0056a109002200c2802002106024020022802f406450d0020022802f00610190b200241f0066a20024180046a41e0011095031a200241003602f005200241e0056a200241f0066a2006200241f0056a10920220022802e0054101460d05024020022802e4052206450d002006200241e0056a41086a28020010040b200141e0016a22012000470d000b200021010b20012000470d010c020b200141e0016a22012000460d010b200241f8076a2106200241f0066a41f8006a21090340200241f0066a200141f0001095031a200141f0006a290300210420024190036a200141f8006a41e8001095031a20044203510d0120024180046a200241f0066a41f0001095031a20024188066a20024190036a41e8001095031a200241f0066a20024180046a41f0001095031a200241f0066a41f0006a2004370300200920024188066a41e8001095031a20061043200141e0016a22012000470d000b0b02402005450d00200710190b106c2002290398021039200241f0066a106f200220024198026a41106a28020022033602800620022802a00221052002200241f0066a41106a28020022013602840620022802f806210b200220024180066a3602f005200220024184066a3602e00520032001470d07024002402003450d0002402005200b460d004100210a03402005200a41286c22006a2201200b20006a220010930220012d0000220620002d0000470d0302400240024020064101460d0020064102470d01200141086a290300200041086a290300520d06200141186a2802002207200041186a280200470d06200141106a2802002201200041106a2802002200460d02417f21060340200641016a220620074f0d032001200041201097030d07200041206a2109200141206a210c200141286a2101200041286a2100200c2903002009290300510d000c070b0b2001410c6a28020022092000410c6a280200470d052009450d01200141046a2802002201200041046a2802002200460d014100210603402001200041201097030d06200141206a2101200041206a2100200641016a22062009490d000c020b0b200141016a200041016a41201097030d040b200a41016a220a2003490d000c020b0b20032101034020052005109302200541286a21052001417f6a22010d000b0b20024180046a41186a2201420037030020024180046a41106a2200420037030020024180046a41086a22064200370300200242003703800420024180046a100720024190036a41186a200129030037030020024190036a41106a200029030037030020024190036a41086a20062903003703002002200229038004370390030240200241cc026a220120024190036a4120109703450d0041c984c200410e100420014120100e20024190036a4120100e0b200120024190036a41201097030d0902402003450d00200341286c2100200b21010340024020012d00002206450d00024020064101470d00200141086a280200450d01200141046a2802001019200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010190b200141286a2101200041586a22000d000b0b0240200241fc066a280200450d00200b10190b024020024198026a41106a2802002200450d0020024198026a41086a2802002101200041286c21000340024020012d00002206450d00024020064101470d00200141086a280200450d01200141046a2802001019200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010190b200141286a2101200041586a22000d000b0b0240200241a4026a280200450d00200241a0026a28020010190b200241d0086a240042010f0b41e0c7c3001029000b20022802e4052202450d0120024103460d0220024104460d0341e8c6c3001029000b41b8c6c3001029000b4198c7c3001029000b4180c7c3001029000b41b0c7c3001029000b20024194046a410136020020024103360294012002419cabc300360290012002420137028404200241a4abc30036028004200220024190016a3602900420024180046a41acabc30010f201000b41d0c6c3001029000b20024180046a41146a410036020020024190036a41146a41043602002002419c036a410c36020020024188066a41146a4103360200200241d889c200360290042002420137028404200241c8c7c300360280042002410c360294032002420337028c06200241fcd7c30036028806200220024180046a3602a0032002200241e0056a360298032002200241f0056a36029003200220024190036a3602980620024188066a41d0c7c30010f201000b41f8c7c3001029000b20064104101c000b101d000b20004104101c000b881203047f027e097f230041206b22022400024002400240024002400240024002400240024002400240024041e201101b2203450d00200242e20137020420022003360200200341003b00002002410236020802400240024002400240200128020022032903704202520d0020022802044102470d01200228020041024104101a2201450d062002410436020420022001360200200241086a28020021040c020b20022802044102470d02200228020041024104101a2201450d062002410436020420022001360200200241086a28020021040c030b41022104200228020021010b200120046a41013a0000200241086a2201200128020041016a3602000c070b41022104200228020021010b200120046a4181013a0000200241086a2201200128020041016a360200200341086a200210cf0102400240024020022802042204200128020022016b41c0004f0d00200141c0006a22052001490d0920044101742201200520052001491b22014100480d092004450d01200228020020042001101a2204450d020c060b200228020021040c060b2001101b22040d040b20014101101c000b41e2014101101c000b41044101101c000b41044101101c000b2002200136020420022004360200200241086a28020021010b200241086a2205200141c0006a360200200420016a220141086a200341346a290000370000200141106a2003413c6a290000370000200141186a200341c4006a290000370000200141206a200341cc006a290000370000200141286a200341d4006a290000370000200141306a200341dc006a290000370000200141386a200341e4006a2900003700002001200329002c37000020032002106302400240024002400240024002400240024002400240200341f0006a2903004201520d0020032903782206420c882207420120074201561b22074200510d0620034180016a290300200780210720022802042204200241086a28020022016b41024f0d01200141026a22052001490d0c20044101742201200520052001491b22014100480d0c2004450d04200228020020042001101a2204450d050c090b0240200228020420052802002201470d00200141016a22042001490d0c20014101742205200420042005491b22054100480d0c2001450d02200228020020012005101a2204450d030c070b200228020021040c070b200228020021040c080b2005101b22040d040b20054101101c000b2001101b22040d040b20014101101c000b4188b2c2001029000b2002200536020420022004360200200241086a28020021010b200241086a200141016a360200200420016a41003a00000c020b2002200136020420022004360200200241086a28020021010b200241086a200141026a360200200420016a2007a741047420067aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b20034188016a20021064200241086a22032802002101200241003602182002420137031020022001417e6a36021c2002411c6a200241106a105d024002400240024002402003280200220141014d0d002002280218210520022802102108200228021421092003410036020020022802002103024002400240024002400240024002402001417e6a220a450d004102210b2005450d12200320082d00003a00004101210c200241086a2204200428020041016a36020020054101460d12200820056a210d200320082d00013a00012004200428020041016a3602004102210b200841026a21044100210e2005417e6a2203450d052002280204220b20016b20034f0d01200120036a220c2001490d0d200b4101742201200c200c2001491b220c4100480d0d200b450d022002280200200b200c101a22010d030c0a0b0240024002402002280204220120054f0d0020014101742204200520052004491b22044100480d0f2001450d01200320012004101a2203450d020c110b4100210b2005450d120c110b2004101b22030d0f0b20044101101c000b200228020021010c020b200c101b2201450d070b2002200c360204200220013602000b200120056a200141026a200a1096031a02402005200241086a220b280200220c460d002002280200200c6a210120052103034020034102460d03200120042d00003a0000200b200b28020041016a360200200141016a2101200441016a2104200c2003417f6a2203470d000b200d20046b2203450d030b20034100480d082003101b220c450d042005210b2003210e0b200d2004460d060c050b2005210b200a0d0b0c0c0b4101210c2005210b200d2004470d030c040b41e4d5c3001029000b20034101101c000b200c4101101c000b200c20042d00003a00004101210f0240200441016a2203200d460d00200c41016a2101200520046b21040340200120032d00003a0000200141016a2101200d200341016a2203470d000b200820046a220f450d010b200c200f6a210d024002400240024020022802042203200b200a6a22016b200f4f0d002001200f6a22042001490d0520034101742201200420042001491b22014100480d052003450d01200228020020032001101a22030d020c060b200228020021030c020b2001101b2203450d040b20022001360204200220033602000b2003200f200b6a22106a2003200b6a200a1096031a02402010200241086a22042802002203460d00200228020020036a2101200f200b6a20036b2105200c21030340200d2003460d01200120032d00003a00002004200428020041016a360200200341016a2103200141016a21012005417f6a22050d000b0b2010210b0b0240200e450d00200c10190b200a450d060c050b101d000b20014101101c000b2002200436020420022003360200200241086a280200210b0b2003200b6a220120082d00003a0000024020054101470d00200b41016a210b0c010b2005417f6a2104200841016a2103200141016a21010340200120032d00003a0000200141016a2101200341016a21032004417f6a22040d000b200b20056a210b0b200241086a200b3602004102210b200a450d010b0240200b200241086a22012802002203460d002002280200220420036a2004200b6a200a1096031a0b20012003200a6a3602000b02402009450d00200810190b20002002290300370200200041086a200241086a280200360200200241206a24000bcb03010b7f230041206b22032400024002402002450d0020024102742204101b22050d0120044104101c000b410421050b0240024002400240200120024103746a22062001460d0020024103742107200141046a210420052108034020082004280200360200200441086a2104200841046a2108200741786a22070d000b200641786a20016b41037641016a21094101210a4100210b4100210403402001280200210c0240024002400240200b20046b200141046a28020022084f0d00200420086a22072004490d07200b410174220d20072007200d491b220d4100480d07200b450d01200a200b200d101a220a0d020c080b200820046a21070c020b200d101b220a450d060b200d210b0b200a20046a200c20081095031a20072104200141086a22012006470d000c020b0b4101210a410021094100210b0b200341186a22044200370300200341106a22014200370300200341086a2208420037030020034200370300200a2005200920031013200041186a2004290300370000200041106a2001290300370000200041086a2008290300370000200020032903003700000240200b450d00200a10190b02402002450d00200510190b200341206a24000f0b101d000b200d4101101c000b8f1605017f017e037f017e067f230041e0056b22042400200441a0036a200141e0011095031a20044190026a200441a0036a105f0240024002402004280290024101470d00200041086a2004290294023702002000420137020020032802002200450d020c010b20044190026a41086a290300210520044190016a20044190026a41106a4180011095031a20042005370308200441086a41086a20044190016a418001109503210620044190016a41086a22014200370300200442003703900141ce80c000411720044190016a1001200441a0036a41086a200129030037030020042004290390013703a00341002101024002400240024002400240024002400240024002400240024002400240200441a0036a411041d889c200410041001000417f460d002004410036029002200441a0036a411020044190026a41044100100041016a41044d0d0120042802900221010b41042107200120026a41808080024b0d0d410021080240200441106a410020042903084201511b2201450d002001450d0002400240024020011067220520012903202209520d00410321072001200210a7020d114113101b2207450d0d2007410f6a41002800998340360000200741086a410029009283403700002007410029008a8340370000200741134133101a2207450d0e200720012900003700132007412b6a200141186a290000370000200741236a200141106a2900003700002007411b6a200141086a29000037000020044190016a41086a220a420037030020044200370390012007413320044190016a1001200441a0036a41086a200a29030037030020042004290390013703a003200441a0036a411041d889c200410041001000417f460d012004420037039002200441a0036a411020044190026a41084100100041016a41084d0d0820042903900242017c2105200710194113210a4113101b22070d020c0f0b4101410220092005541b21070c100b42012105200710194113210a4113101b2207450d0d0b2007410f6a41002800998340360000200741086a410029009283403700002007410029008a83403700002007200a4133101a2207450d0d200720012900003700132007412b6a200141186a290000370000200741236a200141106a2900003700002007411b6a200141086a290000370000200420053703900220044190016a41086a2201420037030020044200370390012007413320044190016a1001200441a0036a41086a200129030037030020042004290390013703a003200441a0036a411020044190026a41081003200710190b024020032802002207450d00200341086a28020021012003280204210b4100210c0240419384c000411041d889c200410041001000417f460d00200441003602a003419384c0004110200441a0036a41044100100041016a41044d0d0520042802a003210c0b4114101b2208450d06200841106a41002800fa8140360000200841086a41002900f28140370000200841002900ea8140370000200841144128101a220a450d07200a200c360014200441003602a803200442013703a003200420013602900220044190026a200441a0036a105d024002400240024020042802a403220d20042802a803220c6b20014f0d00200c20016a2208200c490d0c200d410174220e20082008200e491b220e4100480d0c200d450d0120042802a003200d200e101a22080d020c0d0b20042802a00321080c020b200e101b2208450d0b0b2004200e3602a403200420083602a003200e210d0b2008200c6a200720011095031a20044190016a41086a220e42003703002004420037039001200a411820044190016a1001200441a0036a41086a200e29030037030020042004290390013703a003200441a0036a41102008200c20016a10030240200d450d00200810190b200a101941012108200b450d00200710190b20042903082105200441a0036a200441306a41e0001095031a20044190026a200441a0036a41086a41d8001095031a20044190016a41186a220a200641186a29030037030020044190016a41106a220c200641106a29030037030020044190016a41086a220d200641086a290300370300200420062903003703900141002101024020054201520d00200441a0056a41186a200a290300370300200441a0056a41106a200c290300370300200441a0056a41086a200d29030037030020042004290390013703a005410121010b20044190016a20044190026a41d8001095031a200441c0056a41186a2206200441a0056a41186a220a290300370300200441c0056a41106a220c200441a0056a41106a220d290300370300200441c0056a41086a220b200441a0056a41086a220e290300370300200420042903a0053703c00520044190026a20044190016a41d8001095031a20044180056a41186a220f200629030037030020044180056a41106a2206200c29030037030020044180056a41086a220c200b290300370300200420042903c00537038005200441a0036a20044190026a41d8001095031a200a200f290300370300200d2006290300370300200e200c29030037030020042004290380053703a0054102210602402001450d00200441c0056a41186a200441a0056a41186a290300370300200441c0056a41106a200441a0056a41106a290300370300200441c0056a41086a200441a0056a41086a290300370300200420042903a0053703c005410121060b2004419a016a200441c0056a41086a290300370100200441a2016a200441c0056a41106a290300370100200441aa016a200441d8056a290300370100200420063a009101200441003a009001200420042903c005370192012004200441a0036a20044190016a10502004280204210620042802002101200441003a00a003200420014100473a00a103200441a0036a103d02400240419384c000411041d889c200410041001000417f460d00200441003602a003419384c0004110200441a0036a41044100100041016a41044d0d0320042802a00341016a210a0c010b4101210a0b20044190016a41086a220c4200370300200442003703900141ce80c000411720044190016a1001200441a0036a41086a200c29030037030020042004290390013703a00302400240200441a0036a411041d889c200410041001000417f460d002004410036029001200441a0036a411020044190016a41044100100041016a41044d0d04200428029001210c0c010b4100210c0b2004200a3602a003419384c0004110200441a0036a410410032004417f2002200c6a220a200a2002491b3602c00520044190016a41086a22024200370300200442003703900141ce80c000411720044190016a1001200441a0036a41086a200229030037030020042004290390013703a003200441a0036a4110200441c0056a410410030240024002402001450d0002402006411b470d00200141e2e2c100460d02200141e2e2c100411b109703450d020b200041086a2006360200200041046a200136020020004100360200200745200872450d020c120b20004100360204200041086a200636020020004100360200200745200872450d010c110b200041046a4104360200200041013602002007452008720d100b200341046a280200450d0f200710190c0f0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41144101101c000b41284101101c000b101d000b200e4101101c000b41134101101c000b41334101101c000b200a4101101c000b41334101101c000b2000410136020020002007360204200441386a104320032802002200450d010b200341046a280200450d0020001019200441e0056a24000f0b200441e0056a24000b890301077f230041106b220224000240024020002d0000220320012d0000470d000240024020034101460d0020034102470d01200041086a290300200141086a290300520d02200041186a2802002204200141186a280200470d02200041106a2802002203200141106a2802002205460d03417f21060340200641016a220620044f0d042003200541201097030d03200541206a2107200341206a2108200541286a2105200341286a210320082903002007290300510d000c030b0b2000410c6a28020022072001410c6a280200470d012007450d02200041046a2802002203200141046a2802002205460d024100210603402003200541201097030d02200341206a2103200541206a2105200641016a22062007490d000c030b0b20002001460d01200041016a200141016a4120109703450d010b41c5c8c1004114100420022000105e200228020022002002280208100e02402002280204450d00200010190b20022001105e200228020022002002280208100e2002280204450d00200010190b200241106a24000b6501027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a1087032100200241206a240020000be20201027f23004180026b22022400024002402001450d00200220003602000c010b200241d889c2003602000b2002200136020420024180016a200210e4010240200228028801450d00200241086a20024180016a41f8001095031a2002290308200241086a41146a200241dc006a10660240200241086a41106a2802002200450d0020022802102101200041286c21000340024020012d00002203450d00024020034101470d00200141086a280200450d01200141046a2802001019200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010190b200141286a2101200041586a22000d000b0b0240200241146a280200450d00200241106a28020010190b20024180026a240042010f0b2002411c6a4101360200200241033602fc01200241bcabc3003602f8012002420137020c200241a4abc3003602082002200241f8016a360218200241086a41acabc30010f201000bdc0d01087f230041206b220224002002410036021820024201370310024002400240024002400240024002404104101b2203450d0020024104360214200241186a22042004280200220541046a36020020022003360210200320056a41edcad18b06360000024002400240200228021420042802002203470d00200341016a22042003490d0620034101742205200420042005491b22044100480d062003450d01200228021020032004101a2205450d020c040b200228021021050c040b2004101b22050d020b20044101101c000b41044101101c000b2002200436021420022005360210200241186a28020021030b200241186a2204200341016a360200200520036a41013a00004111200241106a1097024100210302400340200341f0b4c3006a280200200341f4b4c3006a280200200241106a10980202400240024002400240024002400240024002400240024002400240024002400240200341f8b4c3006a2802004101470d00200341fcb4c3006a28020020034180b5c3006a280200200241106a10980220034184b5c3006a22062802004102460d010c020b2002200341fcb4c3006a28020011050020022802002002280204200241106a10980220034184b5c3006a22062802004102470d010b02400240024002400240200228021420042802002205470d00200541016a22062005490d1620054101742207200620062007491b22074100480d162005450d01200228021020052007101a22060d020c040b200228021021060c020b2007101b2206450d020b2002200736021420022006360210200428020021050b2004200541016a360200200620056a41003a000020034194b5c3006a22062802004102470d020c030b20074101101c000b0240024002400240200228021420042802002205470d00200541016a22072005490d1420054101742208200720072008491b22084100480d142005450d01200228021020052008101a22070d020c0d0b200228021021070c020b2008101b2207450d0b0b2002200836021420022007360210200428020021050b2004200541016a360200200720056a41013a00002006200241106a10990220034194b5c3006a22062802004102460d010b0240200228021420042802002205470d00200541016a22072005490d1020054101742208200720072008491b22084100480d102005450d02200228021020052008101a22070d030c0a0b200228021021070c030b0240200228021420042802002205470d00200541016a22062005490d0f20054101742207200620062007491b22074100480d0f2005450d04200228021020052007101a22060d050c0a0b200228021021060c050b2008101b2207450d070b2002200836021420022007360210200428020021050b2004200541016a360200200720056a41013a00002006200241106a109a02200341a4b5c3006a22062802004102460d030c080b2007101b2206450d050b2002200736021420022006360210200428020021050b2004200541016a360200200620056a41003a0000200341a4b5c3006a22062802004102470d050b0240024002400240200228021420042802002205470d00200541016a22062005490d0b20054101742207200620062007491b22074100480d0b2005450d01200228021020052007101a22060d020c070b200228021021060c020b2007101b2206450d050b2002200736021420022006360210200428020021050b2004200541016a360200200620056a41003a0000200341c8006a220341c809470d050c060b20084101101c000b20084101101c000b20074101101c000b20074101101c000b0240024002400240200228021420042802002205470d00200541016a22072005490d0620054101742208200720072008491b22084100480d062005450d01200228021020052008101a22070d020c070b200228021021070c020b2008101b2207450d050b2002200836021420022007360210200428020021050b2004200541016a360200200720056a41013a00002006200241106a109b02200341c8006a220341c809470d000b0b200241186a2802002103200228021421072002280210210620024100360218200242013703102002200336020c2002410c6a200241106a105d02400240024020022802142205200228021822046b20034f0d00200420036a22082004490d0320054101742209200820082009491b22084100480d032005450d01200228021020052008101a2205450d020c050b2002280210220520046a200620031095031a200420036a21032007450d060c050b2008101b22050d030b20084101101c000b101d000b20084101101c000b2002200836021420022005360210200520046a200620031095031a200420036a21032007450d010b200610190b200241206a24002003ad4220862005ad840b910701037f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000413f4b0d00200141046a280200200141086a2802002202470d01200241016a22032002490d1120024101742204200320032004491b22044100480d112002450d05200128020020022004101a2203450d060c170b2000418080014f0d01200141046a2802002203200141086a28020022026b41024f0d02200241026a22042002490d1020034101742202200420042002491b22024100480d102003450d08200128020020032002101a2203450d090c140b200128020021030c160b20004180808080044f0d01200141046a2802002203200141086a28020022026b41044f0d04200241046a22042002490d0e20034101742202200420042002491b22024100480d0e2003450d08200128020020032002101a22030d090c0f0b200128020021030c120b200141046a280200200141086a2802002202470d03200241016a22032002490d0c20024101742204200320032004491b22044100480d0c2002450d09200128020020022004101a22030d0a0c0e0b2004101b22030d110b20044101101c000b200128020021030c050b200128020021030c070b2002101b22030d0b0b20024101101c000b2002101b2203450d060b20012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b2004101b2203450d040b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00000240024002400240200141046a2802002203200428020022026b41044f0d00200241046a22042002490d0420034101742202200420042002491b22024100480d042003450d01200128020020032002101a22030d020c070b200128020021030c020b2002101b2203450d050b20012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b101d000b20024101101c000b20044101101c000b20024101101c000b20012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b20012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000bc60801037f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001413f4b0d00200241046a280200200241086a2802002203470d01200341016a22042003490d1920034101742205200420042005491b22054100480d192003450d05200228020020032005101a2204450d060c160b2001418080014f0d01200241046a2802002204200241086a28020022036b41024f0d02200341026a22052003490d1820044101742203200520052003491b22034100480d182004450d08200228020020042003101a2204450d090c130b200228020021040c150b20014180808080044f0d01200241046a2802002204200241086a28020022036b41044f0d04200341046a22052003490d1620044101742203200520052003491b22034100480d162004450d08200228020020042003101a22040d090c0e0b200228020021040c110b200241046a280200200241086a2802002203470d03200341016a22042003490d1420034101742205200420042005491b22054100480d142003450d09200228020020032005101a22040d0a0c0d0b2005101b22040d100b20054101101c000b200228020021040c050b200228020021040c070b2003101b22040d0a0b20034101101c000b2003101b2204450d050b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20014102744102723600000c0a0b2005101b2204450d030b20022004360200200241046a2005360200200241086a28020021030b200241086a2205200341016a360200200420036a41033a00000240024002400240200241046a2802002204200528020022036b41044f0d00200341046a22052003490d0c20044101742203200520052003491b22034100480d0c2004450d01200228020020042003101a22040d020c060b200228020021040c020b2003101b2204450d040b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20013600000c070b20034101101c000b20054101101c000b20034101101c000b20022004360200200241046a2003360200200241086a28020021030b200241086a200341026a360200200420036a20014102744101723b00000c020b20022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20014102743a00000b024002400240200241046a2802002204200241086a28020022036b20014f0d00200320016a22052003490d0320044101742203200520052003491b22034100480d032004450d01200228020020042003101a2204450d020c040b200228020021040c040b2003101b22040d020b20034101101c000b101d000b20022004360200200241046a2003360200200241086a28020021030b200241086a200320016a360200200420036a200020011095031a0bfb0f01097f230041206b2202240002400240024020002802004101470d00200041046a28020021032000410c6a280200220020011097022000450d01200041cc006c2104410021050340200320056a220041046a280200200041086a2802002001109802200141046a22062802002107200141086a220828020021090240024002400240024002400240024002400240024002400240024002400240200041c8006a2d00004101470d0020072009470d01200941016a22072009490d132009410174220a20072007200a491b220a4100480d132009450d0320012802002009200a101a22070d040c0a0b20072009470d01200941016a22072009490d122009410174220a20072007200a491b220a4100480d122009450d0520012802002009200a101a22070d060c0a0b200128020021070c030b200128020021070c050b200a101b2207450d060b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41013a00000c030b200a101b2207450d040b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41003a00000b200628020021072008280200210902400240024002400240024002400240024002402000410c6a2802004101470d0020072009470d01200941016a22072009490d132009410174220a20072007200a491b220a4100480d132009450d0320012802002009200a101a22070d040c0c0b20072009470d01200941016a22072009490d122009410174220a20072007200a491b220a4100480d122009450d0520012802002009200a101a22070d060c0c0b200128020021070c030b200128020021070c050b200a101b2207450d080b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41013a0000200041146a280200200041186a2802002001109802200041206a280200200041246a2802002001109802200041286a2802004101460d030c080b200a101b2207450d060b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41003a0000200041146a280200200041186a2802002001109802200041286a2802004101470d050b2000412c6a280200200041346a28020020011098020c050b200a4101101c000b200a4101101c000b200a4101101c000b200a4101101c000b200241106a2000412c6a280200200041306a28020028020c11060020022802102209200241106a41086a28020020011098022002280214450d00200910190b2000413c6a28020021090240200041386a2802004101470d002009200041c4006a28020020011080032004200541cc006a2205470d010c030b2009200041c0006a28020020011080032004200541cc006a2205470d000c020b0b200241086a200041046a28020011050020022802082103200228020c220020011097022000450d00200041cc006c2104410021050340200320056a220041046a280200200041086a2802002001109802200141046a22062802002107200141086a220828020021090240024002400240024002400240024002400240024002400240024002400240200041c8006a2d00004101470d0020072009470d01200941016a22072009490d122009410174220a20072007200a491b220a4100480d122009450d0320012802002009200a101a22070d040c0a0b20072009470d01200941016a22072009490d112009410174220a20072007200a491b220a4100480d112009450d0520012802002009200a101a22070d060c0a0b200128020021070c030b200128020021070c050b200a101b2207450d060b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41013a00000c030b200a101b2207450d040b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41003a00000b200628020021072008280200210902400240024002400240024002400240024002402000410c6a2802004101470d0020072009470d01200941016a22072009490d122009410174220a20072007200a491b220a4100480d122009450d0320012802002009200a101a22070d040c0c0b20072009470d01200941016a22072009490d112009410174220a20072007200a491b220a4100480d112009450d0520012802002009200a101a22070d060c0c0b200128020021070c030b200128020021070c050b200a101b2207450d080b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41013a0000200041146a280200200041186a2802002001109802200041206a280200200041246a2802002001109802200041286a2802004101460d030c080b200a101b2207450d060b200120073602002006200a360200200828020021090b2008200941016a360200200720096a41003a0000200041146a280200200041186a2802002001109802200041286a2802004101470d050b2000412c6a280200200041346a28020020011098020c050b200a4101101c000b200a4101101c000b200a4101101c000b200a4101101c000b200241106a2000412c6a280200200041306a28020028020c11060020022802102209200241106a41086a28020020011098022002280214450d00200910190b2000413c6a28020021090240200041386a2802004101470d002009200041c4006a28020020011080032004200541cc006a2205470d010c020b2009200041c0006a28020020011080032004200541cc006a2205470d000b0b200241206a24000f0b101d000bf40201057f230041106b220224000240024020002802004101470d00200041046a28020021032000410c6a280200220020011097022000450d012000412c6c2104410021050340200320056a220041046a280200200041086a28020020011098022000410c6a2001108103200041206a280200210602402000411c6a2802004101470d002006200041286a280200200110800320042005412c6a2205470d010c030b2006200041246a280200200110800320042005412c6a2205470d000c020b0b200241086a200041046a28020011050020022802082103200228020c220020011097022000450d002000412c6c2104410021050340200320056a220041046a280200200041086a28020020011098022000410c6a2001108103200041206a280200210602402000411c6a2802004101470d002006200041286a280200200110800320042005412c6a2205470d010c020b2006200041246a280200200110800320042005412c6a2205470d000b0b200241106a24000bda0301057f230041106b220224000240024020002802004101470d00200041046a28020021032000410c6a280200220020011097022000450d012000412c6c2104410021050340200320056a220041046a280200200041086a2802002001109802200041106a2802002106024002402000410c6a2802004101470d002006200041186a28020020011080030c010b2006200041146a28020020011080030b200041206a280200210602402000411c6a2802004101470d002006200041286a280200200110800320042005412c6a2205470d010c030b2006200041246a280200200110800320042005412c6a2205470d000c020b0b200241086a200041046a28020011050020022802082103200228020c220020011097022000450d002000412c6c2104410021050340200320056a220041046a280200200041086a2802002001109802200041106a2802002106024002402000410c6a2802004101470d002006200041186a28020020011080030c010b2006200041146a28020020011080030b200041206a280200210602402000411c6a2802004101470d002006200041286a280200200110800320042005412c6a2205470d010c020b2006200041246a280200200110800320042005412c6a2205470d000b0b200241106a24000be30301017f230041e0056b22022400024002402001450d00200220003602080c010b200241d889c2003602080b2002200136020c200241f0036a200241086a103502400240024002400240024020022903e0044203510d00200241106a200241f0036a41e0011095031a200241f0016a200241106a41e0011095031a2002200241f0016a3602f003200241d0036a200241f0036a10900220022802d8032101200241f0036a200241f0016a41e0011095031a200241d8056a20022802d803360200200220022903d0033703d005200241e0036a200241f0036a2001200241d0056a1092020240024020022802e0034101470d004280828898f01f20022802e403410374ad88a721004101101b210141010d010c050b20022802e40341004721004101101b21014100450d040b2001450d01200141013a0000200141014102101a2201450d020c040b20024184026a410136020020024103360214200241c4abc300360210200242013702f401200241a4abc3003602f0012002200241106a36028002200241f0016a41acabc30010f201000b41014101101c000b41024101101c000b2001450d01200141003a0000200141014102101a22010d0041024101101c000b200120003a0001200241e0056a24002001ad428080808020840f0b41014101101c000be01203027f017e0b7f230041c0016b22022400106c20024180016a41086a220342003703002002420037038001419c82c000410d20024180016a1001200241086a41086a20032903003703002002200229038001370308420021040240024002400240024002400240024002400240024002400240200241086a411041d889c200410041001000417f460d002002420037038001200241086a411020024180016a41084100100041016a41084d0d0120022903800121040b20041039200241b0016a41086a22034200370300200242003703b00141b980c0004115200241b0016a1001200241a0016a41086a2003290300370300200220022903b0013703a0010240024002400240024002400240200241a0016a411041d889c200410041001000417f460d0041002105200241003602084104210641012107200241a0016a4110200241086a41044100100041016a41044d0d0920022802082208450d012008ad420c7e2204422088a70d0f2004a722034100480d0f2003101b2206450d0c200621094100210503404114101b2203450d03200341106a41002800fa8140360000200341086a41002900f28140370000200341002900ea8140370000200341144128101a220a450d04200a200536001420024180016a41086a220b42003703002002420037038001200a411820024180016a1001200241086a41086a200b290300370300200220022903800137030802400240200241086a411041d889c200410041001000417f460d0020024210370284012002200241086a36028001200220024180016a10682002280200450d0920022802042203417f4c0d07024002402003450d00200310df01220c450d0d200b200b280200220d20034100200228028001200228028401200c2003200d1000220d200d417f461b220d200d20034b1b220d6a360200200d2003460d010c0a0b4101210c20022802800120022802840141014100200b28020010001a41002003470d090b200b42003703002002420037038001200a411820024180016a1001200241b0016a41086a200b29030037030020022002290380013703b001200241b0016a41101002200c0d010b4101210c410021030b200a1019200941086a2003360200200941046a20033602002009200c3602002009410c6a21092008200541016a2205470d000b41002107200821050c010b4100210541012107410421060b410421084100210a4100210d02402005410c6c2203410c490d002003410c6e220d41037422094100480d0e2009101b2208450d0a0b0240200620036a220c2006460d004100210a200821032006210903402009280200210b200341046a200941086a2802003602002003200b360200200341086a2103200a41016a210a2009410c6a2209200c470d000b0b20024180016a2008200a1091020240200d450d00200810190b02402005450d002005410c6c21092006210303400240200341046a280200450d00200328020010190b2003410c6a2103200941746a22090d000b0b024020070d00200610190b200241086a41186a20024180016a41186a290300370300200241086a41106a20024180016a41106a290300370300200241086a41086a20024180016a41086a2903003703002002200229038001370308200241b0016a41086a220a4200370300200242003703b00141a982c0004115200241b0016a1001200241a0016a41086a200a290300370300200220022903b0013703a001200241a0016a4110200241086a41201003200241086a106f200241003602b801200242013703b0014120101b2203450d08200242a080808080043702b401200220033602b0012003200229021c370000200341086a200241246a290200370000200341106a2002412c6a290200370000200341186a200241346a290200370000200241086a200241b0016a106302400240024020022802b4012209200a280200220b6b41204f0d00200b41206a2203200b490d102009410174220a20032003200a491b220c4100480d102009450d0120022802b0012009200c101a220a450d020c0e0b200b41206a210320022802b001210a0c0e0b200c101b220a0d0c0b200c4101101c000b41144101101c000b41284101101c000b102b000b2003450d00200c10190b41fcf9c00041331030000b41fcf9c00041331030000b20034101101c000b41fcf9c00041331030000b41204101101c000b20094104101c000b20034104101c000b2002200c3602b4012002200a3602b001200c21090b200241b0016a41086a220c2003360200200a200b6a220b41086a200241c4006a290200370000200b41106a200241cc006a290200370000200b41186a200241d4006a290200370000200b200229023c3700000240200920036b411f4b0d00200341206a220b2003490d0120094101742205200b200b2005491b220b4100480d010240024002402009450d00200a2009200b101a220a450d010c020b200b101b220a0d010b200b4101101c000b2002200b3602b4012002200a3602b0010b200c200341206a360200200a20036a220341186a200241f4006a290200370000200341106a200241ec006a290200370000200341086a200241e4006a2902003700002003200229025c3700002002280210210e2002200241086a41106a280200220f3602800120024180016a200241b0016a105d0240200f450d00200f41286c210d200241b0016a41086a2207280200210320022802b401210c200e210a034020024180016a200a105e20022802800121050240024002400240200c20036b20024180016a41086a280200220b4f0d002003200b6a22092003490d06200c4101742208200920092008491b22064100480d06200c450d0120022802b001200c2006101a22080d020c070b2003200b6a210920022802b00121080c020b2006101b2208450d050b200220063602b401200220083602b0012006210c0b20072009360200200820036a2005200b1095031a0240200228028401450d00200510190b200a41286a210a20092103200d41586a220d0d000b0240200f450d00200f41286c210a200e21030340024020032d0000220b450d000240200b4101470d00200341086a280200450d01200341046a2802001019200341286a2103200a41586a220a0d020c030b200341146a280200450d00200341106a28020010190b200341286a2103200a41586a220a0d000b0b200241146a280200450d040c030b200241b8016a280200210920022802b0012108200241146a2802000d020c030b101d000b20064101101c000b200e10190b200241c0016a24002009ad4220862008ad840bab0a03017f037e087f230041f0016b22022400024002402001450d00200220003602000c010b200241d889c2003602000b20022001360204200241286a2002109f020240024002402002280228450d00200241086a41086a2201200241286a41086a220028020036020020022002290328370308200241186a41086a20012802003602002002200229030837031820024180016a200241186a10a0022002280280014101460d0120024180016a41086a22012903002103200142003703002002420037038001419399c100410d20024180016a100120002001290300370300200220022903800137032842002104024002400240200241286a411041d889c200410041001000417f460d002002420037038001200241286a411020024180016a41084100100041016a41084d0d0120022903800121040b20024180016a41086a22014200370300200242003703800141a099c100411520024180016a1001200241286a41086a2001290300370300200220022903800137032802400240200241286a411041d889c200410041001000417f460d002002420037038001200241286a411020024180016a41084100100041016a41084d0d03200229038001210541e001210041e001101b2201450d010c060b4205210541e001210041e001101b22010d050b20004108101c000b41fcf9c00041331030000b41fcf9c00041331030000b20024194016a410136020020024103360274200241ccabc3003602702002420137028401200241a4abc300360280012002200241f0006a3602900120024180016a41acabc30010f201000b41ca9ec100412820022802840120024180016a41086a28020010f301000b200120024180016a41f00010950322064202370370200641003a00880120064202370390012006200229037037037820064180016a200241f0006a41086a29030037030020062002280069360089012006418c016a200241e9006a41036a28000036000020062003200520047c220420042003541b37039801200620022903283703a001200641a8016a200241286a41086a290300370300200641b0016a200241386a290300370300200641b8016a200241c0006a290300370300200641c0016a200241c8006a290300370300200641c8016a200241d0006a290300370300200641d0016a200241d8006a290300370300200641d8016a200241e0006a290300370300200228021822072108200228021c2209210a0340200841086a210020082f0106220c4103742101417f210b02400240024003402001450d0141dd85c00020004108109703220d450d03200b41016a210b200141786a2101200041086a2100200d417f4a0d000b200a0d010c020b200c210b200a450d010b200a417f6a210a2008200b4102746a41e4016a28020021080c010b0b20072009200228022010a1022002410036023020024201370328200241013602800120024180016a200241286a105d200228022c210b200228023021012002200636027020024180016a200241f0006a1090022002280280012108024002400240024002400240200b20016b200228028801220d4f0d002001200d6a22002001490d03200b410174220a20002000200a491b220a4100480d03200b450d012002280228200b200a101a220b450d020c040b2001200d6a21002002280228210b0c040b200a101b220b0d020b200a4101101c000b101d000b2002200a36022c2002200b3602280b200241306a2000360200200b20016a2008200d1095031a0240200228028401450d00200810190b20064188016a104320061019200241f0016a24002000ad422086200bad840bfc0d07027f017e0a7f017e077f017e017f230041a0026b22022400200241186a2001102d0240024002400240024002400240024002400240024002402002280218450d00200228021c2203ad2204421d88a70d0a2004420386a72205417f4c0d0a024002400240024002400240024002400240024002400240024002402005450d002005101b2206450d022003450d010c030b4101210620030d020b410021054100210b2006450d0c0c020b20054101101c000b200141046a210741002108410021094100210a2003210b034020024200370340200241c0006a2001280200220c2007280200220541082005410849220d1b220e1095031a20072005200e6b3602002001200c200e6a360200200d0d02200a41016a2105200229034021040240200a200b470d002008200520052008491b220bad420386220f422088a70d13200fa7220e4100480d130240200a450d0020062009200e101a22060d010c070b200e101b2206450d060b200620096a2004370000200841026a2108200941086a21092005210a20052003490d000b2006450d0a0b2005ad422086200bad84210f200241106a2001102d2002280210450d0720022802142203ad420c7e2204422088a70d132004a72205417f4c0d132005450d012005101b220c450d042003450d020c050b200b0d070c080b4104210c20030d030b410021094100210b200c450d040c030b200e4101101c000b20054104101c000b410021084100210a4100210e2003210b0340200241086a2001102d02400240024002402002280208450d00200228020c2205417f4c0d12024002402005450d00200510df012207450d0320072001280200200141046a220d2802002209200520092005491b22091095031a200d28020022102009490d04200d201020096b3602002001200128020020096a36020020092005470d010c050b4101210741002005460d040b2005450d00200710190b0240200e450d00200c210503400240200541046a280200450d00200528020010190b2005410c6a2105200a41746a220a0d000b0b200b450d05200c10190c050b20054101101c000b200920101027000b200e41016a21090240200e200b470d002008200920092008491b220bad420c7e2204422088a70d0c2004a7220d4100480d0c0240200e450d00200c200a200d101a220c0d010c0e0b200d101b220c450d0d0b200c200a6a220e2007360200200e41046a2005ad2204422086200484370200200841026a2108200a410c6a210a2009210e20092003490d000b200c450d010b2009200f422088a7470d0320024200370224200241a0c0c100360220200c2009410c6c6a211120094103742205450d04200620056a2112200241206a41086a2113200241d4006a2114200241d0006a2115200c210d200621100340200d22052011460d062005410c6a210d20052802002216450d0720052902042104200220102900002217370330024002402002280220220741a0c0c100460d00200228022421030c010b41e401101b2207450d0d41002103200741003b010620074100360200200741086a200241c0006a41dc011095031a20024100360224200220073602200b201041086a211002400340200741e4006a2109200741e0006a210820072f01062218410374210e41002105417f210a0240024002400340200e2005460d01200241306a200820056a41a87f6a41081097032201450d05200a41016a210a2009410c6a2109200541086a21052001417f4a0d000b20030d010c020b2018210a2003450d010b2003417f6a21032007200a4102746a41e4016a28020021070c010b0b2014201737020020152013360200200241c0006a410c6a200a360200200241c0006a41086a200241206a36020020022007360244200241003602402002200437023420022016360230200241c0006a200241306a10a40220102012470d010c080b20092802002101200920043702002009417c6a220a2802002105200a201636020002402005450d002001450d00200510190b20102012470d000c070b0b200fa7450d010b200610190b200041003602000c0a0b2000410036020002402009450d002009410c6c210a200c210503400240200541046a280200450d00200528020010190b2005410c6a2105200a41746a220a0d000b0b0240200b450d00200c10190b200fa7450d0920061019200241a0026a24000f0b200c210d200fa70d020c030b2011210d0b200fa7450d010b200610190b0240200d2011460d000340200d2802002205450d010240200d41046a280200450d00200510190b200d410c6a220d2011470d000b0b0240200b450d00200c10190b200241c0006a41086a2205200241206a41086a28020036020020022002290320370340200041086a200528020036020020002002290340370200200241a0026a24000f0b101d000b200d4104101c000b41e4014104101c000b102b000b200241a0026a24000bad0201077f230041106b2202240020012802042103024002400240024003402001280200220541086a210620052f010622044103742101410021070240024003402001450d0141f982c200200641081097032208450d02200141786a2101200741016a2107200641086a21062008417f4a0d000b2007417f6a21040b2003450d022003417f6a2103200520044102746a41e4016a21010c010b0b200541e0006a2007410c6c6a2201450d00200128020821062001280200210120024200370308200241086a200120064108200641084922071b1095031a20070d01200041086a2002290308370300410021010c030b2000418183c200360204200041086a41283602000c010b200041a983c200360204200041086a41293602000b410121010b20002001360200200241106a24000be20303027f017e027f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d0020002001410c6c6a220441e4006a2902002105200141016a2101200441e0006a2802002204450d030c010b0240024020002802002201450d0020003301044220862003ad842105410121060c010b2003ad210541002106410021010b200010192005a72103024002402005422088a7220720012f01064f0d00200121040c010b03400240024020012802002204450d00200641016a210620013301044220862003ad8421050c010b2003ad2105410021040b200110192005a72103200421012005422088a7220720042f01064f0d000b0b200420074102746a41e8016a280200210020042007410c6c6a220141e4006a2902002105200141e0006a2802002104024020064101460d00410120066b2101034020002802e4012100200141016a22010d000b0b410021012004450d020b2002417f6a210202402005a7450d00200410190b20020d000b0b0240200041a0c0c100460d0020002802002101200010192001450d0020012802002104200110192004450d00024020042802002201450d000340200410192001210420012802002200210120000d000b0b200410190b0b983a190c7f017e067f017e0b7f017e027f027e017f017e027f037e037f037e017f027e067f017e027f027e0e7f027e0e7f027e107f230041d0026b22022400024002402001450d00200220003602100c010b200241d889c2003602100b20022001360214200241f0006a200241106a10e3010240024002400240024020022802782203450d00200241f0016a2802002104200241ec016a280200210520024180016a2802002106200241fc006a280200210720022802e8012108200241186a200241106a109f022002280218450d01200241306a41086a2201200241186a41086a220928020036020020022002290318370330200241c0006a41086a200128020036020020022002290330370340200241013b015c20024200370254200241a0c0c100360250200241d0006a41086a210a2004450d0241e001210b2008200441e0016c6a210c41f000210d4202210e4115210f41a099c10021104100211141d889c200211241102113417f2114427f2115410321164102211741e401211841ac82c2002119410c211a41e000211b4107211c418801211d419001211e410d211f200241d0006a410d6a212042f4d2b59bc7ae98b830212141dc01212220024184016a21234201212442818080801021254109212642898080809001212741782128419399c1002129423c212a428080808070212b4225212c41ff01212d2008212e4100212f0c030b2002412c6a410136020020024103360254200241d4abc3003602502002420137021c200241a4abc3003602182002200241d0006a360228200241186a41acabc30010f201000b20024184016a410136020020024103360254200241d4abc30036025020024201370274200241a4abc3003602702002200241d0006a36028001200241f0006a41acabc30010f201000b410021010c010b410221010b037e024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e03000102020b200241f0006a41086a200a290300370300200220022903503703700c1e0b412f411e2070205a410c6c6a41a07f4622431b214441e585c00041d283c20020431b21430c010b024002400240024002400240202f0e06000102030405050b202e200d6a290300200e520d130240202e2d0088012201450d00203121302001202d714101470d4e0c4d0b202e29039001200e520d4a202e290398012132200241f0006a41086a22334200370300200242003703702010200f200241f0006a1001200920332903003703002002200229037037031802400240200241186a201320122011201110002014460d0020024200370370200241186a2013200241f0006a41082011100041016a41084d0d08200229037021340c010b420521340b2015203420347c223520352034541b2234500d09200241c0006a2136200228024421370c1e0b2046204e204c204d6a22012001204c491b6a22012046490d452046204d742200200120012000491b2247ad204f862234205088a70d452034a722012051480d4502402046450d00204820462052742001101a22480d0e0c070b2001101b22480d0c0c060b204820462052746a204b3602002046204d6a2146204c450d200240204a20442f01064f0d002044204a2053746a20546a214b204a204d6a214a204c204e6a214c20472046460d0a0c0b0b41012101024020442f01042200204428020022442f0106490d004101210103402001204d6a210120442f01042200204428020022442f01064f0d000b0b204420002053746a20546a214b204420002052746a20556a28020021444100214a2001204d460d1e204d20016b2101034020442802e40121442001204d6a22010d000c1f0b0b2057205e205d20566a22012001205d491b6a22012057490d4320572056742200200120012000491b2258ad205f862234206088a70d432034a722012061480d4302402057450d00205920572062742001101a22590d100c060b2001101b22590d0e0c050b205920572062746a205c360200205720566a21570240205d450d000240205b20432f01064f0d002043205b20636c6a20646a215c205b20566a215b205d205e6a215d20582057460d0d0c0e0b41012101024020432f01042200204328020022432f0106490d00410121010340200120566a210120432f01042200204328020022432f01064f0d000b0b2043200020636c6a20646a215c204320002062746a20656a28020021434100215b20012056460d1c205620016b2101034020432802e4012143200120566a22010d000c1d0b0b2059215a2046413f4b0d2e0c210b2067280200227020666a210020702f0106223b20697421014100215a024003402001450d01206d20002066109703223a450d112001206e6a2101205a206f6a215a200020666a2100203a206a4a0d000b205a206a6a213b0b02402068450d002068206a6a21682070203b206b746a206c6a21674105212f0c190b412f214441e585c00021430b2002204436026420022043360260200242efcc99e3a6ae99b830370318200241086a200241d0006a200241186a200241e0006a10a302200228020822440d04200241f0006a41086a200241d0006a41086a290300370300200220022903503703700c1b0b41fcf9c00041331030000b20014104101c000b20014104101c000b41f0a5c2001029000b41e7d6c10041222044200228020c10f301000b4101212f0c090b4102212f0c090b4102212f0c090b4102212f0c090b4103212f0c090b4104212f0c090b4104212f0c090b4104212f0c090b410021010c400b410121010c3f0b410221010c3e0b410221010c3d0b410221010c3c0b410221010c3b0b410221010c3a0b410221010c390b410221010c380b410221010c370b410221010c360b41002101034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e020001010b2036280200223941086a210020392f0106223820167421014100213a0240024003402001450d01201920004108109703223b450d02200120286a2101203a41016a213a200041086a2100203b20144a0d000b203a20146a21380b2037450d0a203720146a2137203920382017746a20186a2136410021010c1b0b2039201b6a203a201a6c6a2200450d09200028020821012000280200210020024200370370200241f0006a20002001410820014108491b1095031a2001201c4d0d0a20322034802002290370223c520d0c0240202e201d6a2d00002201450d00203121302001202d714101460d490c4a0b202e201e6a290300200e520d46202e290398012135200241f0006a200241c0006a10a002024020022802704101470d00203335020021302002280274213d4101213e20202d00000d170c050b2033290300213f4200213020334200370300200242003703702029201f200241f0006a100120092033290300370300200220022903703703180240200241186a201320122011201110002014460d0020024200370370200241186a2013200241f0006a41082011100041016a41084d0d13200229037021300b20334200370300200242003703702010200f200241f0006a10012009203329030037030020022002290370370318200241186a201320122011201110002014460d0120024200370370200241186a2013200241f0006a41082011100041016a41084d0d13200229037021402035203f202a7c580d030c020b204141086a210020412f0106223920167421014100213a024003402001450d01200241186a20004108109703223b450d0f200120286a2101203a41016a213a200041086a2100203b20144a0d000b203a20146a21390b02402042450d00204220146a2142204120392017746a20186a2802002141410121010c1a0b20232021370200200241f0006a20136a200a360200200241f0006a201a6a20393602002033200241d0006a360200200220413602742002201136027020092011360200200220243703184101101b210102400240203e450d002001450d11200141013a00002002202537021c2002200136021820022030a72201360260200241e0006a200241186a105d200228021c223a200928020022006b20014f0d01200020016a223b2000490d43203a4101742239203b203b2039491b223b2011480d43203a450d062002280218203a203b101a223a0d070c120b2001450d14200120113a00002002202537021c20022001360218200141012026101a2201450d15200120303700012002202737021c200220013602180c080b2002280218213a0c060b420521402035203f202a7c580d010b2031202b83202c8421304101213e41a59ec100213d20202d0000450d010c130b4100213e2035204020307c22305a0d4220202d00000d120b02400240203e450d0020022802502002280254200a28020010a10220024200370254200241a0c0c100360250200220213703180c010b2002280250214120022021370318204141a0c0c100460d00200228025421420c150b2018101b2241450d0a41002142204141003b010620414100360200204141086a200241f0006a20221095031a20024100360254200220413602500c130b203b101b223a450d0b0b2002203b36021c2002203a3602180b2009200020016a360200203a20006a203d20011095031a0b200241e0006a41086a200928020036020020022002290318370360200241f0006a200241e0006a10a4022020203e3a0000200241d0006a201a6a20113a0000203e450d3e200241f0006a41086a200241d0006a41086a290300370300200220022903503703700c140b203c42808080807083421c84213441dd82c20021440c010b203c42808080807083422984213441b482c20021440b2034a721430c010b4131214341ac85c00021440b2002204336026420022044360260200242e1eac98bb68edbb7f4003703182002200241d0006a200241186a200241e0006a10a302200228020022440d09200241f0006a41086a200241d0006a41086a290300370300200220022903503703700c0f0b41e7d6c10041224189d7c100412d10f301000b41e4014104101c000b41014101101c000b203b4101101c000b41fcf9c00041331030000b41fcf9c00041331030000b41014101101c000b41094101101c000b41e7d6c100412241b6d7c100413110f301000b41e7d6c10041222044200228020410f301000b410121010c010b410121010c000b0b205d205e6a215d0240024020582057460d004104212f0c010b4103212f410221010c350b410221010c340b204c204e6a214c0240024020472046460d004102212f0c010b4101212f410221010c340b410221010c330b20022802402002280244200228024810a10202402006450d00200641286c2143200321440340024020442d00002201450d00024020014101470d00204441086a280200450d01204441046a2802001019204441286a2144204341586a22430d020c030b204441146a280200450d00204441106a28020010190b204441286a2144204341586a22430d000b0b02402007450d00200310190b02402004450d00200441e0016c214320084188016a2144034020441043204441e0016a2144204341a07e6a22430d000b0b02402005450d00200810190b4101101b2244450d05204420022d007c3a0000204441014102101a2245450d06204520022d007d3a0001200228027022432144024020022802742200450d002043214420002101034020442802e40121442001417f6a22010d000b2000210103402001417f6a22010d000b0b0240024002402002280278222f450d00202f417f6a214620442f0106450d01204441086a213a410121000c020b4100214741042148410421494100214620000d030c040b0240024020442f01042200204428020022442f01064f0d00410121010c010b410121010340200141016a210120442f01042200204428020022442f01064f0d000b0b204420004103746a41086a213a204420004102746a41e8016a28020021444100210020014101460d00410120016b2101034020442802e4012144200141016a22010d000b0b417f204641016a220120012046491b2247ad2234421e88a70d042034420286a72201417f4c0d04024002400240024002402001450d002001101b2248450d0d2048203a3602002046450d020c010b410421484104203a3602002046450d010b200020442f01064f0d01200041016a214a204420004103746a41086a214b0c020b410121460c020b0240024020442f01042200204428020022442f01064f0d00410121010c010b410121010340200141016a210120442f01042200204428020022442f01064f0d000b0b204420004103746a41086a214b204420004102746a41e8016a28020021444100214a20014101460d00410120016b2101034020442802e4012144200141016a22010d000b0b202f417e6a214c4101214d417f214e4202214f422021504100215141022152410321534108215441e80121554101214620474101470d0a4101212f0c0c0b204821492002280270214320022802742200450d010b20002101034020432802e40121432001417f6a22010d000b03402000417f6a22000d000b0b024002400240200241f8006a2802002256450d002056417f6a215720432f0106450d01204341e0006a212f410121000c020b41002158410421594104215a410021572046413f4d0d020c0f0b0240024020432f01042200204328020022432f01064f0d00410121010c010b410121010340200141016a210120432f01042200204328020022432f01064f0d000b0b20432000410c6c6a41e0006a212f204320004102746a41e8016a28020021434100210020014101460d00410120016b2101034020432802e4012143200141016a22010d000b0b417f205741016a220120012057491b2258ad2234421e88a70d012034420286a72201417f4c0d01024002400240024002402001450d002001101b2259450d0b2059202f3602002057450d020c010b410421594104202f3602002057450d010b200020432f01064f0d01200041016a215b20432000410c6c6a41e0006a215c0c020b410121572059215a2046413f4b0d0f0c020b0240024020432f01042200204328020022432f01064f0d00410121010c010b410121010340200141016a210120432f01042200204328020022432f01064f0d000b0b20432000410c6c6a41e0006a215c204320004102746a41e8016a28020021434100215b20014101460d00410120016b2101034020432802e4012143200141016a22010d000b0b2056417e6a215d41012156417f215e4202215f422021604100216141022162410c216341e000216441e80121654101215720584101470d084103212f0c0b0b410121044101101b2256450d03205620464102743a000020464102742243450d120c0d0b102b000b41014101101c000b41024101101c000b41014101101c000b20014104101c000b20014104101c000b4102212f0c020b4104212f0c030b410221010c250b410221010c240b410221010c230b410221010c220b02402046418080014f0d00410221044102101b2256450d02205620464102744101723b0000204641027422430d010c060b024020464180808080044f0d00410421044104101b2256450d0320562046410274410272360000204641027422430d010c060b4101101b2244450d03204441033a000041052104204441014105101a2256450d042056204636000120464102742243450d050b410020046b21442004214602400340204928020021010240200420446a41074b0d00204641086a22002046490d152004410174224d20002000204d491b22004100480d15024002402004450d00205620042000101a22560d010c040b2000101b2256450d030b200021040b204941046a2149205620466a2001290000370000204441786a2144204641086a21462043417c6a22430d000b2057413f4b0d060c070b20004101101c000b41024101101c000b41044101101c000b41014101101c000b41054101101c000b200421462057413f4d0d010b02402057418080014f0d00410221434102101b2249450d08204920574102744101723b00000c020b024020574180808080044f0d00410421434104101b2249450d07204920574102744102723600000c020b4101101b2244450d05204441033a000041052143204441014105101a2249450d04204920573600010c010b410121434101101b2249450d07204920574102743a0000410121012057450d010b2057410274214d204321010340205a28020022442802002157024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020442802082244413f4b0d0020432001470d01204341016a22012043490d2120434101742200200120012000491b22004100480d212043450d05204920432000101a22490d060c0f0b2044418080014f0d01204320016b41014b0d02200141026a22002001490d2020434101742266200020002066491b22004100480d202043450d0b204920432000101a22490d0c0c0f0b204321000c050b20444180808080044f0d01204320016b41034b0d05200141046a22002001490d1e20434101742266200020002066491b22004100480d1e024020430d002000101b2249450d100c070b204920432000101a22490d060c0f0b204321000c090b20432001470d05204341016a22012043490d1c20434101742200200120012000491b22004100480d1c0240024020430d002000101b2249450d100c010b204920432000101a2249450d0f0b204321010c060b2000101b2249450d090b204321010b204920016a20444102743a00002000200141016a22016b20444f0d060c0c0b204321000b204920016a20444102744102723600002000200141046a22016b2044490d0a0c040b204321000b204920016a41033a000002402000200141016a22436b41034b0d00204341046a22662043490d162000410174222f20662066202f491b22664100480d16024002402000450d00204920002066101a22490d010c080b2066101b2249450d070b206621000b204920436a20443600002000200141056a22016b2044490d080c020b2000101b2249450d030b204920016a20444102744101723b00002000200141026a22016b2044490d060b200021430c060b20004101101c000b20004101101c000b20664101101c000b20004101101c000b20004101101c000b200120446a22432001490d0c20004101742266204320432066491b22434100480d0c02402000450d00204920002043101a22490d010c040b2043101b2249450d030b205a41046a215a204920016a205720441095031a200120446a2101204d417c6a224d0d000b0b024002400240200420466b20014f0d00204620016a22442046490d0c20044101742200204420442000491b22004100480d0c2004450d01205620042000101a2256450d020c090b204620016a2144205620466a204920011095031a2043450d0a0c090b2000101b22560d070b20004101101c000b20434101101c000b41054101101c000b41014101101c000b41044101101c000b41024101101c000b41014101101c000b20002104205620466a204920011095031a2043450d010b204910190b02402058450d00205910190b02402047450d00204810190b02402044450d00204441026a22432044490d0120434104204341044b1b22014100480d01204541022001101a2245450d02204541026a205620441095031a2004450d040c030b204441026a2143204541026a205620441095031a20040d020c030b101d000b20014101101c000b205610190b20022802702002280274200241f8006a28020010a102200241d0026a24002043ad4220862045ad840f0b203121300b202e201d6a2d0000202d714101470d010b202e280290012016460d010b20302131202e200b6a222e200c470d010c030b200241c0006a2167200228024421684108216641032169417f216a4102216b41e401216c41dd85c000216d4178216e4101216f0c010b4100212f0c020b4105212f0c020b410021010c020b410221010c010b410221010c000b0bcc0403037f017e047f23004180026b220424000240024020012d000d450d0041b6d7c1002102413121050c010b2001280200200141046a2205280200200141086a220628020010a10220054200370200200141a0c0c100360200200420022900002207370310024002400240024041e401101b2208450d00200841003b010620084100360200200841086a200441206a41dc011095031a200541003602002001200836020020082f01062209410374210a417f210541002102024002400240024002400340200a2002460d01200441106a200820026a41086a4108109703220b450d03200541016a2105200241086a2102200b41004e0d000c020b0b200921050b20042007370234200420063602302004200536022c2004200136022820042008360224200441003602202004410036021820044201370310200328020021082004200328020422023602002004200441106a105d02402004280214220b200428021822056b20024f0d00200520026a220a2005490d05200b4101742203200a200a2003491b220a4100480d05200b450d022004280210200b200a101a220b450d030c060b2004280210210b0c060b4189d7c1002102412d21050c060b200a101b220b0d030b200a4101101c000b41e4014104101c000b101d000b2004200a3602142004200b3602100b200441106a41086a220a200520026a360200200b20056a200820021095031a200441086a200a28020036020020042004290310370300200441206a200410a40220014180023b010c410021020b200020053602042000200236020020044180026a24000bea1105027f017e067f037e0b7f230041e0026b2202240020002802102203200328020041016a36020020002902142104200028020c2103200028020821052000280200210620002802042100200241306a41086a2207200141086a28020036020020022001290200370330024020002f01062201410b4f0d00200020034103746a220841106a200841086a2208200120036b4103741096031a2008200437000020002003410c6c6a220141ec006a200141e0006a2209200041066a22082f010020036b410c6c1096031a200141e8006a200728020036020020092002290330370200200820082f010041016a3b01002002200036001720022006360013200241e0026a24000f0b02400240024041e401101b220a450d00200a41003b0106200a4100360200200a41086a200241d0006a41dc011095032107200241d0006a41086a2208200041b0016a280200360200200220002902a8013703502000413c6a330000210b2000413e6a310000210c20002d003f21092000350038210d2007200041c0006a200041066a220e2f010041796a22014103741095032107200a41e0006a200041b4016a2001410c6c109503210f200e41063b0100200a20013b0106200241c0006a41086a200828020036020020022002290350370340200d200b200c4210868442208684210b02400240200341064b0d00200041086a20034103746a220741086a2007200041066a22012f010020036b4103741096031a20072004370000200041e0006a2003410c6c6a2207410c6a200720012f010020036b410c6c1096031a200741086a200241306a41086a280200360200200720022903303702000c010b200720034103746a41506a2007200341796a22084103746a2207200141ffff037120086b4103741096031a20072004370000200f2003410c6c6a220341b87f6a200341ac7f6a2207200a41066a22012f010020086b410c6c1096031a200341b47f6a200241306a41086a280200360200200720022903303702000b200120012f010041016a3b0100200241206a41086a2210200241c0006a41086a2211280200360200200220093a0017200220022903403703202002200b3e02102002200b4230883c00162002200b4220883d0114200241086a22122010280200360200200220022903203703002002290310210402400240024020002802002209450d0020002f0104211303402002200641016a220636021020022009360214200241306a41086a2214201228020036020020022002290300370330201341ffff0371210820092f01062200410a4d0d02419402101b2207450d03200741003b010620074100360200200741086a200241d0006a418c021095032103200941386a290000210b200241d0006a41086a220f200941b0016a2802003602002002200941a8016a2902003703502003200941c0006a200941066a22152f0100220141796a22004103741095032116200741e0006a200941b4016a2000410c6c1095032117200741e4016a20094180026a2001417a6a220e4102741095032118201541063b0100200720003b01060240200e450d00410021002018210303402003280200220120003b010420012007360200200341046a2103200e200041016a2200470d000b0b2011200f28020036020020022002290350370340200f20112802003602002002200229034037035002400240201341ffff0371220341064b0d00200941086a2200200841016a220e4103746a200020084103746a220020152f0100220120086b22134103741096031a20002004370000200941e0006a2008410c6c6a2200410c6a20002013410c6c1096031a200041086a2014280200360200200020022903303702002015200141016a22003b0100200941e4016a2201200841027422156a41086a2001200e4102746a2213200041ffff03712201200e6b4102741096031a2013200a360200200320014f0d01200920156a41e8016a2100034020002802002203200841016a22083b010420032009360200200041046a210020012008470d000c020b0b20162008417a6a22034103746a2016200841796a22004103746a220e200741066a22012f010020006b4103741096031a200e200437000020172008410c6c6a220e41b87f6a200e41ac7f6a221320012f0100221520006b410c6c1096031a200e41b47f6a2014280200360200201320022903303702002001201541016a220e3b01002018200841027422136a416c6a201820034102746a2201200e41ffff0371220820036b4102741096031a2001200a360200200320084b0d00200720136a41cc016a2103034020032802002201200041016a22003b010420012007360200200341046a210320082000470d000b0b2010200f280200360200200220022903503703202012201028020036020020022002290320370300024020092802002200450d0020092f0104211320002109200b21042007210a0c010b0b2007210a200b21040b419402101b2200450d03200041003b010620004100360200200041086a200241d0006a418c0210950321012000200528020022033602e401200520003602002005200528020441016a360204200341003b010420032000360200200120002f010622034103746a200437000020002003410c6c6a220141e8006a200241086a280200360200200141e0006a2002290300370200200041e4016a200341016a22034102746a200a360200200020033b0106200a20033b0104200a20003602000c040b200941086a2201200841016a22034103746a200120084103746a2201200020086b22074103741096031a2001200437000020092008410c6c6a220141ec006a200141e0006a220e2007410c6c1096031a200141e8006a200241306a41086a280200360200200e2002290330370200200941066a200041016a22003b0100200941e4016a220120084102746a41086a200120034102746a2201200041ffff0371220720036b4102741096031a2001200a360200201341ffff037120074f0d0320092003417f6a22004102746a41e8016a2103034020032802002201200041016a22003b010420012009360200200341046a210320072000470d000c040b0b4194024104101c000b41e4014104101c000b4194024104101c000b200241e0026a24000b960301037f230041d0006b22022400200241306a41086a2203420037030020024200370330418b82c0004111200241306a1001200241206a41086a2003290300370300200220022903303703200240024002400240200241206a411041d889c200410041001000417f460d00200241c8006a4200370300200241306a41106a42003703002003420037030020024200370330200241206a4110200241306a4120410010002203417f460d022003411f4d0d02200241186a200241306a41186a290300370300200241106a200241306a41106a290300370300200241086a200241306a41086a29030037030020022002290330370300412021044120101b2203450d010c030b200241186a4200370300200241106a4200370300200241086a420037030020024200370300412021044120101b22030d020b20044101101c000b41fcf9c00041331030000b20032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a290300370000200241d0006a24002003ad42808080808004840bfc1404047f017e087f017e230041c0076b22022400024002402001450d00200220003602000c010b200241d889c2003602000b20022001360204200241e0056a20021035024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022903d0064203510d00200241086a200241e0056a41e0011095031a200241e8016a200241086a41e0011095031a2002200241e8016a3602d004200241e0056a200241d0046a10900220022802e8052103024020022802e405450d0020022802e00510190b200241e0056a200241e8016a41e0011095031a200241d0046a200241e0056a105f024002400240024002400240024020022802d0044101470d0020022802d404210120022802d8042200411a460d0120004115470d024102210441f6012100200141bde3c100460d0f200141bde3c10041151097030d020c0f0b200241c8036a200241d0046a41086a4188011095031a410021040240200241c8036a41086a410020022903c8034201511b2201450d002001450d00410321002001200310a702450d03410021040c0e0b4176416c20011b21000c0d0b41002100200141d2e3c100460d0241002104200141d2e3c100411a109703450d0d0b4100210441810121000c0c0b200141206a410020011b210c2001106721064101210041002104200c290300220f2006540d0a4102210041022104200f20064280027c560d0a2006200f5a0d014100210b41002105410021074100210e4104210903404120101b2200450d0520002001290000370000200041186a200141186a290000370000200041106a200141106a290000370000200041086a200141086a2900003700002000412041c000101a2200450d062000200637002002402007200e470d00200741016a220a2007490d20200b200a200a200b491b220ead420c7e220f422088a70d20200fa7220a4100480d2002402007450d0020092005200a101a22090d010c090b200a101b2209450d080b200920056a220a2000360200200a41046a42c08080808005370200200b41026a210b2005410c6a2105200741016a2107200642017c2206200c290300220f540d000c030b0b410021040c0a0b41042109410021074100210e0b410c101b220d450d044120101b2200450d0520002001290000370000200041186a200141186a290000370000200041106a200141106a290000370000200041086a200141086a2900003700002000412041c000101a2201450d062003ad21062001200f370020200d42c08080808005370204200d2001360200200241f8036a1043200241003602e805200242013703e00541012104410121014101101b22000d090c140b200241fc016a41013602002002410336020c200241dcabc300360208200242013702ec01200241a4abc3003602e8012002200241086a3602f801200241e8016a41acabc30010f201000b41204101101c000b41c0004101101c000b200a4104101c000b410c4104101c000b41204101101c000b41c0004101101c000b200241f8036a10430b200241003602e805200242013703e005024020044101460d0020044102470d024101101b2201450d0d200241013602e405200241e8056a22032003280200220541016a360200200220013602e005200120056a41023a000020022802e40520032802002201470d04200141016a22032001490d1320014101742205200320032005491b22054100480d132001450d0820022802e00520012005101a2203450d090c160b410121014101101b2200450d0b0b200241e0056a41086a22032003280200220520016a360200200220013602e405200220003602e005200020056a20013a000020022802e4052200200328020022016b41084f0d01200141086a22032001490d1120004101742201200320032001491b22014100480d112000450d0420022802e00520002001101a2200450d050c0f0b4101101b2201450d0b200241013602e405200241e8056a22032003280200220541016a360200200220013602e005200120056a41003a000020022802e40520032802002201470d02200141016a22032001490d1020014101742205200320032005491b22054100480d102001450d0720022802e00520012005101a2203450d080c0c0b20022802e00521000c0e0b20022802e00521030c120b20022802e00521030c0a0b2001101b22000d0a0b20014101101c000b2005101b22030d0d0b20054101101c000b2005101b22030d040b20054101101c000b20012001101c000b41014101101c000b41014101101c000b200220053602e405200220033602e005200241e8056a28020021010b200241e8056a200141016a360200200320016a20003a00000c070b200220013602e405200220003602e005200241e8056a28020021010b200241e0056a41086a2205200141086a360200200020016a2006370000200220073602e801200241e8016a200241e0056a105d02400240024002402007450d0020092007410c6c6a21082009210303402003280200210a2002200341086a28020022013602e801200241e8016a200241e0056a105d024002400240024020022802e405220b200528020022006b20014f0d00200020016a220c2000490d09200b4101742200200c200c2000491b22004100480d09200b450d0120022802e005200b2000101a220b0d020c060b20022802e005210b0c020b2000101b220b450d040b200220003602e4052002200b3602e005200528020021000b2005200020016a360200200b20006a200a20011095031a2003410c6a22032008470d000b0b200241013602e801200241e8016a200241e0056a105d200d280200210b2002200d28020822013602e801200241e8016a200241e0056a105d02400240024020022802e4052203200528020022006b20014f0d00200020016a22052000490d0620034101742200200520052000491b22004100480d062003450d0120022802e00520032000101a2203450d020c040b20022802e00521030c040b2000101b22030d020b20004101101c000b20004101101c000b200220003602e405200220033602e005200241e8056a28020021000b200241e0056a41086a2205200020016a360200200320006a200b20011095031a02400240024020022802e4052200200528020022016b41084f0d00200141086a22032001490d0320004101742201200320032001491b22014100480d032000450d0120022802e00520002001101a2200450d020c040b20022802e00521000c040b2001101b22000d020b20014101101c000b101d000b200220013602e405200220003602e005200241e8056a28020021010b200241e0056a41086a2203200141086a360200200020016a427f3700002003280200210320022802e005210520044101470d0302402007450d002007410c6c21002009210103400240200141046a280200450d00200128020010190b2001410c6a2101200041746a22000d000b0b0240200e450d00200910190b0240200d41046a280200450d00200d28020010190b200d10190c030b200220053602e405200220033602e005200241e8056a28020021010b200241e8056a200141016a360200200320016a20003a00000b200241e8056a280200210320022802e00521050b200241c0076a24002003ad4220862005ad840ba90c04027f047e017f037e230041f0006b22022400200241c0006a41086a22034200370300200242003703404194c8c1004117200241c0006a1001200241d0006a41086a20032903003703002002200229034037035002400240024002400240024002400240024002400240200241d0006a411041d889c200410041001000417f460d002002420037036820024200370360200241d0006a4110200241e0006a4110410010002203417f460d022003410f4d0d02200241e8006a2903002104200229036021050c010b42002105420021040b200241206a200442002001ad22064200109903200241306a2005420020064200109903200241106a42004200200542001099034182d6c100210102402002290328200229031884420052200241306a41086a2903002205200229032020022903107c7c2206200554720d002002290330210742002104200241c0006a41086a220342003703002002420037034041fdc7c1004117200241c0006a1001200241d0006a41086a20032903003703002002200229034037035002400240200241d0006a411041d889c200410041001000417f460d002002420037036820024200370360200241d0006a4110200241e0006a4110410010002203417f460d052003410f4d0d05200241e8006a2903002105200229036021040c010b420021050b200420077c22072004542203200520067c2003ad7c220420055420042005511b4101460d00024002400240419384c000411041d889c200410041001000417f460d0020024100360260419384c0004110200241e0006a41044100100041016a41044d0d0520022802602103411a101b2201450d08200141186a41002f00c3c8413b0000200141106a41002900bbc841370000200141086a41002900b3c841370000200141002900abc8413700002001411a4134101a2201450d092001200336001a42002106200241c0006a41086a22084200370300200242003703402001411e200241c0006a1001200241d0006a41086a200829030037030020022002290340370350200241d0006a411041d889c200410041001000417f460d012002420037036820024200370360200241d0006a4110200241e0006a4110410010002208417f460d072008410f4d0d07200241e8006a2903002105200229036021060c020b200241f0006a24004194d6c1000f0b420021050b2001101941acd6c1002101200620077c22092006542208200520047c2008ad7c220620055420062005511b0d00200010a60122010d0020022000104541e6fac00021012002290300220a2007542208200241086a290300220520045420052004511b0d002000200a20077d200520047d2008ad7d104642002105200241c0006a41086a220142003703002002420037034041a7fbc0004116200241c0006a1001200241d0006a41086a20012903003703002002200229034037035002400240200241d0006a411041d889c200410041001000417f460d002002420037036820024200370360200241d0006a4110200241e0006a4110410010002201417f460d092001410f4d0d09200241e8006a290300210a200229036021050c010b4200210a0b0240200520077d220b200556200a20047d2005200754ad7d2205200a562005200a511b0d002002200b37035020022005370358200241c0006a41086a220142003703002002420037034041a7fbc0004116200241c0006a1001200241e0006a41086a200129030037030020022002290340370360200241e0006a4110200241d0006a411010030b411a101b2200450d0841002101200041186a41002f00c3c8413b0000200041106a41002900bbc841370000200041086a41002900b3c841370000200041002900abc8413700002000411a4134101a2200450d092000200336001a2002200637036820022009370360200241c0006a41086a22034200370300200242003703402000411e200241c0006a1001200241d0006a41086a200329030037030020022002290340370350200241d0006a4110200241e0006a41101003200010190b200241f0006a240020010f0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b411a4101101c000b41344101101c000b41fcf9c00041331030000b411a4101101c000b41344101101c000bd60a07027f017e047f017e037f037e037f230041306b22022400024002402001450d00200220003602080c010b200241d889c2003602080b2002200136020c200241106a200241086a10de010240024002400240024002400240024020022802102203450d0020022902142204a721052003210041002106024002400240024002402004422088a7220741286c2201450d000240034020002d00004102460d01200041286a210041002106200141586a2201450d020c000b0b200041106a280200210141082108200041086a29030021094100210a4100210b0240200041186a280200220c41286c22004128490d0020004100480d03200cad42287e422088a74100470d032000101b2208450d09200c210b0b2001200120006a460d01200c41286c210c4100210a200821000340200141086a2903002104200141106a290300210d200141186a290300210e2001290300210f200041206a200141206a290300370300200041186a200e370300200041106a200d370300200041086a20043703002000200f370300200041286a2100200a41016a210a200141286a2101200c41586a220c0d000c020b0b410021080b20022006360218200242013703104101101b210c02400240024002402008450d00200c450d0820024281808080103702142002200c360210200c41013a00002002200a360228200241286a200241106a105d200241106a41086a221028020021002002280214210c0240200a450d002008200a41286c6a21112008210103400240024002400240200c20006b41204f0d00200041206a220a2000490d0a200c4101742206200a200a2006491b22124100480d0a200c450d012002280210200c2012101a22060d020c0b0b200041206a210a200228021021060c020b2012101b2206450d090b20022012360214200220063602102012210c0b2010200a360200200620006a220041186a200141186a290000370000200041106a200141106a290000370000200041086a200141086a29000037000020002001290000370000200141206a29030021040240024002400240200c200a6b41084f0d00200a41086a2200200a490d0a200c4101742212200020002012491b22124100480d0a200c450d012006200c2012101a22060d020c0c0b200a41086a21000c020b2012101b2206450d0a0b20022012360214200220063602102012210c0b201020003602002006200a6a20043700002011200141286a2201470d000b0b200c20006b41084f0d01200041086a22012000490d04200c410174220a20012001200a491b22014100480d04200c450d022002280210200c2001101a220c450d030c0b0b200c450d0820024281808080103702142002200c360210200c41003a0000428080808010210420070d0c0c0d0b2002280210210c0c0a0b2001101b220c0d080b20014101101c000b101d000b20124101101c000b20124101101c000b200241246a41013602002002410336022c200241e4abc30036022820024201370214200241a4abc3003602102002200241286a360220200241106a41acabc30010f201000b41014101101c000b41014101101c000b20004108101c000b200220013602142002200c3602100b200241106a41086a200041086a2201360200200c20006a20093700002001ad422086210402402008450d00200b450d00200810190b2007450d010b200741286c2100200321010340024020012d0000220a450d000240200a4101470d00200141086a280200450d01200141046a2802001019200141286a2101200041586a22000d020c030b200141146a280200450d00200141106a28020010190b200141286a2101200041586a22000d000b0b02402005450d00200310190b200241306a24002004200cad840ba205020a7f017e230041206b220224002002410e360204200241edd7c100360200200241106a41fbd7c1002002103b410021030240024002400240200228021022042002280218220541d889c200410041001000417f460d002002410036020020042005200241044100100041016a41044d0d01200228020021030b02402002280214450d00200410190b2002200310be0120024100360218200242013703102002280200210620022002280208220336020c2002410c6a200241106a105d02400240024002402003450d002006200341286c6a2107200241106a41086a22082802002104200228021421092006210303400240024002400240200920046b41204f0d00200441206a22052004490d062009410174220a20052005200a491b220b4100480d062009450d0120022802102009200b101a220a0d020c070b200441206a21052002280210210a0c020b200b101b220a450d050b2002200b3602142002200a360210200b21090b20082005360200200a20046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a290300210c0240024002400240200920056b41084f0d00200541086a22042005490d062009410174220b20042004200b491b220b4100480d062009450d01200a2009200b101a220a0d020c080b200541086a21040c020b200b101b220a450d060b2002200b3602142002200a360210200b21090b20082004360200200a20056a200c3700002007200341286a2203470d000b2002280204450d060c050b200241186a28020021042002280210210a20022802040d040c050b101d000b200b4101101c000b200b4101101c000b41fcf9c00041331030000b200610190b200241206a24002004ad422086200aad840be90104027f017e017f017e230041206b22022400200241106a41086a220342003703002002420037031041a099c1004115200241106a1001200241086a20032903003703002002200229031037030002400240024002402002411041d889c200410041001000417f460d002002420037031020024110200241106a41084100100041016a41084d0d0220022903102104410821054108101b2203450d010c030b42052104410821054108101b22030d020b20054101101c000b41fcf9c00041331030000b2003427f200420047c220620062004541b370000200241206a24002003ad42808080808001840bbf0303027f017e027f02402001450d000340200028026c21002001417f6a22010d000b0b4100210341002101024003402002450d010240200120002f01064f0d0020014103742104200141016a21012002417f6a2102200020046a41146a290200a74103470d010c020b0240024020002802002201450d0020003301044220862003ad842105410121060c010b2003ad210541002106410021010b200010192005a72103024002402005422088a7220720012f01064f0d00200121040c010b03400240024020012802002204450d00200641016a210620013301044220862003ad8421050c010b2003ad2105410021040b200110192005a72103200421012005422088a7220720042f01064f0d000b0b200420074102746a41f0006a2802002100200420074103746a41146a2902002105024020064101460d00410120066b21010340200028026c2100200141016a22010d000b0b410021012002417f6a21022005a74103470d000b0b0240200041a0c0c100460d0020002802002101200010192001450d0020012802002104200110192004450d00024020042802002201450d000340200410192001210420012802002200210120000d000b0b200410190b0beb0503077f017e017f230041c0006b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f01064f0d01200241086a41086a220620052003410c6c6a220741106a2802003602002002200741086a290200370308200241186a41086a220820074194016a2802003602002007418c016a29020021092001410c6a200341016a360200200141086a2004360200200141046a200536020020022009370318200241286a41086a220320062802003602002002413c6a200828020036020020002002290308220937020020022002290318370234200041086a2003290300370200200041106a200241286a41106a29030037020020022009370328200241c0006a24000f0b20004100360200200241c0006a24000f0b200128020021070240024020052802002203450d00200741016a210720053301044220862004ad8421090c010b2004ad2109410021030b200510192009a72104024002402009422088a7220620032f01064f0d00200321050c010b03400240024020032802002205450d00200741016a210720033301044220862004ad8421090c010b2004ad2109410021050b200310192009a72104200521032009422088a7220620052f01064f0d000b0b200241086a41086a220820052006410c6c6a220341106a2802003602002002200341086a290200370308200241186a41086a220a20034194016a28020036020020022003418c016a290200370318200520064102746a4194026a2802002103024020074101460d00410120076b210503402003280290022103200541016a22050d000b0b200141003602002001410c6a4100360200200141086a2004360200200141046a2003360200200241286a41086a220320082802003602002002413c6a200a28020036020020002002290308220937020020022002290318370234200041086a2003290300370200200041106a200241286a41106a29030037020020022009370328200241c0006a24000b8503010e7f23004190016b220124002001200010ae02024020012903204202510d00200141c0006a21022001413c6a2103200141386a210420014184016a210520014180016a2106200141fc006a2107200141f8006a2108200141f0006a210903402002280200210a2004280200210b024002402003280200220c450d00200c210d200b210e0340200e28029002210e200d417f6a220d0d000b0340200b200b2f01064102746a4190026a280200210b200c417f6a220c0d000c020b0b200b210e0b200141e8006a41206a200a3602002005200b2f0106360200200641003602002007200b36020020084100360200200942003703002001200e36026c20014100360268200141e8006a1084012001200010ae02200141206a2903004202520d000b0b02402000280204220b41a0c0c100460d00200b280200210c200b1019200c450d00200c280200210e200c1019200e450d000240200e280200220b450d000340200e1019200b210e200b280200220c210b200c0d000b0b200e10190b20014190016a24000b950603087f017e017f230041d0016b220224000240024020012802202203450d00200141206a2003417f6a36020020012802082104200128020c2203200128020422052f01064f0d01200241186a2206200520034105746a220741206a290000370300200241106a2208200741186a290000370300200241086a2209200741106a2900003703002002200741086a290000370300200241206a2005200341c8006c6a41e8026a41c8001095031a2001410c6a200341016a360200200141086a2004360200200141046a2005360200200241e8006a41186a2006290300370300200241e8006a41106a2008290300370300200241e8006a41086a200929030037030020022002290300370368200241e8006a41206a200241206a41c8001095031a2000200241e8006a41e8001095031a200241d0016a24000f0b20004202370320200241d0016a24000f0b200128020021070240024020052802002203450d00200741016a210720053301044220862004ad84210a0c010b2004ad210a0b20051019200aa7210402400240200a422088a7220620032f01064f0d00200321050c010b03400240024020032802002205450d00200741016a210720033301044220862004ad84210a0c010b2004ad210a0b20031019200aa7210420052103200a422088a7220620052f01064f0d000b0b200241186a2208200520064105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220b200341106a2900003703002002200341086a290000370300200241206a2005200641c8006c6a41e8026a41c8001095031a200520064102746a4184096a2802002103024020074101460d00410120076b210503402003280280092103200541016a22050d000b0b200141003602002001410c6a4100360200200141086a2004360200200141046a2003360200200241e8006a41186a2008290300370300200241e8006a41106a2009290300370300200241e8006a41086a200b29030037030020022002290300370368200241e8006a41206a200241206a41c8001095031a2000200241e8006a41e8001095031a200241d0016a24000b130020004102360204200041c0afc3003602000b13002000410e3602042000419cc2c1003602000b13002000410436020420004190b1c3003602000b3101017f02404101101b2202450d00200042818080801037020420002002360200200241003a00000f0b41014101101c000bb90503047f027e037f230041106b22022400200241003a000820012802002001280204200241086a410120012802081000210320012001280208200341016a41014b22046a22033602080240024002402004450d0002400240024020022d000822054103712204450d0020044101460d0120044102470d0220024100360208200220053a0008200141086a220441002001280200200141046a280200200241086a41017241032003100022012001417f461b22014103200141034922011b20042802006a36020020010d032002280208410276ad2106420121070c050b2005410276ad2106420121070c040b200241003b0108200220053a00082001280200200141046a280200200241086a4101724101200310002103200141086a22012001280200200341016a220141014b6a36020020014102490d0120022f0108410276ad2106420121070c030b0240024020054102762204450d0020044104470d014200210720024200370308200141086a220441002001280200200141046a280200200241086a41082003100022012001417f461b22014108200141084922011b20042802006a36020020010d0320022903082106420121070c040b200141046a280200210420024100360208200141086a2205410020012802002004200241086a41042003100022012001417f461b22014104200141044922011b20052802006a36020020010d0120023502082106420121070c030b200441046a220841084b0d0042002106200141046a2109200141086a2105410021040340200241003a000820012802002009280200200241086a410120031000210320052005280200200341016a41014b220a6a2203360200200a450d0120023100082004410374413871ad86200684210642012107200441016a220441ff01712008490d000c030b0b420021070b0b2000200637030820002007370300200241106a24000bce0603067f037e037f230041306b22022400200241003a0020200241206a200128020022032001280204220441004722051095031a0240024002400240024020042005490d00200141046a200420056b22063602002001200320056a2205360200024002402004450d000240024020022d002022034103712204450d00024020044101460d0020044102470d02200241003a001e200241003b011c2002411c6a200520064103200641034922071b22041095031a200141046a200620046b3602002001200520046a36020020070d0320022f011c20022d001e41107472410874200372410276ad21080c080b200241003a0020200241206a2005200641004722041095031a20062004490d06200141046a200620046b3602002001200520046a3602002006450d0220022d002041087420037241fcff0371410276ad21080c070b2003410276ad21080c060b0240024020034102762204450d00024020044104460d002004410c470d024200210a2002420037032820024200370320200241206a200520064110200641104922031b22041095031a200141046a200620046b3602002001200520046a36020020030d04200241286a2903002109200229032021084201210a0c090b4200210a20024200370320200241206a200520064108200641084922031b22041095031a200141046a200620046b3602002001200520046a36020020030d03200229032021080c070b20024100360220200241206a200520064104200641044922031b22041095031a200141046a200620046b3602002001200520046a36020020030d01200235022021080c060b200441046a220b41104b0d00200141046a210c200241106a210d4200210842002109410021030340200241003a0020200241206a2005200641004722041095031a20062004490d04200c200620046b22073602002001200520046a22053602002006450d01200241086a20023100204200200341037441f80071109a03200d2903002009842109200229030820088421084201210a20072106200341016a22042103200441ff0171200b490d000c070b0b4200210a0b0c040b200520041027000b200420061027000b200420061027000b420021094201210a0b200020083703082000200a370300200041106a2009370300200241306a24000be141030f7f037e017f230041f0026b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d000022044102460d0020044103470d13200141216a2d00002105200141246a2802002106200341306a200141196a290000370300200341286a200141116a290000370300200341186a41086a200141096a29000037030020032001290001370318200241096a2800002107200241056a280000210820022d0001210920022d0000210a200341e0026a41026a220b200241046a2d00003a0000200341e0016a41086a220c200241156a290000370300200341e0016a410d6a220d2002411a6a2900003700002003200241026a2f01003b01e00220032002410d6a2900003703e001200a450d01410121020c020b200141086a2802002104200141046a280200210c200241096a2800002107200241056a280000210820022d0001210a20022d00002101200341e0026a41026a200241046a2d00003a0000200341e0016a41086a2209200241156a290000370300200341e0016a410d6a220b2002411a6a2900003700002003200241026a2f01003b01e00220032002410d6a2900003703e0012001450d03410121020c040b200341d0026a41026a200b2d00003a0000200341b8016a41086a200c290300370300200341b8016a410d6a200d290000370000200320032f01e0023b01d002200320032903e0013703b80141012102200941ff01714101470d00200341e0026a41026a200341d0026a41026a2d00003a0000200341e0016a41086a200341b8016a41086a290300370300200341e0016a410d6a200341b8016a410d6a290000370000200320032f01d0023b01e002200320032903b8013703e001410021020c010b418d81c0002108412a21070b2003413c6a41026a220a200341e0026a41026a2d00003a0000200341e0006a41086a2209200341e0016a41086a290300370300200341e0006a41106a200341e0016a41106a290300370300200320032f01e0023b013c200320032903e00137036020020d2f200341d3006a2009290300370000200341d8006a200341ed006a290000370000200320032f013c3b014020032007360047200320083600432003200329036037004b2003200a2d00003a0042200341c0006a10cc01450d034115101b2202450d102002410d6a41002900f0c541370000200241086a41002900ebc541370000200241002900e3c541370000200241154135101a2202450d11200220032903183700152002412d6a200341306a290300370000200241256a200341186a41106a2903003700002002411d6a200341186a41086a290300370000200341e0026a41086a22074200370300200342003703e00220024135200341e0026a1001200341d0026a41086a2007290300370300200320032903e0023703d002200341d0026a411041d889c200410041001000417f460d062003200341d0026a3602b801200341103602bc01200341003602e00120034100200341d0026a4110200341e0016a41044100100022072007417f461b2207410420074104491b22083602c001200741034d0d1520032802e001210e200341003602e001200341c0016a4100200341d0026a4110200341e0016a41042008100022072007417f461b2207410420074104491b20086a360200200741034d0d1520032802e001210f200341e0006a200341b8016a103a2003280260220b450d15200341e0006a41086a280200210920032802642110200341e0016a200341b8016a103a20032802e001220c450d14200341e0016a41086a280200210d20032802e4012111200210192006200e470d08200b20094105746a210a200b2102410021080340200a20026b41ff004d0d0b200341c0006a2002460d0c20082002200341c0006a412010970322074100476a21082007450d0c200241206a2207200341c0006a460d0c20082007200341c0006a412010970322074100476a21082007450d0c200241c0006a2207200341c0006a460d0c20082007200341c0006a412010970322074100476a21082007450d0c200241e0006a2207200341c0006a460d0c20024180016a210220082007200341c0006a412010970322074100476a210820070d000c0c0b0b200341d0026a41026a2201200341e0026a41026a2d00003a0000200341b8016a41086a2009290300370300200341b8016a410d6a200b290000370000200320032f01e0023b01d002200320032903e0013703b80141012102200a41ff01714101470d00200341186a41026a20012d00003a0000200341e0016a41086a200341b8016a41086a290300370300200341e0016a410d6a200341b8016a410d6a290000370000200320032f01d0023b0118200320032903b8013703e001410021020c010b418d81c0002108412a21070b2003413c6a41026a2201200341186a41026a2d00003a0000200341e0006a41086a220a200341e0016a41086a290300370300200341e0006a41106a200341e0016a41106a290300370300200320032f01183b013c200320032903e00137036020020d02200341d3006a200a290300370000200341c0006a41186a200341ed006a290000370000200320032f013c3b014020032007360047200320083600432003200329036037004b200320012d00003a0042200341c0006a10cc01450d01200341003602e801200342013703e0012004200341e0016a106420032802e401210820032802e801210a20032802e0012107200341e0016a41186a22094200370300200341e0016a41106a22024200370300200341e0016a41086a22014200370300200342003703e0012007200a200341e0016a1005200341b8016a41186a2009290300370300200341b8016a41106a220a2002290300370300200341b8016a41086a22092001290300370300200320032903e0013703b80102402008450d00200710190b200341e0016a41186a200341b8016a41186a2903003703002002200a29030037030020012009290300370300200320032903b8013703e0014119101b2202450d0f200241186a41002d00f8c4413a0000200241106a41002900f0c441370000200241086a41002900e8c441370000200241002900e0c441370000200241194139101a2202450d10200220032903e001370019200241316a200341f8016a290300370000200241296a200341e0016a41106a290300370000200241216a200341e0016a41086a290300370000200341e0026a41086a22014200370300200342003703e00220024139200341e0026a1001200341d0026a41086a2001290300370300200320032903e0023703d002200341d0026a4110100c2101200210192001450d0441f9c4c1002108411f21070c020b41f8c5c10021084114210720044102460d2c0c2d0b4198c5c1002108411721070b20041043200410190c2b0b20021019418cc6c10021084113210720044102460d290c2a0b200c41014b0d01200341e0016a200441d8001095031a200341013a006020034101360264200341086a200341e0016a200341e0006a105020034185026a2003280208453a0000200341f5016a200341c8016a290300370000200341fd016a200341d0016a290300370000200341083a00e001200341ed016a200341b8016a41086a290300370000200341043a00e401200320032903b8013700e501200341e0016a103d0c1f0b419fc6c1002108411021072010450d250c240b200341e0026a41086a22024200370300200342003703e00241afc5c100411c200341e0026a1001200341d0026a41086a2002290300370300200320032903e0023703d0024100210a0240200341d0026a411041d889c200410041001000417f460d00200341003602e001200341d0026a4110200341e0016a41044100100041016a41044d0d0d20032802e001210a0b200341e0026a41086a22024200370300200342003703e00241afc5c100411c200341e0026a1001200341d0026a41086a2002290300370300200320032903e0023703d00202400240200341d0026a411041d889c200410041001000417f460d00200341003602e001200341d0026a4110200341e0016a41044100100041016a41044d0d0f20032802e00141016a21020c010b410121020b200320023602e001200341e0026a41086a22024200370300200342003703e00241afc5c100411c200341e0026a1001200341d0026a41086a22012002290300370300200320032903e0023703d002200341d0026a4110200341e0016a4104100320024200370300200342003703e00241cbc5c1004118200341e0026a100120012002290300370300200320032903e0023703d0024100210102400240200341d0026a411041d889c200410041001000417f460d00200342103702642003200341d0026a360260200341e0016a200341e0006a103a20032802e0012207450d10200320032902e4012212370264200320073602602012422088a721022012a721010c010b200341003602682003420137036041012107410021020b200341e0016a41186a2209200341b8016a41186a290300370300200341e0016a41106a220b200341b8016a41106a290300370300200341e0016a41086a220d200341b8016a41086a290300370300200320032903b8013703e00120012002470d1c200241016a22012002490d1020024101742208200120012008491b2201ad4205862212422088a70d102012a722084100480d102002450d02200720024105742008101a2207450d030c1b0b2002200a460d03200b20094105746a210a0340200341c0006a2002460d0120082002200341c0006a412010970322074100476a21082007450d0141002115200a200241206a2202470d000c0f0b0b410121150c0d0b2008101b22070d180b20084101101c000b410021150c0a0b4190b4c3001029000b41154101101c000b41354101101c000b41194101101c000b41394101101c000b2010450d00200b10190b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b200c200d4105746a2106200c21024100210702400240024002400240024002400340200620026b41ff004d0d01200341c0006a2002460d0220072002200341c0006a4120109703220a4100476a2107200a450d02200241206a220a200341c0006a460d022007200a200341c0006a4120109703220a4100476a2107200a450d02200241c0006a220a200341c0006a460d022007200a200341c0006a4120109703220a4100476a2107200a450d02200241e0006a220a200341c0006a460d0220024180016a21022007200a200341c0006a4120109703220a4100476a2107200a0d000c020b0b20022006460d02200c200d4105746a21060340200341c0006a2002460d0120072002200341c0006a4120109703220a4100476a2107200a450d014100210a2006200241206a2202470d000c020b0b4101210a0b200541ff0171450d010c020b4100210a200541ff01710d010b200a0d01200341e0016a41186a2207200341c0006a41186a290300370300200341e0016a41106a220a200341c0006a41106a290300370300200341e0016a41086a2206200341c0006a41086a290300370300200320032903403703e00102402011200d470d00200d41016a2202200d490d03200d4101742211200220022011491b2211ad4205862212422088a70d032012a722024100480d0302400240200d450d00200c200d4105742002101a220c450d010c020b2002101b220c0d010b20024101101c000b200c200d4105746a220220032903e001370000200241186a2007290300370000200241106a200a290300370000200241086a2006290300370000200d41016a210d2015450d040240200920084d0d00200b2009417f6a22094105746a220229000021122002290008211320022900102114200b20084105746a220741186a200241186a2900003700002007201437001020072013370008200720123700000c050b41a8b4c30020082009104a000b20150d00200341e0016a41186a2208200341c0006a41186a290300370300200341e0016a41106a2206200341c0006a41106a290300370300200341e0016a41086a2215200341c0006a41086a290300370300200320032903403703e00120102009470d02200941016a22022009490d0120094101742210200220022010491b2210ad4205862212422088a70d012012a722024100480d01024002402009450d00200b20094105742002101a220b450d010c040b2002101b220b0d030b20024101101c000b41afc6c10021084116210720100d130c140b101d000b200b20094105746a220220032903e001370000200241186a2008290300370000200241106a2006290300370000200241086a2015290300370000200941016a2109200a450d00200d20074d0d01200c200d417f6a220d4105746a220229000021122002290008211320022900102114200c20074105746a220741186a200241186a2900003700002007201437001020072013370008200720123700000b20034185026a2003290318370000200341e0016a41156a200341c0006a41106a290300370000200341fd016a200341c0006a41186a29030037000020034195026a200341186a41106a2903003700002003419d026a200341186a41186a290300370000200341083a00e001200341ed016a200341c0006a41086a2903003700002003418d026a200341186a41086a290300370000200341013a00e401200320032903403700e501200341ac026a200d360200200341a8026a2009360200200341a5026a20053a0000200341e0016a103d200341e0026a41086a22024200370300200342003703e002419993c0004115200341e0026a1001200341d0026a41086a2002290300370300200320032903e0023703d002410021020240024002400240200341d0026a411041d889c200410041001000417f460d00200342103702642003200341d0026a360260200341e0016a200341e0006a105620032802e0012207450d0120032902e4012212422088a721022012a7450d00200710190b02402009200f4f22080d0041002002200d6b2207200720024b1b200f490d00200341fc016a200d360200200341f8016a2011360200200341f0016a2009360200200341ec016a20103602002003200c3602f4012003200b3602e8012003200f3602e4012003200e3602e0014115101b2202450d022002410d6a41002900f0c541370000200241086a41002900ebc541370000200241002900e3c541370000200241154135101a2202450d03200220032903183700152002412d6a200341306a290300370000200241256a200341286a2903003700002002411d6a200341186a41086a2903003700002003413536026420032002360260200341e0016a200341e0006a10dc01200210192010450d0b0c0a0b024002402008450d00200341f5016a200341186a41106a290300370000200341fd016a200341186a41186a290300370000200341083a00e001200341ed016a200341186a41086a290300370000200341023a00e401200320032903183700e501200341e0016a103d4119101b2202450d06200241186a41002d00f8c4413a0000200241106a41002900f0c441370000200241086a41002900e8c441370000200241002900e0c441370000200241194139101a2202450d0720022003290318370019200241316a200341306a290300370000200241296a200341186a41106a290300370000200241216a200341186a41086a290300370000200341e0026a41086a22074200370300200342003703e00220024139200341e0026a1001200341d0026a41086a2007290300370300200320032903e0023703d002200341d0026a411041d889c200410041001000417f460d01200342103702bc012003200341d0026a3602b801200341e0016a200341b8016a105520032d00e0012207410e460d08200341e0006a200341e0016a410172220841d7001095031a200341e0026a41086a220a4200370300200342003703e00220024139200341e0026a1001200341d0026a41086a200a290300370300200320032903e0023703d002200341d0026a4110100220021019200320073a00e0012008200341e0006a41d7001095031a200341013a00b8012003200f3602bc01200341106a200341e0016a200341b8016a105020034185026a2003280210453a0000200341ed016a200341186a41086a290300370000200341f5016a200341186a41106a290300370000200341fd016a200341306a290300370000200341043a00e401200341083a00e001200320032903183700e501200341e0016a103d411521074115101b22020d090c0a0b200341f5016a200341286a290300370000200341fd016a200341306a290300370000200341083a00e001200341ed016a200341186a41086a290300370000200341033a00e401200320032903183700e501200341e0016a103d411521074115101b2202450d090c080b20021019411521074115101b22020d070c080b41fcf9c00041331030000b41154101101c000b41354101101c000b41a8b4c3002007200d104a000b41194101101c000b41394101101c000b41fcf9c00041331030000b2002410d6a41002900f0c541370000200241086a41002900ebc541370000200241002900e3c54137000002400240200220074135101a2202450d00200220032903183700152002412d6a200341186a41186a290300370000200241256a200341186a41106a2903003700002002411d6a200341186a41086a290300370000200341e0026a41086a22074200370300200342003703e00220024135200341e0026a1001200341d0026a41086a22082007290300370300200320032903e0023703d002200341d0026a411010022002101920074200370300200342003703e00241cbc5c1004118200341e0026a100120082007290300370300200320032903e0023703d00202400240024002400240200341d0026a411041d889c200410041001000417f460d00200342103702642003200341d0026a360260200341e0016a200341e0006a103a20032802e0012205450d06200320032902e40122123702e401200320053602e00141002106200341003602e8012012a7210e2012422088a7220a450d024100210941002106410021070340024002402006450d00200520074105746a21022005200720096a4105746a210803402007200a4f0d07200341186a2002460d022002200341186a4120109703450d02200920076a220d200a4f0d0820082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200241206a2102200841206a2108200a200741016a2207470d000c060b0b200520074105746a210203402007200a4f0d06200341186a2002460d012002200341186a4120109703450d01200241206a2102200a200741016a2207470d000c040b0b2009417f6a2109200641016a2106200741016a2207200a470d000c030b0b4100210a200341003602e801200342013703e001410121054100210e0b410021060b200341e8016a200a20066b36020020034118360264200341cbc5c100360260200341e0016a200341e0006a1098010240200e450d00200510190b20100d050c060b41b8fdc2002007200a104a000b41c8fdc200200d200a104a000b41354101101c000b41fcf9c00041331030000b20074101101c000b200b10190b02402011450d00200c10190b4100210820044102460d0b0c0c0b20032001360264200320073602600b200720024105746a220820032903e001370000200841186a2009290300370000200841106a200b290300370000200841086a200d290300370000200341e0006a41086a200241016a360200200341183602e401200341cbc5c1003602e001200341e0006a200341e0016a10980102402001450d00200710190b200341e0006a41186a200341b8016a41186a290300370300200341e0006a41106a200341b8016a41106a290300370300200341e0006a41086a200341b8016a41086a290300370300200320032903b801370360200341e0016a200441d8001095031a4119101b2202450d01200241186a41002d00f8c4413a0000200241106a41002900f0c441370000200241086a41002900e8c441370000200241002900e0c441370000200241194139101a2202450d0220022003290360370019200241316a200341e0006a41186a2207290300370000200241296a200341e0006a41106a2208290300370000200241216a200341e0006a41086a22092903003700002003410036022020034201370318200341e0016a200341186a1064200328021c210b2003280220210d20032802182101200341e0026a41086a22064200370300200342003703e00220024139200341e0026a1001200341d0026a41086a2006290300370300200320032903e0023703d002200341d0026a41102001200d10030240200b450d00200110190b20021019200341e0016a10432007200341b8016a41186a2903003703002008200341b8016a41106a2903003703002009200341b8016a41086a290300370300200320032903b8013703604120101b2202450d03200341fc016a4100360200200341ec016a428180808010370200200341c0006a41086a2903002112200341c0006a41106a290300211320032903402114200241186a200341c0006a41186a290300370000200241106a2013370000200241086a201237000020022014370000200342013702f401200320023602e8012003200c3602e4012003200a3602e0014115101b2201450d042001410d6a41002900f0c541370000200141086a41002900ebc541370000200141002900e3c541370000200141154135101a2201450d05200120032903603700152001412d6a200341e0006a41186a290300370000200141256a200341e0006a41106a2903003700002001411d6a200341e0006a41086a290300370000200320013602182003413536021c200341e0016a200341186a10dc012001101920021019200341e0016a410d6a200341c0006a41086a290300370000200341f5016a200341c0006a41106a290300370000200341e0016a411d6a200341c0006a41186a290300370000200341e0016a41256a20032903b801370000200341e0016a412d6a200341b8016a41086a290300370000200341e0016a41356a200341b8016a41106a2903003700002003419d026a200341b8016a41186a290300370000200341003a00e401200341083a00e001200320032903403700e501200341ac026a200c360200200341a8026a200a360200200341e0016a103d0b20041019410021080c090b41194101101c000b41394101101c000b41204101101c000b41154101101c000b41354101101c000b200b10190b2011450d00200c101920044102470d020c010b20044102470d010b200141086a28020022021043200210190b2000200736020420002008360200200341f0026a24000b130020004102360204200041fcd6c3003602000b130020004100360204200041d889c2003602000b1300200041013602042000419c95c3003602000b130020004103360204200041b4fec2003602000b130020004101360204200041f0fdc2003602000b1300200041033602042000418ccbc2003602000b1300200041073602042000418092c3003602000b130020004104360204200041a0b2c2003602000b13002000410236020420004190e4c2003602000b130020004105360204200041ecabc3003602000b130020004101360204200041b8c1c3003602000b130020004105360204200041f4eec2003602000b130020004105360204200041e4c3c3003602000b130020004102360204200041ecedc2003602000b130020004104360204200041fdccc1003602000b130020004103360204200041f8bec3003602000b130020004101360204200041b4bec3003602000b3901017f02404110101b2202450d002002420037000820024200370000200042908080808002370204200020023602000f0b41104101101c000bf40606047f017e017f017e017f057e230041106b22022400200241003602082001410020012802002001280204200241086a41042001280208100022032003417f461b22034104200341044922031b20012802086a22043602080240024020030d00200228020821054200210620024200370308200141086a220741002001280200200141046a280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d01200229030821084200210620024200370308200741002001280200200141046a2209280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d012002290308210a4200210620024200370308200141086a2207410020012802002009280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d012002290308210b4200210620024200370308200741002001280200200141046a2209280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d012002290308210c4200210620024200370308200141086a2207410020012802002009280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d012002290308210d4200210620024200370308200741002001280200200141046a2209280200200241086a41082004100022032003417f461b2203410820034108491b20072802006a2204360200200341074d0d012002290308210e2009280200210720024100360208200141086a2203410020012802002007200241086a41042004100022042004417f461b22044104200441044922041b20032802006a220736020020040d0120022802082109200141046a2802002104200241003602082003410020012802002004200241086a41042007100022012001417f461b2201410420014104491b20032802006a360200200141034d0d01200041c0006a20022802083602002000413c6a2009360200200041386a2005360200200041306a200e370300200041286a200d370300200041206a200c370300200041186a200b370300200041106a200a37030020002008370308420121060c010b420021060b20002006370300200241106a24000bec0301097f230041c0006b220324000240200128020022044100480d00200441ffffffff07460d002001200441016a2205360200200141046a2104200141086a280200210602400240024003402004280200220841086a210920082f0106220741057421044100210a0240024003402004450d01200220094120109703220b450d02200441606a2104200a41016a210a200941206a2109200b417f4a0d000b200a417f6a21070b2006450d022006417f6a2106200820074102746a4180096a21040c010b0b2008200a41c8006c6a41e8026a2204450d0020042d002422094102470d010b200020012802102002200141146a280200280210110200200128020021050c010b4100210a024020094101470d00200341386a2004413d6a290000370300200341306a200441356a290000370300200341286a2004412d6a2900003703002003200441256a2900003703204101210a0b200341186a2204200341206a41186a290300370300200341106a2209200341206a41106a290300370300200341086a220b200341206a41086a290300370300200320032903203703002000200a3a000020002003290300370001200041096a200b290300370000200041116a2009290300370000200041196a20042903003700000b20012005417f6a360200200341c0006a24000f0b107b000b940d030b7f067e0a7f23004180016b22082400024002400240024002400240200728020022094100480d00200941ffffffff07460d002007200941016a220a360200200741086a280200210b200741046a220c210d410021090340024002400240024002400240024020090e020001010b200d280200220f41086a2110200f2f0106220e410574210941002111024002400240024003402009450d012004201041201097032212450d02200941606a2109201141016a2111201041206a21102012417f4a0d000b2011417f6a210e0b200b450d01200b417f6a210b200f200e4102746a4180096a210d410021090c090b200f41e8026a201141c8006c6a2209450d002009280200450d00200941106a2903002113200941086a29030021140c010b200841286a20072802102004200741146a280200280214110200200841306a29030021132007280200210a200829032821140b2007200a417f6a360200200141186a29030021152007280234210920012903102116024041004101410220142013842217501b20021b22104101460d0020104102470d02200941f0006a21094200211820162015844200520d030c0d0b200941e0006a21094200211820162015844200510d0c0c020b200c280200220f201b6a2110200f2f0106220c201d742109410021110240024003402009450d012003201020211097032212450d02200920226a2109201120196a2111201020216a21102012201e4a0d000b2011201e6a210c0b201c450d03201c201e6a211c200f200c201f746a20206a210c410121090c060b200f41e8026a201141c8006c6a2209450d022009280200450d02200941106a2903002115200941086a29030021160c030b200941d0006a21094200211820162015844200510d0a0b200841186a2009290300200941086a29030020162015109803200120182001290308221620082903187d221520152016562015507222091b37030802402009450d0041bdcec1002109412221100c090b200728020022094100480d04200941ffffffff07460d04410121192007200941016a221a3602004108211b200741086a280200211c4105211d417f211e4102211f418009212041202121416021220c020b200841086a20072802102003200741146a280200280214110200200841106a29030021152007280200211a200829030821160b2007201a417f6a3602000240201620057d2218201656201520067d2016200554ad7d221620155620162015511b4101470d0041dfcec1002109411d21100c070b024020174200520d00200741346a2802002209290340200556200941c8006a290300221520065620152006511b450d0041fccec1002109411f21100c070b411e2110200310a60122090d060240201420057c22172014542209201320067c2009ad7c221520135420152013511b450d00419bcfc1002109412d21100c070b4100210920032004460d05200320044120109703450d05200720032018201610ce02200720042017201510ce02200841e0006a41186a200341186a290000370300200841e0006a41106a200341106a290000370300200841e0006a41086a200341086a290000370300200841c0006a41086a200441086a290000370300200841c0006a41106a200441106a290000370300200841c0006a41186a200441186a29000037030020082003290000370360200820042900003703400240024002400240200741246a2802002209200741206a280200470d00200941016a22102009490d0320094101742211201020102011491b2211ad42d8007e2215422088a70d032015a722214100480d032009450d012007411c6a280200200941d8006c2021101a2210450d020c070b2007411c6a28020021100c070b2021101b22100d050b20214108101c000b101d000b410121090c000b0b107b000b200741206a20113602002007411c6a2010360200200741246a28020021090b2010200941d8006c6a2210200829036037000141002109201041003a00002010200829034037002120102008280039360041201041096a200841e0006a41086a290300370000201041116a200841e0006a41106a290300370000201041196a200841e0006a41186a290300370000201041296a200841c0006a41086a290300370000201041316a200841c0006a41106a290300370000201041396a200841c0006a41186a290300370000201041c4006a2008413c6a280000360000201041d0006a200637030020102005370348200741246a2210201028020041016a3602000b0b200020103602042000200936020020084180016a24000f0b41d8fdc2001029000bfc0f010c7f230041f0006b220324000240024002400240024002400240024002400240024002400240024002404114101b2204450d00200441106a41002800fce341360000200441086a41002900f4e341370000200441002900ece341370000200441144134101a2204450d01200420012900003700142004412c6a200141186a290000370000200441246a200141106a2900003700002004411c6a200141086a290000370000200341d8006a41086a220542003703002003420037035820044134200341d8006a1001200341306a41086a2005290300370300200320032903583703300240024002400240200341306a411041d889c200410041001000417f460d002003421037025c2003200341306a360258200341206a200341d8006a10682003280220450d0320032802242106200341186a200341d8006a10682003280218450d03200328021c2107200341106a200341d8006a10682003280210450d032003280214210841002109200341003a006c200341e0006a2205200528020022052003280258200328025c200341ec006a41012005100041016a41014b22056a3602002005450d03024020032d006c2205450d004101210920054101470d040b200341086a200341d8006a10682003280208450d03200328020c2205417f4c0d092005450d01200510df01220a450d06200341e0006a220b200b280200220b200541002003280258200328025c200a2005200b1000220b200b417f461b220b200b20054b1b220b6a360200200b2005470d020c070b20041019410121044180e4c100210641112107410221090c070b4101210a2003280258200328025c41014100200341e0006a28020010001a41002005460d050b2005450d00200a10190b41fcf9c00041331030000b41144101101c000b41344101101c000b20054101101c000b200341d4006a41026a220c200341ec006a41026a220b2d00003a0000200320032f006c3b0154200b200c2d00003a0000200320032f01543b016c20041019200341306a41026a200b2d00003a0000200320032f016c3b0130410021040b2003412c6a41026a220b200341306a41026a2d00003a0000200320032f01303b012c02402004450d002000200636020420004101360200200041086a2007360200200341f0006a24000f0b200341286a41026a200b2d00003a0000200320032f012c3b01280240024002400240200228023020064d0d004115101b2204450d05410021062004410d6a410029009ee441370000200441086a4100290099e44137000020044100290091e441370000200441154135101a2204450d06200420012900003700152004412d6a200141186a290000370000200441256a200141106a2900003700002004411d6a200141086a290000370000200341d8006a41086a220742003703002003420037035820044135200341d8006a1001200341306a41086a200729030037030020032003290358370330200341306a411041d889c200410041001000417f460d012003421037025c2003200341306a3602582003200341d8006a10682003280200450d0820032802042207417f4c0d042007450d02200710df012206450d09200341e0006a220b200b280200220b200741002003280258200328025c20062007200b1000220b200b417f461b220b200b20074b1b220b6a360200200b2007460d030c070b2005210420052102200a210b0c0c0b0c010b410121062003280258200328025c41014100200341e0006a28020010001a41002007470d040b200410192007411a20061b210d200641a6e4c10020061b210c024002400240024002402006450d00200341306a200c2007200210d002200341306a41086a28020021072003280234210620032802304101470d042000200636020420004101360200200041086a2007360200200d450d01200c101920050d020c030b2000200c36020420004101360200200041086a200d3602000b2005450d010b200a10190b200341f0006a24000f0b200341d8006a41026a220e200341cf006a2d00003a0000200320032f004d3b0158200341cc006a2d00002109200341c8006a2802002104200341c4006a2802002102200341c0006a280200210b2003413c6a280200210802402005450d00200a10190b200341286a41026a200e2d00003a0000200320032f01583b01282004417f4c0d004101210502402004450d002004101b2205450d090b2005200b2004109503210a200341306a41146a2004360200200341306a41106a20043602002003200836023820032007360234200320063602302003200a36023c2003200941ff01714101463a00484114101b2205450d06200541106a41002800fce341360000200541086a41002900f4e341370000200541002900ece341370000200541144134101a2205450d07200520012900003700142005412c6a200141186a290000370000200541246a200141106a2900003700002005411c6a200141086a2900003700002003413436025c20032005360258200341306a200341d8006a10df022005101902402004450d00200a10190b200d450d09200c10190c090b102b000b41154101101c000b41354101101c000b2007450d00200610190b41fcf9c00041331030000b20074101101c000b41144101101c000b41344101101c000b20044101101c000b20002006360204200020032f01283b001d200041003602002000411c6a20093a0000200041186a2004360200200041146a2002360200200041106a200b3602002000410c6a2008360200200041086a20073602002000411f6a2003412a6a2d00003a0000200341f0006a24000bc13d01087f230041a0016b220824000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002410c6a280200200241106a280200100f2209417f460d00410c101b220a450d01200a2009360208200a42818080801037020002404101450d00200a410141016a3602004101417e460d00200a41014102723602004104101b220b450d03200b200a360200200a280208210c4103101b220d450d04200d41026a41002d00baf6413a0000200d41002f00b8f6413b00004106101b220e450d05200e41046a41002f00f9d8413b0000200e41002800f5d8413600004120101b2209450d062009200c36021c2009410136021820094286808080e0003702102009200e36020c20094283808080303702042009200d360200200a200a280200417f6a220d3602000240200d0d00200a41086a280200100b200a200a280204417f6a220d360204200d0d00200a10190b4103101b220d450d07200d41026a41002d00baf6413a0000200d41002f00b8f6413b00004103101b220e450d08200e41026a41002d00bdf6413a0000200e41002f00bbf6413b00002009412041c000101a2209450d092009410d36023c2009410036023820094283808080303702302009200e36022c20094283808080303702242009200d3602204103101b220d450d0a200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410f101b220e450d0b200e41076a4100290088f441370000200e4100290081f441370000200941c000418001101a2209450d0c2009410e36025c200941003602582009428f808080f0013702502009200e36024c20094283808080303702442009200d3602404103101b220d450d0d200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410f101b220e450d0e200e41076a4100290097f441370000200e4100290090f4413700002009410f36027c200941003602782009428f808080f0013702702009200e36026c20094283808080303702642009200d3602604103101b220d450d0f200d41026a41002d00baf6413a0000200d41002f00b8f6413b00004108101b220e450d10200e42e5f0d1fbb5ac98b6ec003700002009418001418002101a2209450d112009411036029c012009410036029801200942888080808001370290012009200e36028c012009428380808030370284012009200d360280014103101b220d450d12200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410a101b220e450d13200e41086a41002f00aff4413b0000200e41002900a7f441370000200941113602bc01200941003602b8012009428a808080a0013702b0012009200e3602ac0120094283808080303702a4012009200d3602a0014103101b220d450d14200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410a101b220e450d15200e41086a41002f00b9f4413b0000200e41002900b1f441370000200941123602dc01200941003602d8012009428a808080a0013702d0012009200e3602cc0120094283808080303702c4012009200d3602c0014103101b220d450d16200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410a101b220e450d17200e41086a41002f00c3f4413b0000200e41002900bbf441370000200941133602fc01200941003602f8012009428a808080a0013702f0012009200e3602ec0120094283808080303702e4012009200d3602e0014103101b220d450d18200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410b101b220e450d19200e41076a41002800ccf441360000200e41002900c5f4413700002009418002418004101a2209450d1a2009411436029c0220094100360298022009428b808080b001370290022009200e36028c022009428380808030370284022009200d360280024103101b220d450d1b200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410d101b220e450d1c200e41056a41002900d5f441370000200e41002900d0f441370000200941153602bc02200941003602b8022009428d808080d0013702b0022009200e3602ac0220094283808080303702a4022009200d3602a0024103101b220d450d1d200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410c101b220e450d1e200e41086a41002800e5f441360000200e41002900ddf441370000200941163602dc02200941003602d8022009428c808080c0013702d0022009200e3602cc0220094283808080303702c4022009200d3602c0024103101b220d450d1f200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410b101b220e450d20200e41076a41002800f0f441360000200e41002900e9f441370000200941173602fc02200941003602f8022009428b808080b0013702f0022009200e3602ec0220094283808080303702e4022009200d3602e0024103101b220e450d21200e41026a41002d00baf6413a0000200e41002f00b8f6413b00004115101b220d450d22200d410d6a4100290081f541370000200d41086a41002900fcf441370000200d41002900f4f4413700002009411836029c03200941003602980320094295808080d002370290032009200d36028c032009428380808030370284032009200e360280034103101b220d450d23200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410f101b220e450d24200e41076a4100290090f541370000200e4100290089f541370000200941193602bc03200941003602b8032009428f808080f0013702b0032009200e3602ac0320094283808080303702a4032009200d3602a0034103101b220d450d25200d41026a41002d00baf6413a0000200d41002f00b8f6413b00004107101b220e450d26200e41036a410028009bf541360000200e4100280098f5413600002009411a3602dc03200941003602d80320094287808080f0003702d0032009200e3602cc0320094283808080303702c4032009200d3602c0034103101b220e450d27200e41026a41002d00baf6413a0000200e41002f00b8f6413b00004111101b220d450d28200d41106a41002d00aff5413a0000200d41086a41002900a7f541370000200d410029009ff5413700002009411b3602fc03200941003602f8032009429180808090023702f0032009200d3602ec0320094283808080303702e4032009200e3602e0034103101b220d450d29200d41026a41002d00baf6413a0000200d41002f00b8f6413b0000410e101b220e450d2a200e41066a41002900b6f541370000200e41002900b0f5413700002009418004418008101a220c450d2b200c411c36029c04200c410036029804200c428e808080e00137029004200c200e36028c04200c42838080803037028404200c200d360280044103101b2209450d2c200941026a41002d00baf6413a0000200941002f00b8f6413b0000410e101b220d450d2d200d41066a41002900c4f541370000200d41002900bef541370000200c411d3602bc04200c41003602b804200c428e808080e0013702b004200c200d3602ac04200c4283808080303702a404200c20093602a0044103101b2209450d2e200941026a41002d00baf6413a0000200941002f00b8f6413b00004110101b220d450d2f200d41086a41002900d4f541370000200d41002900ccf541370000200c411e3602dc04200c41003602d804200c429080808080023702d004200c200d3602cc04200c4283808080303702c404200c20093602c0044103101b2209450d30200941026a41002d00baf6413a0000200941002f00b8f6413b00004110101b220d450d31200d41086a41002900e4f541370000200d41002900dcf541370000200c411f3602fc04200c41003602f804200c429080808080023702f004200c200d3602ec04200c4283808080303702e404200c20093602e004200841086a41086a2005360200200841086a41206a4100360200200841086a41146a200641086a2802003602002008200436020c2008200336020820084100360238200820073602342008200a36023020084201370320200820062902003702142008200128020036022c200241146a28020021072002411c6a280200210f200841003602602008420137035820084114360248200841c8006a200841d8006a105d4100210402400240024002400240024002400340200c20046a220d28020021012008200d41086a2802002209360248200841c8006a200841d8006a105d0240024002400240200828025c2206200841d8006a41086a220e280200220a6b20094f0d00200a20096a2203200a490d0520064101742205200320032005491b22034100480d052006450d01200828025820062003101a22060d020c060b200828025821060c020b2003101b2206450d040b2008200336025c200820063602580b200e200a20096a3602002006200a6a200120091095031a200d410c6a28020021052008200d41146a2802002201360248200841c8006a200841d8006a105d0240024002400240200828025c220a200e28020022036b20014f0d00200320016a22092003490d05200a4101742206200920092006491b22064100480d05200a450d012008280258200a2006101a22090d020c070b200828025821090c020b2006101b2209450d050b2008200636025c200820093602582006210a0b200e200320016a2206360200200920036a200520011095031a0240024002400240024002400240024002400240024002400240024002400240200d41186a2802004101470d00200a2006470d01200a41016a2201200a490d11200a4101742203200120012003491b22014100480d11200a450d032009200a2001101a22090d040c140b200a2006470d01200a41016a2201200a490d10200a4101742203200120012003491b22014100480d10200a450d052009200a2001101a22090d060c140b200a21010c030b200a21010c050b2001101b2209450d100b2008200136025c200820093602580b200e200641016a220a360200200920066a41023a0000200d411c6a280200210d2001200a6b41034b0d05200a41046a2203200a490d0b20014101742205200320032005491b22034100480d0b2001450d03200920012003101a22090d040c100b2001101b2209450d0e0b2008200136025c200820093602580b200e200641016a220a360200200920066a41013a0000200d411c6a280200210d2001200a6b41034b0d05200a41046a2203200a490d0820014101742205200320032005491b22034100480d082001450d03200920012003101a22090d040c0e0b2003101b2209450d0c0b2008200336025c200820093602580b200e200641056a3602002009200a6a200d360000200441206a2204418005470d040c030b2003101b2209450d0a0b2008200336025c200820093602580b200e200641056a3602002009200a6a200d360000200441206a2204418005470d010b0b200828025c21090240024041202007200f20082802582206200841e0006a280200200841086a1010220a417f460d00200a417d470d014102210d2009450d3f0c3e0b4100210d20090d3d0c3e0b4104101b220e450d39200b280200220d28020041016a220141014d0d07200d2001360200200e200d36020002402009450d00200610190b200841d0006a4281808080103703002008200e36024c2008200a36024820022802002106200228020421012008410036026020084201370358200841003602980120084198016a200841d8006a105d20082802602103200828025c21042008280258210d410a10df012209450d3a41012105024002400240200a20062001200d20032009410a200841086a10112206417d460d0020060d3e2008410936029c012008200941016a36029801024020092d00002206450d00024020064101470d00200841d8006a20084198016a102e2008280258417e714104470d010b200910192004450d02200d10190c020b410021050b2009101902402004450d00200d10190b410321092005450d010b410221090b200841d8006a41386a200841086a41386a280200360200200841d8006a41306a200841086a41306a290300370300200841d8006a41286a200841086a41286a290300370300200841d8006a41206a200841086a41206a290300370300200841d8006a41186a200841086a41186a290300370300200841d8006a41106a200841086a41106a290300370300200841d8006a41086a200841086a41086a290300370300200820082903083703582000200841d8006a2009109201200a1012200e28020022092009280200417f6a3602000240200e28020022092802000d002009280208100b200e28020022092009280204417f6a360204200e28020022092802040d00200910190b200e10194101210d41002106200c41046a2802000d3e0c3f0b101d000b20034101101c000b20064101101c000b20014101101c000b20014101101c000b20034101101c000b20034101101c000b00000b10de02000b410c4104101c000b41044104101c000b41034101101c000b41064101101c000b41204104101c000b41034101101c000b41034101101c000b41c0004104101c000b41034101101c000b410f4101101c000b4180014104101c000b41034101101c000b410f4101101c000b41034101101c000b41084101101c000b4180024104101c000b41034101101c000b410a4101101c000b41034101101c000b410a4101101c000b41034101101c000b410a4101101c000b41034101101c000b410b4101101c000b4180044104101c000b41034101101c000b410d4101101c000b41034101101c000b410c4101101c000b41034101101c000b410b4101101c000b41034101101c000b41154101101c000b41034101101c000b410f4101101c000b41034101101c000b41074101101c000b41034101101c000b41114101101c000b41034101101c000b410e4101101c000b4180084104101c000b41034101101c000b410e4101101c000b41034101101c000b41104101101c000b41034101101c000b41104101101c000b41044104101c000b410a4101101c000b41c0b1c2001029000b200610190b200d450d02200841d8006a41386a200841086a41386a280200360200200841d8006a41306a200841086a41306a290300370300200841d8006a41286a200841086a41286a290300370300200841d8006a41206a200841086a41206a290300370300200841d8006a41186a200841086a41186a290300370300200841d8006a41106a200841086a41106a290300370300200841d8006a41086a200841086a41086a290300370300200820082903083703582000200841d8006a200d1092014100210d41012106200c41046a280200450d010b200c28020010190b0240200c41106a280200450d00200c28020c10190b0240200c41246a280200450d00200c41206a28020010190b0240200c41306a280200450d00200c28022c10190b0240200c41c4006a280200450d00200c41c0006a28020010190b0240200c41d0006a280200450d00200c28024c10190b0240200c41e4006a280200450d00200c41e0006a28020010190b0240200c41f0006a280200450d00200c28026c10190b0240200c4184016a280200450d00200c4180016a28020010190b0240200c4190016a280200450d00200c28028c0110190b0240200c41a4016a280200450d00200c41a0016a28020010190b0240200c41b0016a280200450d00200c2802ac0110190b0240200c41c4016a280200450d00200c41c0016a28020010190b0240200c41d0016a280200450d00200c2802cc0110190b0240200c41e4016a280200450d00200c41e0016a28020010190b0240200c41f0016a280200450d00200c2802ec0110190b0240200c4184026a280200450d00200c4180026a28020010190b0240200c4190026a280200450d00200c28028c0210190b0240200c41a4026a280200450d00200c41a0026a28020010190b0240200c41b0026a280200450d00200c2802ac0210190b0240200c41c4026a280200450d00200c41c0026a28020010190b0240200c41d0026a280200450d00200c2802cc0210190b0240200c41e4026a280200450d00200c41e0026a28020010190b0240200c41f0026a280200450d00200c2802ec0210190b0240200c4184036a280200450d00200c4180036a28020010190b0240200c4190036a280200450d00200c28028c0310190b0240200c41a4036a280200450d00200c41a0036a28020010190b0240200c41b0036a280200450d00200c2802ac0310190b0240200c41c4036a280200450d00200c41c0036a28020010190b0240200c41d0036a280200450d00200c2802cc0310190b0240200c41e4036a280200450d00200c41e0036a28020010190b0240200c41f0036a280200450d00200c2802ec0310190b0240200c4184046a280200450d00200c4180046a28020010190b0240200c4190046a280200450d00200c28028c0410190b0240200c41a4046a280200450d00200c41a0046a28020010190b0240200c41b0046a280200450d00200c2802ac0410190b0240200c41c4046a280200450d00200c41c0046a28020010190b0240200c41d0046a280200450d00200c2802cc0410190b0240200c41e4046a280200450d00200c41e0046a28020010190b0240200c41f0046a280200450d00200c2802ec0410190b200c1019200b28020022092009280200417f6a3602000240200b28020022092802000d002009280208100b200b28020022092009280204417f6a360204200b28020022092802040d00200910190b200b10194100210902402006410047200d720d00200a101202400340200e20096a220a280200220d200d280200417f6a36020002400240200a280200220d2802000d00200d280208100b200a280200220d200d280204417f6a360204200a280200220a280204450d010b200941046a22094104470d010c020b200a1019200941046a22094104470d000b0b200e10190b200841a0016a24000f0b200041fbd8c10036020420004102360200200041086a41103602000240200841146a2802002209450d00200841086a41106a280200450d00200910190b0240200841246a280200450d00200841206a28020010190b200841306a2209280200220a200a280200417f6a36020002402009280200220a2802000d00200a280208100b2009280200220a200a280204417f6a360204200928020022092802040d00200910190b0240200841386a2802002209450d002008413c6a280200450d00200910190b0240200c41046a280200450d00200c28020010190b0240200c41106a280200450d00200c28020c10190b0240200c41246a280200450d00200c41206a28020010190b0240200c41306a280200450d00200c28022c10190b0240200c41c4006a280200450d00200c41c0006a28020010190b0240200c41d0006a280200450d00200c28024c10190b0240200c41e4006a280200450d00200c41e0006a28020010190b0240200c41f0006a280200450d00200c28026c10190b0240200c4184016a280200450d00200c4180016a28020010190b0240200c4190016a280200450d00200c28028c0110190b0240200c41a4016a280200450d00200c41a0016a28020010190b0240200c41b0016a280200450d00200c2802ac0110190b0240200c41c4016a280200450d00200c41c0016a28020010190b0240200c41d0016a280200450d00200c2802cc0110190b0240200c41e4016a280200450d00200c41e0016a28020010190b0240200c41f0016a280200450d00200c2802ec0110190b0240200c4184026a280200450d00200c4180026a28020010190b0240200c4190026a280200450d00200c28028c0210190b0240200c41a4026a280200450d00200c41a0026a28020010190b0240200c41b0026a280200450d00200c2802ac0210190b0240200c41c4026a280200450d00200c41c0026a28020010190b0240200c41d0026a280200450d00200c2802cc0210190b0240200c41e4026a280200450d00200c41e0026a28020010190b0240200c41f0026a280200450d00200c2802ec0210190b0240200c4184036a280200450d00200c4180036a28020010190b0240200c4190036a280200450d00200c28028c0310190b0240200c41a4036a280200450d00200c41a0036a28020010190b0240200c41b0036a280200450d00200c2802ac0310190b0240200c41c4036a280200450d00200c41c0036a28020010190b0240200c41d0036a280200450d00200c2802cc0310190b0240200c41e4036a280200450d00200c41e0036a28020010190b0240200c41f0036a280200450d00200c2802ec0310190b0240200c4184046a280200450d00200c4180046a28020010190b0240200c4190046a280200450d00200c28028c0410190b0240200c41a4046a280200450d00200c41a0046a28020010190b0240200c41b0046a280200450d00200c2802ac0410190b0240200c41c4046a280200450d00200c41c0046a28020010190b0240200c41d0046a280200450d00200c2802cc0410190b0240200c41e4046a280200450d00200c41e0046a28020010190b0240200c41f0046a280200450d00200c2802ec0410190b200c1019200b28020022092009280200417f6a3602000240200b28020022092802000d002009280208100b200b28020022092009280204417f6a360204200b28020022092802040d00200910190b200b1019200841a0016a24000bda0e05057f017e157f027e0a7f230041900b6b22022400024020002802000d002000417f36020020012802082103200128020021040240024020012802042205450d002005210620042101034020012802800921012006417f6a22060d000b0340200420042f01064102746a4180096a28020021042005417f6a22050d000c020b0b200421010b200241086a411c6a20042f0106360200200241086a41186a4100360200200241086a41146a20043602002002200336022820024100360218200242003703102002200136020c2002410036020820024198026a200241086a10ae02024020022903b80222074202510d002000410c6a2108200041046a2109200241c0016a41146a210a200241a0016a410c6a210b20024198026a41256a210c200241dd026a210d200241c8026a210e200241c0026a210f200241dc026a2110200241d0026a2111200241d4026a2112200241d8026a2113200241bc026a211420024198026a41206a211520024198026a411c6a21160340200241d8006a41086a220420024198026a41086a2217290300370300200241d8006a41106a220120024198026a41106a2218290300370300200241d8006a41186a220620024198026a41186a2219290300370300200241306a41086a2203200d41086a290000370300200241306a41106a221a200d41106a290000370300200241306a41186a221b200d41186a290000370300200241306a411f6a221c200d411f6a28000036000020022002290398023703582002200d290000370330200e290300211d200f290300211e20102d0000211f201128020021052012280200212020132802002121200241f8006a411f6a2222201c280000360000200241f8006a41186a2223201b290300370300200241f8006a41106a2224201a290300370300200241f8006a41086a2225200329030037030020022002290330370378200241c0016a41186a22262006290300370300200241c0016a41106a221c2001290300370300200241c0016a41086a221a2004290300370300200220022903583703c001024002400240024002400240024002402009280200220341a0c0c100460d00200041086a28020021270c010b418009101b2203450d0141002127200341003b010620034100360200200341086a20024198026a41f8081095031a200041086a4100360200200920033602000b0240034020032f01062228410574211b410021044100210102400340201b2004460d01200241c0016a200320046a41086a41201097032206450d03200441206a2104200141016a21012006417f4a0d000b2001417f6a21280b02402027450d002027417f6a2127200320284102746a4180096a28020021030c010b0b200241a0016a41186a22042026290300370300200241a0016a41106a2201201c290300370300200241a0016a41086a2206201a290300370300200220022903c0013703a001201c2008360200200241c0016a410c6a2028360200201a2009360200200a20022903a001370200200a41086a2006290300370200200a41106a2001290300370200200a41186a2004290300370200200220033602c401200241003602c0012018201d3703002017201e3703002014201f3a0000201520213602002016202036020020192005360200200c2002290378370000200c41086a2025290300370000200c41106a2024290300370000200c41186a2023290300370000200c411f6a20222800003600002002200737039802200241c0016a20024198026a1086011a0c060b200341e8026a200141c8006c6a21060240024020074201510d00201f41ff01714102470d010c030b200642013703002006201e370308200641106a201d370300201f41ff01714102460d020b2006201f3a00242006413d6a2023290300370000200641356a20242903003700002006412d6a2025290300370000200641256a200229037837000020200d020c030b4180094108101c000b2020450d010b2020210120052104034020042802900221042001417f6a22010d000b0340200520052f01064102746a4190026a28020021052020417f6a22200d000c020b0b200521040b20052f0106210120152021360200201620013602002019410036020020024198026a41146a200536020020184100360200201742003703002002200436029c022002410036029802200241c0016a20024198026a10ac02024020022802c001450d00200641186a21010340200241a0016a41106a201c290300370300200241a0016a41086a2204201a290300370300200220022903c0013703a00120024188026a41086a2004280200360200200220022903a00137038802201a200b41086a2802003602002002200b2902003703c001200241f8016a200120024188026a200241c0016a108701024020022802f801450d0020022802fc012204450d00200241f8016a41086a280200450d00200410190b200241c0016a20024198026a10ac0220022802c0010d000b0b20024198026a1084010b20024198026a200241086a10ae02201529030022074202520d000b0b200241086a10ad022000200028020041016a360200200241900b6a24000f0b108501000b840701087f230041900a6b22042400024002400240024020002802000d002000417f360200200441e0006a41186a200141186a290000370300200441e0006a41106a200141106a290000370300200441e0006a41086a200141086a29000037030020042001290000370360024002402000280204220541a0c0c100460d00200041086a28020021060c010b418009101b2205450d0241002106200541003b010620054100360200200541086a20044198016a41f8081095031a200041086a4100360200200041046a20053602000b200041046a210702400240034020052f010622084105742109410021014100210a0240034020092001460d01200441e0006a200520016a41086a4120109703220b450d03200141206a2101200a41016a210a200b417f4a0d000b200a417f6a21080b02402006450d002006417f6a2106200520084102746a4180096a28020021050c010b0b200441086a41186a200441e0006a41186a290300370300200441086a41106a200441e0006a41106a290300370300200441086a41086a200441e0006a41086a290300370300200420042903603703082000410c6a2101410021062008210a41000d010c040b2000410c6a21014101450d030b200441b0016a4200370300200441ac016a41a0c0c100360200200441003602b801200441003602a801200442003703a001200441a0c0c10036029c0120044100360298012005200a41c8006c6a41e8026a210120044198016a1084010c030b108501000b4180094108101c000b200441e0006a411c6a200441086a41086a29030037020020044184016a200441086a41106a2903003702002004418c016a200441086a41186a290300370200200420013602702004200a36026c2004200736026820042005360264200420063602602004200429030837027420044198016a411c6a420037020020044198016a41106a200441d0006a41086a290300370300200441bd016a200429002d370000200441c5016a2004412d6a41086a290000370000200441cd016a2004412d6a41106a290000370000200441d5016a2004412d6a41186a290000370000200441dc016a200441cc006a2800003600002004420037039801200441023a00bc01200441a0c0c1003602b001200420042903503703a001200441e0006a20044198016a10860121010b200141106a200337030020012002370308200142013703002000200028020041016a360200200441900a6a24000bc60101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a2802002204450d002004210520032100034020002802800921002005417f6a22050d000b0340200320032f01064102746a4180096a28020021032004417f6a22040d000c020b0b200321000b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a10ad02200141306a24000bf77509227f047e4f7f017e387f017e057f027e0f7f230041c0046b220424004100210520044100360290022004200236028c022004200136028802024002400240024002400240200241044f0d00200441013a0048200441c4036a4101360200200441013602f401200442013702b403200441c4d6c3003602b0032004200441c8006a3602f0012004200441f0016a3602c003200441e0006a200441b0036a1024200428026821022004280264210620042802602107410521080c010b20044190026a4104360200024002400240024020012800004180c2cdeb06470d002002417c714104470d01200441013a0048200441c4036a4101360200200441013602f401200442013702b403200441c4d6c3003602b0032004200441c8006a3602f0012004200441f0016a3602c003200441e0006a200441b0036a102420042802682102200428026421062004280260210741052108410021050c040b410121080c010b02400240024002400240024002400240024002400240024002400240200241074d0d0020044188026a41086a41083602000240024002400240200128000422074101470d00200441b0036a20044188026a10d10220042802b0034101470d014104210a4100210b4100210c20042d00b4030d020c050b410221080c120b200441b0036a410572210f4104210a200441b0036a412c6a2110200441d4036a2111200441d0036a2112200441cc036a2113200441c8036a2114200441c4036a2115200441c0036a2116200441bc036a2117200441b8036a211841002107412821054100210b4100210c410021090340200441f0016a41026a2219200f41026a2d00003a00002004200f2f00003b01f0012010280200211a200441d8036a280200211b2011280200211c2012280200211d2013280200211e2014280200211f20152802002120201628020021212017280200212220182802002106024020042d00b4032223417e6a220141ff0171410b4f0d0002400240024002400240024002400240024002400240024002400240024002402001410a4b22240d00024020010e0b00070405020809060b030a000b200941ff0171222541014d0d0c0c0b0b200941ff0171222541004b0d0a0c0b0b200941ff0171222541054d0d0a0c090b200941ff01712225410a4d0d090c080b200941ff0171222541034d0d080c070b200941ff0171222541044d0d070c060b200941ff0171222541084d0d060c050b200941ff0171222541024d0d050c040b200941ff0171222541064d0d040c030b200941ff0171222541074d0d030c020b200941ff01712225410b4d0d020c010b200941ff0171222541094d0d010b411321082023410d4b0d010c020b02400240024002400240024002400240024002400240024020240d00024020010e0b00070405020809060b030a000b20254101470d0e0c0b0b20254100460d0a0c0d0b20254105470d0c0c090b2025410a470d0b0c080b20254103470d0a0c070b20254104470d090c060b20254108470d080c050b20254102470d070c040b20254106470d060c030b20254107470d050c020b2025410b470d040c010b20254109470d030b411421082023410d4d0d010b02402022450d00200610190b0240201f450d00201e450d00201f10190b201b450d10201c1019200b0d110c120b0240024002400240024002400240024002400240024020230e0e1904050119191908031a07000206190b2021450d184118213d2006202141186c6a213e4104213f4114214041102141410c2142410921434108214441ffffffff0321454170214620062147410121010c110b2021450d17202141286c21022006210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101200241586a22020d000c180b0b2021450d16411c214820062021411c6c6a2149410c214a4108214b4114214c4104214d4110214e4109214f41ffffffff0321504170215120062152410221010c0f0b2021450d15202141146c21022006210103400240200141046a280200450d00200128020010190b200141146a21012002416c6a22020d000c160b0b02402022450d00200610190b201f450d1520201019200b0d160c170b2021450d13202141047421022006210103400240200141046a280200450d00200128020010190b200141106a2101200241706a22020d000c140b0b200641ff017122014102460d0320014101460d022021450d1320221019200b0d140c150b2021450d11411c215320062021411c6c6a2154410c2155410821564114215741042158411021594109215a41ffffffff03215b4170215c2006215d410321010c0a0b2021450d104104215e200620214104746a215f41102160410921614108216241ffffffff0321634170216420062165410421010c090b201f450d0c201f410c6c2102202121010340024020012802002205450d00200141046a280200450d00200510190b2001410c6a2101200241746a22020d000c0d0b0b201f450d0b41042194012021201f4104746a2195014110219601410c219701410821980141742199012021219a01410521010c070b0240024002400240024002400240024002400240024020240d00024020010e0b00070405020809060b030a000b410121090c0b0b410021090c0a0b410521090c090b410a21090c080b410321090c070b410421090c060b410821090c050b410221090c040b410621090c030b410721090c020b410b21090c010b410921090b200441e0006a41026a222420192d00003a0000200420042f01f0013b01600240200b200c470d00200b41016a2201200b490d072007200120012007491b220cad422c7e2226422088a70d072026a722014100480d070240200b450d00200a200541586a2001101a220a0d010c040b2001101b220a450d030b200a20056a220141586a20233a00002001201a3602002001417c6a201b360200200141786a201c360200200141746a201d360200200141706a201e3602002001416c6a201f360200200141686a2020360200200141646a2021360200200141606a20223602002001415c6a20063602002001415b6a20242d00003a0000200141596a20042f01603b0000200741026a21072005412c6a2105200b41016a210b200441b0036a20044188026a10d10220042802b0034101470d000b20042d00b403450d030b20042902b4032227a722084110762105200841087621092027422088a72107200441b0036a41106a2802002102200441bc036a2802002106200b0d0c0c0d0b20014104101c000b410820021028000b200b412c6c2101200a41606a21050240024003402001450d01200141546a2101200541206a21072005412c6a220d210520072d0000410b470d000b200d280200210e0c010b4100210e0b200b412c6c2101200a41586a21050240024003402001450d01200141546a2101200541286a21072005412c6a220d210520072d00004104470d000b200441c0006a200d10d202200e2004280244460d010c0d0b200e4100470d0c0b024002400240024020044188026a41086a2802002002470d004280c2cdeb062128200441b4026a200b360200200441b0026a2201200c360200200441ac026a200a360200200441003602a00220044280c2cdeb06428080808010843702a402200a450d0320012903002229a7212a200a2029422088a7222b412c6c6a2105200a2101034020052001460d0220012d000021022001412c6a2207210120024102470d000b200441386a200741586a10d20220042802382101200428023c21020c020b200441003a0048200441c4036a4101360200200441013602f401200442013702b403200441c4d6c3003602b0032004200441c8006a3602f0012004200441f0016a3602c003200441e0006a200441b0036a1024200441bb036a200441e0006a41086a280200360000200420042903603700b303200441ac026a200441b7036a290000370000200441053a00a402200441013602a002200420042900b0033700a5020240200b450d00200b412c6c2108200a21010340200110d3022001412c6a2101200841546a22080d000b0b200441a0026a41047221010240200c450d00200a10190b4100450d130c140b410021010b2002410020011b212c200141d889c20020011b212d200a202b412c6c6a2105200a210102400240034020052001460d0120012d000021022001412c6a2207210120024108470d000b200441306a200741586a10d20220042802302101200428023421020c010b410021010b2002410020011b212e200141d889c20020011b210d200a202b412c6c6a2105200a210102400240034020052001460d0120012d000021022001412c6a2207210120024104470d000b200441286a200741586a10d20220042802282101200428022c21020c010b410021010b2002410020011b212f200141d889c20020011b2130200a202b412c6c6a2105200a210102400240024003404100210e20052001460d0120012d000021022001412c6a2207210120024103470d000b200441206a200741586a10d20220042802244100200428022022011b22020d010c020b410021014100410041001b2202450d010b200141d889c20020011b41186a2101200241286c21024100210e0340200e20012d0000456a210e200141286a2101200241586a22020d000b0b41142131200d202e41146c6a213241002133410821344106212e41e7d7c1002135410c213641102137410221384104213941d7e4c100213a41e3c2b1e306213b4100213c410021010c010b4186d1c10041361030000b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e080001020304070a0b0b0b0240200d2032460d000240024002400340200d280200210102400240200d20346a2802002202202e460d0020022039470d012001203a460d042001280000203b470d010c040b20012035460d0220012035202e109703450d020b200d20316a220d2032470d000c040b0b4101213c200d20366a280200450d010c0a0b41012133200d20366a2802000d090b200d20376a2802002201200e6b220220014b0d0941bcd5c100210141262123202f20024d0d50203020022038746a2202450d5041e2d5c100210141202123202c200228020022024d0d50202d20022039746a2202450d50411f212341e7d0c100210120022802080d50200d20316a210d20022d000d2039460d1f0c500b024002402033203c71410171450d00200a202b412c6c6a2105200a2101034020052001460d0220012d000021022001412c6a2207210120024106470d000b200441186a200741586a10d202200428021c450d01200041bcd1c100360204411f21230c520b411c411e203c1b21234182d5c100419ed5c100203c1b21010c500b200a202b412c6c6a2105200a2101034020052001460d0520012d000021022001412c6a2207210120024102470d000b200441106a200741586a10d20220042802102101200428021421020c050b02402047203f6a280200450d00204728020010190b0240204720406a2802002202450d00204728020c21012002203f7421020340024020012d00002043470d00200120446a280200204571450d002001203f6a28020010190b200120416a2101200220466a22020d000b0b2047203d6a21010240204720416a280200450d00204720426a28020010190b200121472001203e470d1e0c500b02402052204a6a2802002202450d00205228020421012002204d7421020340024020012d0000204f470d002001204b6a280200205071450d002001204d6a28020010190b2001204e6a2101200220516a22020d000b0b02402052204b6a280200450d002052204d6a28020010190b205220486a210102402052204c6a280200450d00205228021010190b2001215220012049470d1e0c4f0b0240205d20556a2802002202450d00205d2802042101200220587421020340024020012d0000205a470d00200120566a280200205b71450d00200120586a28020010190b200120596a21012002205c6a22020d000b0b0240205d20566a280200450d00205d20586a28020010190b205d20536a21010240205d20576a280200450d00205d28021010190b2001215d20012054470d1e0c4e0b024020652802082202450d00206528020021012002205e7421020340024020012d00002061470d00200120626a280200206371450d002001205e6a28020010190b200120606a2101200220646a22020d000b0b206520606a210102402065205e6a280200450d00206528020010190b200121652001205f470d1e0c4d0b410021010b2002410020011b2166200141d889c20020011b2167200a202b412c6c6a2105200a21010240024003404100216820052001460d0120012d000021022001412c6a2207210120024103470d000b200441086a200741586a10d20220042802082101200428020c21020c010b410021010b41282169200141d889c20020011b226a2002410020011b41286c6a216b4103216c41b8f6c100216d4104216e41bbf6c100216f4101217041e0002171410d217241792173410e21744198f5c100217541072176419ff4c10021774106217842e5f0d1fbb5ac98b6ec00217941a7f4c100217a410a217b41b1f4c100217c4102217d41bbf4c100217e41c5f4c100217f410b21800141e9f4c10021810141ddf4c100218201410c21830141d0f4c10021840141b0f5c10021850141bef5c1002186014181f4c100218701410f2188014190f4c1002189014189f5c100218a0141ccf5c100218b014110218c0141dcf5c100218d01419ff5c100218e014111218f0141f4f4c1002190014115219101411c21920141002193010c310b209a0122072096016a219a01024020072802042201450d00024020072097016a2802002202450d0020022097016c21020340024020012802002205450d0020012094016a280200450d00200510190b20012097016a210120022099016a22020d000b0b20072098016a280200450d0020072094016a28020010190b209a01209501470d1c0c470b4113212341aad0c10021010c470b412a212341bdd0c10021010c460b02400240024002400240024002400240024002400240206a206b460d0041dbd1c100211b412d212302400240206a280208206c470d000240206a2802002201206d460d002001206d206c1097030d010b206a20696a211e0240024002400240024002400240024002400240024002400240024002400240206a2d001822010d0041aed2c100211b413621232066206a28021c22014d0d1020672001206e746a221f450d10206a28020c2101024002400240024002400240024002400240024002400240206a2802142202206c470d004188d2c100211b412621232001206f460d1c2001206f206c109703450d1c206f2001206c1097030d1c2070101b2207450d30200720683a0000201f2d000c2071470d1d201f2802082070470d1d201f280200210f41002101034020010d02200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c1e0b0b4188d2c100211b41262123200220736a220220744b0d1b024020020e0f00091c070508040602030b1c1c1c0a000b024020012075460d002075200120761097030d1c0b201f2d000c2071470d1b201f2802080d1b201e216a201f20726a2d0000206e460d450c1b0b201f20726a2d0000210120071019201e216a2001206e460d530c1a0b2001208701460d0a2087012001208801109703450d0a2001208901460d132089012001208801109703450d1302402001208a01460d00208a0120012088011097030d1a0b201f2d000c2071470d19201f2802080d19201e216a201f20726a2d0000206e460d4d0c190b2001208b01460d0a208b012001208c01109703450d0a02402001208d01460d00208d012001208c011097030d190b206c101b2207450d2e200720683a0002200720683b0000201f2d000c2071470d20201f280208206c470d20201f280200210f4100210103402001207d4b0d15200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c210b0b02402001208401460d00208401200120721097030d180b201f2d000c2071470d17201f2802080d17201e216a201f20726a2d0000206e460d440c170b2001207f460d09207f2001208001109703450d0902402001208101460d0020810120012080011097030d170b201f2d000c2071470d16201f2802080d16201e216a201f20726a2d0000206e460d440c160b2001208501460d0920850120012074109703450d0902402001208601460d00208601200120741097030d160b206c101b2207450d2e200720683a0002200720683b0000201f2d000c2071470d1e201f280208206c470d1e201f280200210f4100210103402001207d4b0d13200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c1f0b0b2001207a460d09207a2001207b109703450d092001207c460d0f207c2001207b109703450d0f02402001207e460d00207e2001207b1097030d150b201f2d000c2071470d14201f2802080d14201e216a201f20726a2d0000206e460d440c140b02402001208201460d0020820120012083011097030d140b201f2d000c2071470d13201f2802080d13201e216a201f20726a2d0000206e460d3f0c130b024020012077460d0020012900002079520d130b2076101b2207450d2e20072068360003200720703a0002200720683b0000201f2d000c2071470d15201f2802082076470d15201f280200210f410021010340200120784b0d09200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c160b0b02402001209001460d0020900120012091011097030d120b201f2d000c2071470d11201f2802080d11201e216a201f20726a2d0000206e460d3c0c110b02402001208e01460d00208e012001208f011097030d110b207d101b2207450d25200720683b0000201f2d000c2071470d14201f280208207d470d14201f280200210f410021010340200120704b0d08200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c150b0b02402001207d470d00206a2092016a2193010b201e216a410621010c5c0b206e101b2207450d2620072068360000201f2d000c2071470d14201f280208206e470d14201f280200210f4100210103402001206c4b0d07200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c150b0b201f2d000c2071470d0d201f2802080d0d201f20726a2d00002201206e460d0d201e216a2001206e72206e460d450c0d0b201f2d000c2071470d0c201f2802080d0c201e216a201f20726a2d0000206e460d3b0c0c0b201f2d000c2071470d0b201f2802080d0b201f20726a2d00002201206e460d0b201e216a2001206e72206e460d330c0b0b2076101b2207450d2520072068360003200720703a0002200720683b0000201f2d000c2071470d0f201f2802082076470d0f201f280200210f410021010340200120784b0d04200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c100b0b201f20726a2d00002201206e460d0c20071019201e216a2001206e72206e460d3c0c090b201f20726a2d0000210120071019201e216a2001206e460d310c080b201f20726a2d0000210120071019201e216a2001206e460d3d0c070b201f20726a2d00002201206e460d0b20071019201e216a2001206e72206e460d380c060b2070101b2207450d1c200720683a0000201f2d000c2071470d13201f2802082070470d13201f280200210f41002101034020010d04200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c140b0b207d101b2207450d1e200720683b0000201f2d000c2071470d13201f280208207d470d13201f280200210f410021010340200120704b0d04200720016a2102200f20016a2105200120706a210120052d000020022d0000460d000c140b0b201f20726a2d0000210120071019201e216a2001206e460d3a0c030b201f20726a2d0000210120071019201e216a2001206e460d290c020b201f20726a2d00002201206e460d0f20071019201e216a2001206e72206e460d360c010b201f20726a2d0000210120071019201e216a2001206e460d310b2000201b3602040c520b2007101920004188d2c1003602040c510b209301450d04209301280204450d07209301280200229b01209301280208229c014d0d0820004196d3c10036020441c90021230c500b2007101920004188d2c1003602040c4f0b2007101920004188d2c1003602040c4e0b2007101920004188d2c1003602040c4d0b2007101920004188d2c1003602040c4c0b4100219b014100219c010c040b2007101920004188d2c1003602040c4a0b2007101920004188d2c1003602040c490b200041e4d2c100360204413221230c480b209c0120032802384d0d00200041dfd3c10036020441c10021230c470b200441b0036a41086a22024200370300200441a0c0c1003602b403200420032903083e02c003200420032903103e02b003200441b0036a4104722201410d10d4022001410c10d4022001410710d4022001410f10d402200441d8006a20042802c003360200200441c8006a41086a2002290300370300200420042903b003370348200a450d10200441b0036a410c6a20293702002004200a3602b80320042028428080808010843703b003200441e0006a200441b0036a10d5024101101b2201450d11200141003a0000200420042f01b0033b01a002200441c0036a41e0083b0100200441b8036a428180808010370300200420013602b403200441013602b003200420042f01a0023b01c203200441e0006a200441b0036a10d602219d014103101b2202450d12200241026a41002d00baf6413a0000200241002f00b8f6413b00004103101b2205450d13200541026a41002d00bdf6413a0000200541002f00bbf6413b0000200441a0026a41026a229e01200441b0036a41026a229f012d00003a0000200420042f00b0033b01a002200441f4006a22a0012802002107200441e0006a41106a2802002101209f01209e012d00003a0000200420042f01a0023b01b00320072001470d05200141016a22072001490d412001410174229e0120072007209e01491b229e01ad42287e2227422088a70d412027a722074100480d412001450d03200441ec006a280200200141286c2007101a2201450d060c040b20a1012d000020a7016a220120a8014b0d30024002400240024020010e0400030102000b20a10128020c2201450d33200120a9016c210220a10128020420aa016a210103400240200120ab016a2802000d002001280200220520a001490d0020012005209d016a3602000b200120a9016a2101200220ac016a22020d000c340b0b20a10128020c2201450d3220a10128020422bf01200120ad016c6a21c001410021010c310b20a10128020c2201450d3120a10128020422c101200120af016c6a21c2010c2f0b20a101280204220120a001490d3020a101209e016a2001209d016a36020020a10120a3016a22a10120a401470d2d0c310b2007101920004188d2c1003602040c440b2007101920004188d2c1003602040c430b2007101b2201450d020b200441f0006a209e01360200200441ec006a2001360200200441f4006a28020021070b200441ec006a280200200741286c6a220141003a00182001200536020c200142838080803037020420012002360200200141106a4283808080303702002001411b6a200441b2036a2d00003a0000200141196a20042f01b0033b00002001411c6a209d0136020020a00120a00128020041016a360200200441b0036a200441e0006a418c011095031a200441f0016a200441b0036a10d702200441f0016a41106a280200229e01412c6c210120042802f80122a10141586a210202400340410021052001450d01200141546a2101200241286a21072002412c6a22a001210220072d00004103470d000b20a00141086a2802002201450d00200141286c210220a00128020041186a2101410021050340200520012d0000456a2105200141286a2101200241586a22020d000b0b209e01412c6c210120a10141586a21022005417f6a21a00102400340410021052001450d01200141546a2101200241286a21072002412c6a229d01210220072d00004103470d000b209d0141086a2802002201450d00200141286c2102209d0128020041186a2101410021050340200520012d0000456a2105200141286a2101200241586a22020d000b0b209e01412c6c210120a10141606a21020240024003402001450d01200141546a2101200241206a21072002412c6a229d01210220072d00004104470d000b209d012802002101209e010d010c2f0b41002101209e01450d2e0b200120056a21a201412c21a30120a101209e01412c6c6a21a4014104219e01200441c8006a41047221a501410021a601417821a701410321a801411421a901411021aa01417c21ab014101219d01416c21ac01411c21ad01410221ae01411821af01410c21b001410821b10142808080801021b201412d21b30142202127417f21b401410b219f01417021b501417e21b60141ec0021b701420321b801420221b90141ff0121ba01410521bb01410621bc01410021bd01410021be01410721010c3a0b20074104101c000b41014101101c000b41024101101c000b41034101101c000b41014101101c000b41044101101c000b41034101101c000b41024101101c000b41074101101c000b41074101101c000b4186d1c10041361030000b41014101101c000b41034101101c000b41034101101c000b410021010c2b0b410121010c2a0b410221010c290b410321010c280b410421010c270b410521010c260b410621010c250b410621010c240b410621010c230b410621010c220b410621010c210b410621010c200b410621010c1f0b410621010c1e0b410621010c1d0b410621010c1c0b410621010c1b0b410621010c1a0b410621010c190b410621010c180b410621010c170b410621010c160b410621010c150b410621010c140b410621010c130b410621010c120b410721010c110b410121010b034002400240024002400240024002400240024020010e020001010b20bf01220120ad016a21bf01024020012802182202450d0020012802102101200220ae01742102034002402001280200220520a001490d0020012005209d016a3602000b2001209e016a2101200220ab016a22020d000b0b20bf0120c001470d010c090b20be012111024020c101280214209e01742202450d0020c10128020c21010340024020012d0000209f01470d002001209e016a2205280200220720a001490d0020052007209d016a3602000b200120aa016a2101200220b5016a22020d000b0b20b101101b2201450d02200120b201370200209e01101b221e450d0120c10120b0016a2105201e20a60136020020c10120a9016a22102802002224450d03410021024101211b4101210f4101211c4101210702400240024002404100202422234f0d00024003402002209d016a21230240024002400240024020052802002002209e01746a2d0000220220b6016a20a8014f0d00200210d80221c301200441c8006a20b1016a28020021c40120a50121c5010c010b0240024002400240024002400240200220bb01460d00200220bc01470d012007450d0c200720b4016a2107200f210220232024490d0a0c150b2007450d0b201b200f470d03201b209d016a2202201b490d28201b209d0174221f20022002201f491b2202ad20b801862226202788a70d282026a7221f20a601480d28201b450d012001201b20a80174201f101a22010d020c040b200210d80221c601200441c8006a20b1016a28020021c70120a50121c8010c060b201f101b2201450d020b2002211b0b2001200f20a801746a2202209d01360204200220233602000240201c200720b4016a221f470d00201c209d01742202200720072002491b2202ad20b901862226202788a70d252026a7221920a601480d2502400240201c450d00201e201c20ae01742019101a221e0d010c040b2019101b221e450d030b2002211c0b200f209d016a2102201e201f20ae01746a200f360200202320244f0d100c050b201f4104101c000b20194104101c000b410021020c010b410121020b0240024002400240024003400240024020020e020001010b20c501280200221920b1016a21be0120192f0106211f410021020240024002400340201f2002460d0120a60120b401209d0120be0120026a2d0000221a20c30120ba0171221d4b1b201a201d461b221a450d022002209d016a2102201a209d01460d000b200220b4016a211f0b024020c401450d0020c40120b4016a21c4012019201f20ae01746a20b7016a21c501410021020c040b200441c8006a211f200720b4016a22022007490d010c0b0b200441c8006a211f02402019200220a801746a20a9016a2202450d0020022802002219209d01460d0b201920ae01470d002002209e016a211f0b200720b4016a220220074f0d0a0b200220074b0d09200f201e200220ae01746a28020022024d0d092001200220a801746a22192802042202201f2802006a221f2002490d092019209e016a201f360200201b200f470d06201b209d016a2202201b490d26201b209d0174221f20022002201f491b221fad20b801862226202788a70d262026a7220220a601480d26201b450d042001201b20a801742002101a22010d050c0b0b20c801280200221920b1016a21be0120192f0106211f4100210202400340201f2002460d0120a60120b401209d0120be0120026a2d0000221a20c60120ba0171221d4b1b201a201d461b221a450d032002209d016a2102201a209d01460d000b200220b4016a211f0b024020c701450d0020c70120b4016a21c7012019201f20ae01746a20b7016a21c801410121020c010b0b200441c8006a211f200720b4016a22022007490d010c070b200441c8006a211f02402019200220a801746a20a9016a2202450d0020022802002219209d01460d07201920ae01470d002002209e016a211f0b200720b4016a220220074f0d060b200220074b0d05200f201e200220ae01746a28020022024d0d052001200220a801746a22192802042202201f2802006a221f2002490d052019209e016a201f360200200f210220232024490d030c0e0b2002101b2201450d060b201f211b0b2001200f20a801746a2202209d01360204200220233602000240201c2007470d00201c209d016a2202201c490d20201c209d0174221f20022002201f491b221fad20b901862226202788a70d202026a7220220a601480d2002400240201c450d00201e201c20ae01742002101a221e0d010c080b2002101b221e450d070b201f211c0b200f209d016a2102201e200720ae01746a200f3602002007209d016a2107202320244f0d0b0b2002210f2023220220102802002223490d000c020b0b0240201b450d00200110190b410121bd010240201c450d00201e1019201121be0120a10120a3016a22a10120a401470d040c0e0b201121be010c0c0b4194d5c30020022023104a000b20024104101c000b20024104101c000b410721010c170b410021010c060b41044104101c000b41084104101c000b200120b1016a210f4101211c4101211b0c010b2002450d012001200220a801746a210f0b2001212341012102034020012902002126200420b3013a00b003200420262027883e02b403200520022026a76a220720b4016a200441b0036a10d9022004209f013a00b003200420a0013602b40320052007200441b0036a10d902200220ae016a2102200f200120b1016a2201470d000b202321010b0240201b450d00200110190b0240201c450d00201e10190b20c10120af016a21c10102400240200441c8006a20aa016a280200450d0020102802002202450d00200528020021012002209e01742102410021050340024020012d000020a301470d002001209f013a00002001209e016a20a2013602002005209d016a21050b200120aa016a2101200220b5016a22020d000b410121be0120050d010b201121be010b20c10120c201460d01410121010c000b0b20a10120a3016a22a10120a401470d0d0b024020bd01410171450d0020042802f8012109200441fc016a2902002227a7210202402027422088a72201450d002001412c6c2108200921010340200110d3022001412c6a2101200841546a22080d000b0b02402002450d00200910190b200428024c200441d0006a280200200441d4006a28020010ab02200041a0d4c100360204411a21010c030b024020be01410171450d00200441b0036a41106a200441f0016a41106a280200360200200441b0036a41086a200441f0016a41086a290300370300200420042903f0013703b003200441a0026a200441b0036a10d5024110101b2208450d08200841063a00004101101b2201450d09200141003a00004101101b2202450d0a200220012d00003a0000200110194110101b2209450d0b200941063a000041f000101b2201450d0c200141063a00602001412c3b0150200120a0013602442001410b3a0040200141d8003a00302001412d3a0020200141003602142001410f3a0010200141003602042001410f3a00002001200441d8006a280200360224024020092d00004109470d00200928020841ffffffff0371450d00200928020410190b20091019024020082d00004109470d00200828020841ffffffff0371450d00200828020410190b20081019200441d4036a4287808080f000370200200441d0036a2001360200200441cc036a4100360200200441b0036a410c6a4281808080800c370200200441b8036a4101360200200441003602dc03200442043702c403200420023602b403200441013602b003200441a0026a200441b0036a10da02200441b0036a200441a0026a418c011095031a20044188026a200441b0036a10d70220044188026a410c6a290200212720042802900221a101200428028c02210120042802880221080c020b20042802f80121a1010b200441fc016a290200212720042802f401210120042802f00121080b200428024c200441d0006a280200200441c8006a410c6a28020010ab0220a101450d02200441a0026a410c6a2027370200200420a1013602a80220042001ad4220862008ad843703a002200441b0036a200441a0026a200328023410db0220042802b0034101470d010240200441b8036a280200450d0020042802b40310190b200041bad4c100360204412321010b20004101360200200041086a2001360200200441c0046a24000f0b200441bc036a28020022a001450d01200441c0036a2903002127200441b8036a280200210220042802b403210920032802302161200441003602900220044201370388024104101b2201450d022004410436028c0220044190026a22082008280200220541046a3602002004200136028802200120056a2009360000024002400240200428028c022209200828020022016b41044f0d00200141046a22082001490d0d20094101742201200820082001491b22014100480d0d2009450d0120042802880220092001101a2208450d020c0e0b20042802880221080c0e0b2001101b22080d0c0b20014101101c000b4186d1c10041361030000b4186d1c10041361030000b41044101101c000b41104108101c000b41014101101c000b41014101101c000b41104108101c000b41f0004108101c000b410721010c000b0b101d000b2004200136028c02200420083602880220044190026a28020021010b20044188026a41086a200141046a360200200820016a200236000020a0012027422088a72201412c6c22086a21022027a72164024002400240024002402001450d00200841546a2122200441b0036a4101722108200441b0036a41276a2105200441b0036a41206a210b200441b0036a41186a2107200441b0036a41106a2106200441b0036a41086a212120a0012101034020012d000021092005200141286a280000360000200b200141216a2900003703002007200141196a2900003703002006200141116a2900003703002021200141096a2900003703002004200141016a2900003703b0032009410f460d02200441a0026a41276a22202005280000360000200441a0026a41206a220d200b290300370300200441a0026a41186a220e2007290300370300200441a0026a41106a22602006290300370300200441a0026a41086a22412021290300370300200420042903b0033703a002200820042903a002370000200841086a2041290300370000200841106a2060290300370000200841186a200e290300370000200841206a200d290300370000200841276a2020280000360000200420093a00b003200441e0006a200441b0036a20044188026a10dc0220042d00602209411a470d05202241546a21222001412c6a22012002470d000b200222012002470d020c030b20a00122012002470d010c020b2001412c6a22012002460d010b200441b0036a4101722108200441b0036a41276a2105200441b0036a41206a210b200441b0036a41186a2107200441b0036a41106a2106200441b0036a41086a2121034020012d000021092005200141286a280000360000200b200141216a2900003703002007200141196a2900003703002006200141116a2900003703002021200141096a2900003703002004200141016a2900003703b0032009410f460d01200441a0026a41276a22222005280000360000200441a0026a41206a2220200b290300370300200441a0026a41186a220d2007290300370300200441a0026a41106a220e2006290300370300200441a0026a41086a22602021290300370300200420042903b0033703a002200820042903a002370000200841086a2060290300370000200841106a200e290300370000200841186a200d290300370000200841206a2020290300370000200841276a2022280000360000200420093a00b003200441b0036a10d3022001412c6a22012002470d000b0b02402064450d0020a00110190b20044188026a41086a280200210120042903880221272000411c6a41003a0000200041186a2001360200200041106a20273702002000410c6a209c01360200200041086a209b0136020020002061360204200041003602002000411d6a20042f00b0033b00002000411f6a200441b2036a2d00003a0000200441c0046a24000f0b200441e0006a41086a28020021612004280264215c02402022450d002001412c6a2101200441b0036a4101722108200441b0036a41276a210b200441b0036a41206a2107200441b0036a41186a2106200441b0036a41106a2121200441b0036a41086a2122034020012d00002105200b200141286a2800003600002007200141216a2900003703002006200141196a2900003703002021200141116a2900003703002022200141096a2900003703002004200141016a2900003703b0032005410f460d01200441a0026a41276a2220200b280000360000200441a0026a41206a220d2007290300370300200441a0026a41186a220e2006290300370300200441a0026a41106a22602021290300370300200441a0026a41086a22412022290300370300200420042903b0033703a002200820042903a002370000200841086a2041290300370000200841106a2060290300370000200841186a200e290300370000200841206a200d290300370000200841276a2020280000360000200420053a00b003200441b0036a10d3022001412c6a22012002470d000b0b02402064450d0020a00110190b0240200428028c02450d0020042802880210190b024020094105470d002061450d00205c10190b200041ddd4c10036020420004101360200200041086a4125360200200441c0046a24000f0b2020450d0320211019200b0d040c050b200020013602040b20004101360200200041086a2023360200200a450d0b0240202b450d00202b412c6c2108200a21010340200110d3022001412c6a2101200841546a22080d000b0b202a450d0b200a1019200441c0046a24000f0b2022450d00200610190b200b450d010b200b412c6c210b200a21010340200110d3022001412c6a2101200b41546a220b0d000b0b200c450d04200a10190c040b0240200b450d00200b412c6c2108200a21010340200110d3022001412c6a2101200841546a22080d000b0b41192108200c450d00200a10190b0b0c010b410021090b200441b0026a2002360200200441ac026a2006360200200441013602a00220042007ad4220862005ad42ffff03834210862009ad42ff0183420886842008ad42ff018384843702a402200441a0026a4104722101200841ff01714105470d010b2001280208450d002001280204101920042802a0020d0041002108200441ac026a280200220921010340200110d3022001412c6a2101200841546a22080d000b200441b0026a280200450d00200910190b20004194d0c10036020420004101360200200041086a41163602000b200441c0046a24000bf1dc0137077f017e017f017e027f017e027f017e3e7f027e107f017e077f017e027f027e0a7f017e037f017e017f017e0f7f027e067f017e117f027e0e7f017e0b7f027e107f027e0a7f017e037f027e397f017e067f017e017f017e047f017e0f7f017e097f017e0b7f017e0b7f017e277f230041d080046b22022400024002402001280204220320012802082204470d00200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022802bc8004210120022802b88004210420004101360200200041003a00042001450d01200410190c010b200441016a21050240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004417f460d0020032005490d01200128020020046a2d00002104200141086a200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402004410b4b0d0002400240024002400240024002400240024002400240024020040e0c00070405020809060b030a01000b200241206a200110d901410121062002280224210720022802204101470d1220074108762108200241306a2802002101200241206a41086a29030021090cab010b200241206a200110e40220022802204101470d0b20022802242201410876210a200241206a41086a290300220b4220882109200241306a280200210c0cbe010b200241206a200110e40220022802204101470d0b200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030cbb010b200241206a200110e40220022802204101470d0b20022802242201410876210d200241206a41086a290300220e4220882109200241306a280200210f0cb8010b200241206a200110e40220022802204101470d0b200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030cb5010b200241206a200110e40220022802204101470d0b200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030cb2010b200241206a200110e40220022802204101470d0b200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030caf010b200241206a200110e40220022802204101470d0c200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030cac010b200241206a200110e40220022802204101470d0c200228022422014108762104200241206a41086a2903002209422088210b200241306a28020021030ca9010b200241206a200110e40220022802204101470d0c200228022422104108762101200241206a41086a29030022114220882109200241306a28020021120ca6010b200241206a200110e40220022802204101470d0c200228022422134108762101200241206a41086a2903002209422088210b200241306a28020021140ca3010b200241206a200110e40220022802204101470d0c200041013602002000200241206a41047222012902003702042000410c6a200141086a290200370200200241d080046a24000f0b200041123a000420004101360200200041056a20043a0000200241d080046a24000f0b200241186a200241346a280200360200200241106a2215200241206a410c6a290200370300200220022902243703084100210a410021014100211603402001411f4b0d0c20152802002205200241086a410c6a22172802002204460d1b200441016a21032004417f460d5620052003490d57200228020820046a2d0000210420172003360200200441ff00712001411f71742016722116200141076a21012004418001710d000b20014120490d2b20046741686a41ff017141044f0d2b4100210a410d21180c0c0b200241c880046a200241346a280200360200200241c080046a22012002412c6a290200370300200220022902243703b88004200128020021084100210420022802c48004210120022802b8800421194100210703402004411f4b0d0d20082001460d1b2001417f460d572008200141016a221a490d58201920016a2d0000220341ff00712004411f71742007722107200441076a2104201a21012003418001710d000b200241c480046a201a36020020044120490d2b20036741686a41ff017141044f0d2b41002101410d21080c0d0b200241c880046a200241346a280200360200200241c080046a221b200241206a410c6a290200370300200220022902243703b880044100210d410021014100211c03402001411f4b0d0e201b2802002205200241b880046a410c6a221d2802002204460d1b200441016a21032004417f460d5820052003490d5920022802b8800420046a2d00002104201d2003360200200441ff00712001411f7174201c72211c200141076a21012004418001710d000b20014120490d2b20046741686a41ff017141044f0d2b4100210d410d211e0c0e0b200241c880046a200241346a280200360200200241c080046a221f200241206a410c6a290200370300200220022902243703b8800441002120410021014100212103402001411f4b0d0f201f2802002205200241b880046a410c6a22222802002204460d1b200441016a21032004417f460d5920052003490d5a20022802b8800420046a2d0000210420222003360200200441ff00712001411f71742021722121200141076a21012004418001710d000b20014120490d2b20046741686a41ff017141044f0d2b410d2101410021230ca8010b200241346a2802002124200241306a28020021012002412c6a2802002125200241286a28020021262002280224212741002122410021044100212803402004411f4b0d0f20252001460d1b2001417f460d5a2025200141016a2229490d5b202720016a2d0000220341ff00712004411f71742028722128200441076a2104202921012003418001710d000b20044120490d2b20036741686a41ff017141044f0d2b410d2101410021040ca5010b200241c880046a200241346a280200360200200241c080046a222a200241206a410c6a290200370300200220022902243703b880044100212b410021014100212c03402001411f4b0d0f202a2802002205200241b880046a410c6a22222802002204460d1b200441016a21032004417f460d5b20052003490d5c20022802b8800420046a2d0000210420222003360200200441ff00712001411f7174202c72212c200141076a21012004418001710d000b20014120490d2b20046741686a41ff017141044f0d2b410d2101410021230ca2010b41002123200241206a4100418080011094031a410021254100210302402007450d00200141086a212d200141046a21284101210641002125410021054100212e034020282802002221202d28020022036b2007202e6b220441808001200441808001491b2204490d23200320046a22082003490d6720212008490d68200241206a200128020020036a20041095031a202d20083602000240024002400240202520056b20044f0d00200520046a22032005490d860120254101742208200320032008491b22084100480d86012025450d01200620252008101a22060d020c6e0b200420056a21030c020b2008101b2206450d6c0b200821250b200620056a200241206a20041095031a2003210520072004202e6a222e4b0d000b0b41002101410021040340410021082001411f4b0d2320032023460d25200320234d0d68200620236a2d0000220541ff00712001411f71742004722104200141076a2101202341016a222e21232005418001710d000b20014120490d2f20056741686a41ff017141044f0d2f410d21070c230b200241346a280200212f200241306a28020021012002412c6a2802002106200241286a280200213020022802242131410021044100212d03402004411f4b0d0e20062001460d1a2001417f460d5b2006200141016a2232490d5c203120016a2d0000220341ff00712004411f7174202d72212d200441076a2104203221012003418001710d000b20044120490d2a20036741686a41ff017141044f0d2a410d21010c9e010b200241c880046a200241346a280200360200200241c080046a22012002412c6a290200370300200220022902243703b88004200128020021054100210420022802c48004210120022802b8800421254100210303402004411f4b0d0e20052001460d1a2001417f460d5c2005200141016a2223490d5d202520016a2d0000222e41ff00712004411f71742003722103200441076a210420232101202e418001710d000b200241c480046a202336020020044120490d2a202e6741686a41ff017141044f0d2a41002104410d21250c0e0b200241c880046a200241346a280200360200200241c080046a2233200241206a410c6a290200370300200220022902243703b8800441002134410021014100212203402001411f4b0d0f20332802002212200241b880046a410c6a22052802002204460d1a200441016a21032004417f460d5d20122003490d5e20022802b88004222020046a2d0000210420052003360200200441ff00712001411f71742022722122200141076a21012004418001710d000b20014120490d2a20046741686a41ff017141044f0d2a410d2110410021350c98010b200241346a2802002136200241306a28020021012002412c6a280200212e200241286a280200213720022802242138410021044100213903402004411f4b0d0f202e2001460d1a2001417f460d5e202e200141016a2223490d5f203820016a2d0000220341ff00712004411f71742039722139200441076a2104202321012003418001710d000b20044120490d2a20036741686a41ff017141044f0d2a410d21130c1a0b200241346a2802002106200241306a28020021012002412c6a2802002103200241286a280200210820022802242125410021044100210503402004411f4b0d0f20032001460d1b2001417f460d5f2003200141016a222e490d60202520016a2d0000222341ff00712004411f71742005722105200441076a2104202e21012023418001710d000b024020044120490d00410d210120236741686a41ff01714104490d1c0b2006202e46210102402008450d00202510190b2001450d2b410921040c91010b410f21180b4100213a4100213b0ca4010b200241c480046a200136020041002101410f21080b4100211a410021190ca0010b410f211e0b4100213c4100213d0c9c010b410f2101410021230c99010b410f2101410021040c96010b410f2101410021230c93010b410f21010c90010b200241c480046a200136020041002104410f21250b41002108410021060c8c010b410f2110410021350c89010b410f21130c0b0b410f21010c0c0b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241b880046a200241206a102420022903b880042209422088a7213a20022802c08004210c2009a7213b410521184100210a0c96010b200241c480046a2008360200200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a7211a200228021021032009a7211941052108410021010c93010b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a7213c2002280210210f2009a7213d4105211e4100210d0c90010b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a72120200228021021032009a72123410521010c8d010b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022903b880042209422088a7212220022802c0800421032009a72104410521010c8a010b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a7212b200228021021032009a72123410521010c87010b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022802c08004210320022802bc8004212220022802b880042120410521010c84010b200241c480046a2005360200200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a72108200228021021032009a7210641052125410021040c81010b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088a72134200228021021122009a72135410521100c7e0b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022802c08004211420022903b880042109410521130b2009422088a7213e2009a7213f0c7a0b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a1024410521010b2000200136020420004101360200200041086a20022902b88004370200200041106a200241b880046a41086a2802003602002008450d8c0120251019200241d080046a24000f0b200241013a00a88004200241cc80046a410136020020024101360204200242013702bc8004200241c4d6c3003602b880042002200241a880046a360200200220023602c88004200241086a200241b880046a102420022802102101200229030821094105210702402025450d00200610190b0c760b410f21070b410021234100212d0c730b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022903b880042209422088a7212320022802c0800421012009a7212d410521070c720b2016450d0b410021404104214141012142411f2143410c2144200241086a410c6a214541082146200241086a41086a2147417f214841ff0021494107214a418001214b4168214c4120214d41ff01214e41808004214f421c215042202151411c215241102153410321544118215541142156410421054100211541002117410021220c4d0b2007450d0b41002163410421054108216441012165200241346a21664101216741102168200241206a41106a21694201216a41c4d6c300216b41ff01216c420c216d4220216e410c216f417b217041792171417c217241782173417f217441c000217541807f21764170217741ffffff07217842808080807021794108217a4100217b4100217c2008201a460d4b410221220c4e0b201c450d0b410021800141042181014101218201411f218301410c218401200241b880046a410c6a2185014108218601200241b880046a41086a218701417f21880141ff002189014107218a01418001218b014168218c014120218d0141ff01218e01421c218f014220219001411c219101411021920141032193014118219401411421950141022196014202219701417c219801410421054100211b4100211d410321220c4e0b2021450d0b41042199014100219a014101219b01410c219c01200241206a410c6a219d014108219e01200241206a41086a219f01417f21a001410321a101411f21a20141ff0021a301410721a40141800121a501416821a601412021a70141ff0121a801422821a901422021aa01412821ab01411c21ac01411a21ad01411921ae01411821af01411421b001411021b101410221b20141c00021b30141807f21b401417021b50141847e21b6014100211f41042105410021b701410021b801410421220c4e0b2028450d0b410421ba01410021bb01410121bc01411f21bd01417f21be0141ff0021bf01410721c00141800121c101416821c201412021c30141ff0121c401420221c501422021c601410221c701410021c801410021c90141042105410521220c4e0b202c450d0b410421ca01410021cb01410121cc01410c21cd01410821ce01417f21cf01410321d001411f212b41ff0021d101410721d20141800121d301416821d401412021d50141ff0121d601421421d701422021d801411421d9014100212a41042105410021da01410021db01410621220c4e0b202d450d0b410121dc01410120066b21dd01410421de01410021df01200241346a21e001410121e101411021e201420121e30141c4d6c30021e401410821e50141ff0121e601420421e701422021e801417f21e90141e00021ea01410321eb01411f21ec0141ff0021ed01410721ee0141800121ef01416821f001412021f101200241c280046a21f201200241c180046a21f30141c00021f40141807f21f50141fb0121f601410221f701410021f801410021f901410021fa0141042105410721220c4e0b2003450d0b200241206a410c6a2121200241206a41086a2128410021074100212e410021014100212d410421050340200241206a200241b880046a10e50220022f002520022d0027411074722104202128020021082028280200210620022d0024212520022802204101460d11200141016a212302402001202d470d002007202320232007491b222dad420c7e2209422088a70d552009a7221c4100480d5502402001450d002005202e201c101a22050d010c410b201c101b2205450d400b2005202e6a220120253a0000200141036a20044110763a0000200141016a20043b0000200141086a2008360200200141046a2006360200200741026a2107202e410c6a212e2023210120232003490d000c0d0b0b2022450d0c200241b880046a410c6a215d200241206a41086a215f410021604100215c410021584100213341042157410421900241042105024020122003460d000340200341016a21042003417f460d4120122004490d42202020036a2c00002101205d200436020020014100480d16200141017441807f71200172220141ff017141847e6a221041034b0d174100215e0240024002400240024020100e0400010203000b4103215e20122004470d030c1e0b4102215e20122004470d020c1d0b4101215e0b20122004460d1b0b200341026a21032004417f460d4320122003490d44202020046a2d00002101205d20033602004100210302402001450d0020014101470d1c41800221030b200241206a200241b880046a1021200241206a410c6a2802002134205f28020021352002280224211020022802204101460d1d205841016a2104024020582033470d002060200420042060491b2233ad4204862262422088a70d552062a722014100480d55024002402058450d002057205c2001101a22570d010c480b2001101b2257450d470b2057219002205721050b2005205c6a220120103602002001410c6a20614180807c71205e722003722261360200200141086a2034360200200141046a2035360200200420224f0d1f206041026a2160205c41106a215c20022802b88004212020042158200241b880046a41086a2802002212205d2802002203470d000b0b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a1024200229020c216220022802082135410521040c170b2039450d0c200241296a219102410021920241042193024101219402411f219502417f21960241ff0021970241072198024180012199024168219a024120219b0241ff01219c0241808001219d024110219e02200241086a41106a219f02410c21a002200241086a410c6a21a102422021a202410221a302410821a402200241206a41086a21a502410621a602411421a702200241206a41146a21a802420421a902410321aa02421821ab02411821ac02417e21ad0241807f21ae0241847e21af02420321b00241042105410021b102410021b202410821220c4c0b2004450d0e200241206a41004180081094031a410121284100212d410021054100210703402003202e6b200420076b22014180082001418008491b2201490d10202e20016a2221202e490d3a20032021490d3b200241206a2006202e6a20011095031a0240024002400240202d20056b20014f0d00200520016a22232005490d55202d410174222e20232023202e491b222e4100480d55202d450d012028202d202e101a22280d020c410b200120056a21230c020b202e101b2228450d3f0b202e212d0b202820056a200241206a20011095031a2021212e202321052004200120076a22074b0d000b200241206a20282023103220022802204101470d1041082107202d450d1c202810190c670b20024103410220011b3a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a10242002412b6a200241c080046a280200360000200220022903b88004370023200041053a000420004101360200200020022900203700052000410c6a200241276a290000370000200241d080046a24000f0b410021154104210541002117410021010c4d0b4100212241042105410021040c620b4100211b410421054100211d410121010c4b0b410021b70141042105410021010c5f0b41042105410021c801410021c9010c5d0b410021da0141042105410021010c5b0b4104210541002104410021fa010c590b41042105410021234100212d0b200241c480046a28020020022802c88004462101024020022802bc8004450d0020022802b8800410190b2001450d022023ad422086202dad84210b410621040c5c0b4104210541002104410021330c430b410021b10241042105410021b202410221010c430b20024103410220011b3a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088210b200228021021034105210141002104202d450d61200510190c610b200241306a2802002103202d450d5f200510190c5f0b4100210541012128410021234100212d2003202e490d020c3e0b200241013a00a88004200241cc80046a410136020020024101360204200242013702bc8004200241c4d6c3003602b880042002200241a880046a360200200220023602c88004200241086a200241b880046a102420022903082209422088a72123200228021021012009a7210441052107202d450d0a202810192004212d0c570b2028410876210520032021222e4f0d3c0b202e20031027000b411821040c010b410621040b0b2062422088a721122062a721340c020b200241013a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022802102112200228020c213420022802082135410521040c010b410c21040b200141ff017141087420047221102058450d3e0c330b200241306a280200211220580d320c3d0b2004212d0c4c0b205841016a21040c320b0c4a0b417f20051027000b200520031028000b417f20031027000b200320051028000b417f200141016a1027000b200141016a20081028000b417f20031027000b200320051028000b417f20031027000b200320051028000b417f200141016a1027000b200141016a20251028000b417f20031027000b200320051028000b417f200141016a1027000b200141016a20061028000b417f200141016a1027000b200141016a20051028000b417f20031027000b200320121028000b417f200141016a1027000b200141016a202e1028000b417f200141016a1027000b200141016a20031028000b200320081027000b200820211028000b202341016a20031028000b20084101101c000b202e20211027000b202120031028000b201c4104101c000b202e4101101c000b417f20041027000b200420121028000b417f20031027000b200320121028000b20014104101c000b410121220c010b410321010c0b0b410321010c0a0b410321010c090b410321010c080b410321010c070b410321010c060b410321010c050b410321010c040b410321010c030b2005205c6a21ed02411021ee02410421ef02410921f002410821f10241ffffffff0321f202417021f302410e2122410321010c020b02402003202e6b2204417f4c0d00024002402004450d002004101b22010d0120044101101c000b410121010b2023ad4220862109202dad210b20012006202e6a20041095031a2004ad220e422086211102402025450d00200610190b2009200b84210b2011200e8421092005410874202841ff0171722105410121040c190b102b000b200241c480046a28020020022802c88004462101024020022802bc8004450d0020022802b8800410190b02402001450d002004ad4220862033ad84210b410721040c180b20024103410220011b3a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a1024422021c00220022903082111200228021021122004450d10410421c102200520044104746a21c202411021c302410921c402410821c50241ffffffff0321c602417021c702200521c802410a2122410321010b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e0400010206060b200241146a28020020022802184621010240200228020c450d00200228020810190b2001450d032017ad4220862015ad84210b410c21040cdc010b200241c480046a28020020022802c88004462101024020022802bc8004450d0020022802b8800410190b2001450d01201dad422086201bad84210b410a21040cdb010b2023203646210102402037450d00203810190b2001450d0220b202ad42208620b102ad84210b410b21040cda010b20024103410220011b3a00a88004411421c902200241206a41146a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a1024422021ca022002290308210e2002280210210f201d450d03411c21cb022005201d411c6c6a21cc02410c21cd02410821ce02410421cf02411021d002410921d10241ffffffff0321d202417021d302200521d402410b21220cb7010b20024103410220011b3a00a88004411421d502200241206a41146a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241b880046a200241206a1024422021d60220022903b88004210b20022802c08004210c2017450d04411c21d70220052017411c6c6a21d802410c21d902410821da02410421db02411021dc02410921dd0241ffffffff0321de02417021df02200521e002410c21220cb8010b20024103410220011b3a0008411421e102200241206a41146a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a1024422021e20220022903b88004210920022802c08004211420b202450d05411821e302200520b20241186c6a21e402410421e502411021e602410c21e702410921e802410821e90241ffffffff0321ea02417021eb02200521ec02410d21220cb9010b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020220e1100020105060708090a1113181a1c20244d4d0b2017225720426a2117410021014100212003404100210a200120434b0d122047280200225820452802002204460d14200420426a210320042048460d7220582003490d73200228020820046a2d0000210420452003360200200420497120012043717420207221202001204a6a21012004204b710d000b02402001204d490d00200467204c6a204e712041490d4e0b200241206a200241086a102120022802202042460d4e200241206a20446a2802002159200241206a20466a280200215a2002280224215b410021044100215c0340200420434b0d212047280200225820452802002203460d23200320426a210120032048460d880120582001490d89012002280208225d20036a2d00002103204520013602002003204971200420437174205c72215c2004204a6a21042003204b710d000b02402004204d490d00200367204c6a204e712041490d530b4100215e200241206a4100204f1094031a02400240205c450d004100215e4101215f41002103410021600340205820016b205c20606b2204204f2004204f491b2204490d36200120046a22612001490d9b0120582061490d9c01200241206a205d20016a20041095031a204520613602000240024002400240205e20036b20044f0d00200320046a22612003490ddf01205e2042742201206120612001491b22012040480ddf01205e450d01205f205e2001101a225f0d020ca1010b200420036a21610c020b2001101b225f450d9f010b2001215e0b205f20036a200241206a20041095031a205c200420606a22604d0d0220452802002101204728020021582002280208215d206121030c000b0b4101215f410021610b024020152057470d0020152042742201201520426a220420042001491b2204ad20507e2262205188a70dd9012062a722012040480dd901024002402015450d002005201520526c2001101a22050d010ca4010b2001101b2205450da3010b200421150b2005205720526c6a2201202020467622043b00012001205f3602102001205b360204200120203a0000200120546a20042053763a0000200120556a2061360200200120566a205e360200200120446a2059360200200120466a205a36020020172016490dad010cbd010b201a20656a2104201a2074460d7520082004490d762019201a6a2c00002101200241b880046a206f6a20043602004101210402400240024020012063480d00410721082001207571450d01200120767222012077470d01200241206a200241b880046a10e50220022f002520022d002720687472210120022d0024210820022802202065470d022001207871221a2068762103201a206476211a200241206a206f6a290200217d200241206a20646a28020021190c050b411821080b207e2119207f217d0c020b2001207871220420687621032004206476211a207d207983200241206a206f6a35020084217d200241206a20646a2802002119410021040c020b41012104200241013a00a880042066410136020020022067360204206920023602002002206a3702242002206b3602202002200241a880046a360200200241086a200241206a1024410521082002280208227e2119200229020c227f217d0b0b2003206874201a206c71206474722001206c71722101207da7211a20040d06024002400240207c207b470d00207b2065742204207b20656a220320032004491b2222ad206d7e2262206e88a70dd7012062a722042063480dd701207b450d012005207b206f6c2004101a22050d020c740b207b21220c010b2004101b2205450d720b2005207a6a2204201a360200200420706a20012068763a0000200420716a20013b0000200420726a2019360200200420736a20083a00000240207c20656a220120074f0d00207a206f6a217a20022802b8800421192022217b2001217c200241b880046a20646a2802002208200241b880046a206f6a280200221a470dab01410121220cbe010b207c41016a21040ce9010b201d225c2082016a211d410021014100212003404100210d20012083014b0d0920870128020022582085012802002204460d0b20042082016a21032004208801460d6b20582003490d6c20022802b8800420046a2d0000210420850120033602002004208901712001208301717420207221202001208a016a21012004208b01710d000b02402001208d01490d00200467208c016a208e0171208101490d400b200241206a200241b880046a10212002280220208201460d40200241206a2084016a22012802002160200241206a2086016a220428020021612002280224215e200241206a200241b880046a10262002280220208201460d412004280200215f2002280224215d02400240024020012802002201450d002001209601742203209601752257ad20970186226220900188a70dd6012062a72201208001480dd6012001101b2258450d990120032098016a215920582101205d210403402001200428020036020020012081016a210120042081016a210420032098016a22030d000b2059209601762082016a2104205f450d020c010b410021574104215841002104205f450d010b205d10190b0240201b205c470d00201b208201742201201b2082016a220320032001491b2201ad208f017e226220900188a70dd4012062a72203208001480dd40102400240201b450d002005201b2091016c2003101a22050d010c9a010b2003101b2205450d99010b2001211b0b2005205c2091016c6a220120202086017622033b0001200120583602102001205e360204200120203a000020012093016a2003209201763a000020012094016a200436020020012095016a205736020020012084016a206036020020012086016a2061360200201d201c490daa010cb9010b200241206a200241b880046a1031209d012802002120209f0128020021612002280224215f2002280220209b01460d23200241206a200241b880046a1031209d01280200215b209f012802002157200228022421592002280220209b01460d24200241b880046a209e016a2802002203200241b880046a209c016a225d2802002222460d252022209b016a2101202220a001460d850120032001490d860120022802b88004226020226a2d00002104205d20013602004100215e200420a1014b0d26024002400240024002400240024002400240024020040e0400030102000b4100215e41002104410021220340200420a2014b0d2120032001460d22200120a001460d7f20032001209b016a225c490d8001206020016a2d00002158205d205c360200205820a30171200420a20171742022722122200420a4016a2104205c2101205820a501710d000b4100215e0240200420a701490d0020586720a6016a20a80171209901490d550b20b70120b801460d070c080b200241206a200241b880046a10e502209f012903002162200228022421222002280220209b01460d3c4102215e20b70120b801460d060c070b20032001460d39202220b2016a215c200120a001460da5012003205c490da601206020016a2c00002104205d205c3602004100215e20044100480d3c410021582004209b017420b40171200472220420a8017120b6016a220120a1014b0d40024020010e0400020304000b410321582003205c470d040c410b20032001460d39202220b2016a2104200120a001460d900120032004490d9101206020016a2c00002101205d20043602002001209a01480d3c41072103200120b30171450d3d200120b40172220120b501470d3e200241206a200241b880046a10e502209f012903002162200228022421222002280220209b01460d414101215e20b70120b801460d040c050b410221582003205c470d020c3f0b410121580b2003205c460d3d0b202220a1016a2101205c20a001460d9e0120032001490d9f012060205c6a2d00002104410c2122200241b880046a410c6a20013602004103215e4100210302402004450d002004209b01470d3f410121030b20b70120b801470d010b20b701209b0174220120b701209b016a220420042001491b2204ad20a9017e22b90120aa0188a70dd30120b901a72201209a01480dd3010240024020b701450d00200520b70120ab016c2001101a22050d010c91010b2001101b2205450d90010b200421b7010b200520b80120ab016c6a2201205936020c20012020360208200120613602042001205f360200200120a7016a2062370200200120ac016a2022360200200120ad016a20033a0000200120ae016a20583a0000200120af016a205e3a0000200120b0016a205b360200200120b1016a2057360200201f20ab016a211f20b801209b016a220121b80120012021490daa010ce6010b20c801222020bc016a21c8012029210141002104410021030340200420bd014b0d0620252001460d08200120be01460d672025200120bc016a2229490d68202720016a2d0000222220bf0171200420bd0171742003722103200420c0016a210420292101202220c101710d000b0240200420c301490d0020226720c2016a20c4017120ba01490d3d0b024020c9012020470d00202020bc0174220120c80120c8012001491b22c901ad20c50186226220c60188a70dd2012062a7220120bb01480dd20102402020450d002005202020c701742001101a22050d010c98010b2001101b2205450d97010b2005202020c701746a200336020020c8012028490daa010ce4010b200241206a200241b880046a1031200228022020cc01460d27200241206a20ce016a280200215e20022802242161200241b880046a20ce016a2802002204200241b880046a20cd016a22222802002203460d28200320cc016a2101200320cf01460d8e0120042001490d8f01200241206a20cd016a280200215720022802b88004222020036a2d0000216020222001360200206020d0014b0d2a0240024002400240024020600e0400030102000b41002160410021584100210303402058202b4b0d1e20042001460d24200120cf01460d86012004200120cc016a225d490d8701202020016a2d0000215c2022205d360200205c20d101712058202b71742003722103205820d2016a2158205d2101205c20d301710d000b41002160205820d501490d03205c6720d4016a20d6017120ca014f0d030c530b410021584100210303402058202b4b0d1220042001460d21200120cf01460d89012004200120cc016a225d490d8a01202020016a2d0000215c2022205d360200205c20d101712058202b71742003722103205820d2016a2158205d2101205c20d301710d000b41022160205820d501490d02205c6720d4016a20d6017120ca014f0d020c4b0b410021584100210303402058202b4b0d1120042001460d21200120cf01460d7a2004200120cc016a225d490d7b202020016a2d0000215c2022205d360200205c20d101712058202b71742003722103205820d2016a2158205d2101205c20d301710d000b41032160205820d501490d01205c6720d4016a20d6017120ca014f0d010c4a0b410021584100210303402058202b4b0d1020042001460d1e200120cf01460d772004200120cc016a225d490d78202020016a2d0000215c2022205d360200205c20d101712058202b71742003722103205820d2016a2158205d2101205c20d301710d000b41012160205820d501490d00205c6720d4016a20d6017120ca01490d490b200241a880046a20ce016a2003360200200220603602ac8004200220573602a8800420022902ac80042162024020da0120db01470d0020da0120cc0174220120da0120cc016a220420042001491b2204ad20d7017e22b90120d80188a70dd10120b901a7220120cb01480dd1010240024020da01450d00200520da0120d9016c2001101a22050d010c90010b2001101b2205450d8f010b200421da010b200520db0120d9016c6a2201206237020c200120573602082001205e36020420012061360200202a20d9016a212a20db0120cc016a220121db012001202c490daa010ce2010b0240024020062032470d004101215c200241013a000820e0014101360200200220e101360204200241206a20e2016a2002360200200220e301370224200220e4013602202002200241086a360200200241b880046a200241206a1024200241b880046a20e5016a280200225820e2017621fb01205820e50176215d20022802bc8004212220022802b88004212041052104200621320c010b203220dc016a2101203220e901460d7020062001490d714101215c41172104024002400240024002400240024002400240203120326a2d0000220320ea01470d00203220eb016a21224100210441002120034020222132200420ec014b0d0220062001460d04200120e901460d6d2006200120dc016a2203490d6e203120016a2d0000225820ed0171200420ec0171742020722120203220dc016a2122200420ee016a210420032101205820ef01710d000b200420f101490d04410d210420586720f0016a20e6017120de014f0d04200321320c020b200121320c080b410f2104200121320b20fc01212020fd01212220fe0121580c020b200220dc013a000820e00120dc01360200200220e101360204200241206a20e2016a2002360200200220e301370224200220e4013602202002200241086a360200200241b880046a200241206a1024410521042006213220022802b88004222021fc0120022802bc8004222221fd01200241b880046a20e5016a280200225821fe010c010b4100210102400240024002400240024002400240024002402020450d004100215d4101216041002103034020dd0120326a20f701460d072032450d880120062032490d8901203120326a20e9016a2c0000220420df01480d08200420f40171450d03200420f50172220420e6017120f6014d0d0302402003205d470d00205d20dc01742222205d20dc016a225820582022491b222220df01480de00102400240205d450d002060205d2022101a22600d010ca8010b2022101b2260450da7010b2022215d0b206020036a200420e901733a0000203220dc016a2132200320dc016a2222210320222020490d000b203220e9016a210320602104205d21200c010b4101210441002120410021220b410021580340200120ec014b0d0220062003460d03200320e901460d88012006200320dc016a2232490d8901203120036a2d0000225c20ed0171200120ec0171742058722158200120ee016a210120322103205c20ef01710d000b200120f101490d09205c6720f0016a20e6017120de014f0d09410d2101410021ff010c030b208002212020810221222082022158200420e6017120e501744106722104205d450d060c050b410f2101410021ff01200321320c010b200220dc013a000820e00120dc01360200200220e101360204200241206a20e2016a2002360200200220e301370224200220e4013602202002200241086a360200200241b880046a200241206a102420f2012f010021830220f3012d0000218402200241b880046a20e5016a2d000021850220022802bc800421860220022802b8800421870241052101410021ff01200621320b20830221fb01208402215d208502215820860221222087022160410021034101215c2020450d070c060b200220dc013a000820e00120dc01360200200220e101360204200241206a20e2016a2002360200200220e301370224200220e4013602202002200241086a360200200241b880046a200241206a10242006213220022802b88004222021880220022802bc80042222218902200241b880046a20e5016a2802002258218a02410020e6017120e501744105722104205d0d010c020b20880221202089022122208a022158200420e6017120e501744118722104205d450d010b206010190b2020218002202221810220582182020b205820e2017621fb01205820e50176215d200420e2017621ff01200420e5017621030c030b02400240024002400240024002400240205820dc01460d0020580d014104215d0c030b20062032470d01200220dc013a000820e00120dc01360200200220e101360204200241206a20e2016a2002360200200220e301370224200220e4013602202002200241086a360200200241b880046a200241206a1024410521012006213220022802b88004228b0221880220022802bc8004228c02218902200241b880046a20e5016a280200228d02218a020c050b4104210141ceebc0002160412421224101215c20200d060c070b203220e901460d9e012006203220dc016a22ff01490d9f01203120326a2c0000220320df01480d0241062101200320f40171450d01200320f50172220320e6017120f6014d0d01200320e90173215d20ff0121320b200420e2017621ff01200420e5017621034100215c41e00021580c060b20ff0121320c020b4118210120ff012132208802218b02208902218c02208a02218d020b208d0220e20176218e02208d0220e50176218f020b208e0221fb01208f02215d208d022158208c022122208b0221604101215c2020450d010b200410190b20012104206021200b20ff0120e20174200420e6017172200320e6017120e50174722101205c0d0220f90120dc016a2104024020fa0120f901470d0020f90120dc01742203200420042003491b22fa01ad20e70186226220e80188a70dd0012062a7220320df01480dd001024020f901450d00200520f90120de01742003101a22050d010c730b2003101b2205450d720b200520f90120de01746a220320fb013b010e2003205d3a000d200320583a000c20032022360208200320203602042003200136020020f80120e2016a21f801200421f9012004202d490daa010ce0010b20b20222612094026a21b2024100210141002103034020012095024b0d0b202e2023460d0c2023209602460d6a202e20232094026a2204490d6b203820236a2d000022202097027120012095027174200372210320012098026a2101200421232020209902710d000b02402001209b02490d00202067209a026a209c0271209302490d460b4100215c200241206a4100209d021094031a024002402003450d00410021604101215e410021584100215d0340202e20046b2003205d6b2201209d022001209d02491b2201490d21200420016a22232004490d7e202e2023490d7f200241206a203820046a20011095031a0240024002400240206020586b20014f0d00205820016a22202058490dd5012060209402742204202020202004491b2204209202480dd5012060450d01205e20602004101a225e0d020c8c010b200120586a21200c020b2004101b225e450d8a010b200421600b205e20586a200241206a20011095031a202321042020215820032001205d6a225d4b0d000c020b0b4101215e2004212341002160410021200b209f02202036020020a10241003602002002205e36020820022020ad20a202862060ad8437020c4100210141002158034020012095024b0d242020205c460d25205c209602460d89012020205c2094026a2203490d8a01205e205c6a2d0000210420a102200336020020042097027120012095027174205872215820012098026a21012003215c2004209902710d000b02402001209b02490d00200467209a026a209c0271209302490d520b41002160024002402058450d004100215a410421b3024100215b0340205b22572094026a215b410021014100215c034020012095024b0d30200241086a20a4026a280200225d20a1022802002204460d3120042094026a21032004209602460da001205d2003490da1012002280208225e20046a2d0000212020a102200336020020202097027120012095027174205c72215c20012098026a21012020209902710d000b02402001209b02490d00202067209a026a209c0271209302490d560b205d2003460d57200420a3026a21012003209602460da101205d2001490da201205e20036a2c0000210420a10220013602002004209202480d5820042094027420ae02712004722204209c027120af026a220320aa024b0d594100210102400240024002400240024020030e0400010203000b41032101205a2057460d030c040b41022101205a2057460d020c030b410121010b205a2057470d010b205a209402742204205a2094026a220320032004491b2203ad20b00286226220a20288a70dd2012062a72204209202480dd20102400240205a450d0020b302205a20aa02742004101a22b3020d010ca6010b2004101b22b302450da5010b2003215a0b20b302205720aa02746a220420013a00042004205c360200205b2058490d000c020b0b410421b3024100215a4100215b0b410121204108215f410021014100210341002159034020012104200241206a200241086a10222002280220209402460d42200241b880046a20a3026a220120910220a3026a2d00003a000020022091022f00003b01b88004200241206a20a0026a280200215d200241206a209e026a280200215c20a802280200215e0240024020a5022d0000225820a602470d0020202096026a21200c010b205820ad026a20a3024b0d0020202094026a225720204f21b4022057212020b402450d500b200241206a20a3026a225720012d00003a0000200220022f01b880043b0120024020032059470d0020032094026a22012003490dd0012060200120012060491b2259ad20a90286226220a20288a70dd0012062a72201209202480dd00102402003450d00205f20042001101a225f0d010ca4010b2001101b225f450da3010b205f20046a220120583a0000200120a0026a205e360200200120a4026a205c36020020012093026a205d360200200120aa026a20572d00003a000020012094026a20022f01203b0000206020a3026a21602004209e026a210120032094026a210320200d000b209f02280200210120a10228020021200240200228020c450d00200228020810190b20202001470d5c024020b1022061470d0020b10220940274220120b1022094026a220420042001491b2204ad20ab027e226220a20288a70dcf012062a72201209202480dcf010240024020b102450d00200520b10220ac026c2001101a22050d010ca5010b2001101b2205450da4010b200421b1020b2005206120ac026c6a2201205f36020c2001205b3602082001205a360204200120b302360200200120a7026a20033602002001209e026a205936020020b2022039490daa010cb5010b207d422088a72103207b450df601200510190cf6010b205d41ff0171410874205841ff017172210320fb014110742123024020f901450d002005210403400240200441046a280200450d00200428020010190b200441106a210420f80141706a22f8010d000b0b2003202372210320fa01450deb01200510190ceb010b410f210120c9010ddb010cee010b410f211e205c0d3b0c3c0b200241013a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022802c08004210320022802bc8004212220022802b8800421044105210120c901450dec010cd9010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a102420022903082262422088a7213c200241106a280200210f2062a7213d4105211e0c370b024020bf0220b7026a2802002204450d0020bf022802042101200420ba027421040340024020012d000020bc02470d00200120b8026a28020020bd0271450d00200120ba026a28020010190b200120bb026a2101200420be026a22040d000b0b024020bf0220b8026a280200450d0020bf0220ba026a28020010190b20bf0220b5026a2101024020bf0220b9026a280200450d0020bf0228021010190b200121bf02200120b602470da4010c390b410f211820570d430c440b024020c8022802082204450d0020c8022802002101200420c1027421040340024020012d000020c402470d00200120c5026a28020020c60271450d00200120c1026a28020010190b200120c3026a2101200420c7026a22040d000b0b20c80220c3026a2101024020c80220c1026a280200450d0020c80228020010190b200121c802200120c202470da3010cd4010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022903b880042262422088a7213a200241c080046a280200210c2062a7213b4105211820570d410c420b410f211320610d540c550b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022903b880042262422088a7213e200241c080046a28020021142062a7213f4105211320610d530c540b410f2101410021600cc4010b024020d40220cd026a2802002204450d0020d4022802042101200420cf027421040340024020012d000020d102470d00200120ce026a28020020d20271450d00200120cf026a28020010190b200120d0026a2101200420d3026a22040d000b0b024020d40220ce026a280200450d0020d40220cf026a28020010190b20d40220cb026a2101024020d40220c9026a280200450d0020d40228021010190b200121d402200120cc02470d9f010b200e20ca02882109410521014100210d201b450de701200510190ce7010b024020e00220d9026a2802002204450d0020e0022802042101200420db027421040340024020012d000020dd02470d00200120da026a28020020de0271450d00200120db026a28020010190b200120dc026a2101200420df026a22040d000b0b024020e00220da026a280200450d0020e00220db026a28020010190b20e00220d7026a2101024020e00220d5026a280200450d0020e00228021010190b200121e002200120d802470d9e010b200b20d602882109410521014100210a2015450de901200510190ce9010b024020ec0220e5026a280200450d0020ec0228020010190b024020ec0220e1026a2802002204450d0020ec0228020c2101200420e5027421040340024020012d000020e802470d00200120e9026a28020020ea0271450d00200120e5026a28020010190b200120e6026a2101200420eb026a22040d000b0b20ec0220e3026a2101024020ec0220e6026a280200450d0020ec0220e7026a28020010190b200121ec02200120e402470d9d010b200920e20288210b410521134100210120b102450dd501200510190cd5010b410f21220cc2010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a1024200229020c210920022802082123410521224100215e0cc2010b024020052802082204450d0020052802002101200420ef027421040340024020012d000020f002470d00200120f1026a28020020f20271450d00200120ef026a28020010190b200120ee026a2101200420f3026a22040d000b0b200520ee026a21010240200520ef026a280200450d00200528020010190b2001210520ed022001470d9a010cbf010b410f211820590d320c330b410f21010cb9010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022903b880042262422088a7213a200241c080046a280200210c2062a7213b410521180c110b024020fe0220f6026a2802002204450d0020fe022802042101200420f9027421040340024020012d000020fb02470d00200120f7026a28020020fc0271450d00200120f9026a28020010190b200120fa026a2101200420fd026a22040d000b0b024020fe0220f7026a280200450d0020fe0220f9026a28020010190b20fe0220f4026a2101024020fe0220f8026a280200450d0020fe0228021010190b200121fe02200120f502470d97010c320b200241013a00a78004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a780046a360200200241086a200241206a10240c0c0b200241013a00a78004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a780046a360200200241086a200241206a10240c0b0b200241013a00a78004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a780046a360200200241086a200241206a10240c0a0b200241013a00a78004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a780046a360200200241086a200241206a1024200229020c210920022802082123410521010cb3010b200241013a00a78004200241cc80046a410136020020024101360204200241c880046a2002360200200242013702bc8004200241c4d6c3003602b880042002200241a780046a360200200241a880046a200241b880046a102420022903a880042262422088a7213e200241b080046a28020021142062a7213f410521132060450d3e205e101920610d400c410b200241306a280200210320612123205f210120b8010dbb010cbc010b200241306a280200210320572123205b21202059210120610db8010cb9010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a10240cb2010b41092122410021580cb5010b410f2113200228020c0d370c390b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022903b880042262422088a7213e200241c080046a28020021142062a7213f41052113200228020c0d360c380b20022002412c6a2902003703a88004200241286a28020021232002280224210120022802a88004212b20022802ac8004210320db010dac010cad010b200241013a00a78004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a780046a360200200241086a200241206a10240b200229020c21092002280208212341052101410021600ca9010b410a21010ca8010b200241013a00a78004200241cc80046a410136020020024101360204200241c880046a2002360200200242013702bc8004200241c4d6c3003602b880042002200241a780046a360200200241a880046a200241b880046a1024200241b080046a280200210c20022802ac8004213a20022802a88004213b41052118205e0d010b2059450d1f0c1e0b205f101920590d1d0c1e0b410f21130c260b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022903b880042262422088a7213e200241c080046a28020021142062a72101410521130c250b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a1024200229020c21092002280208212341052122410021580ca9010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a1024200241106a280200210420022903082162410521030c040b200241206a41086a200241306a2802003602002022418080807871215e20224180807c712158202241087621040c9f010b41182122410021580ca6010b411821030b0b200141ff017141087420037221220c9a010b410621224100215e0ca2010b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241086a200241206a10240c9d010b200241306a28020021040c97010b4100215e410021580c9f010b410d210120c9010da4010cb7010b410d211e205c0d040c050b2002280224221e410876210d200241306a280200210f2002412c6a280200213c200241206a41086a280200213d205c0d030c040b2002280224211e200241206a41106a280200210f2002412c6a280200213c200241206a41086a280200213d02402060450d0020604104742104205e21010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010190b200141106a2101200441706a22040d000b0b201e410876210d20610d010b205c450d020c010b205e1019205c450d010b411c21b5022005205c411c6c6a21b602410c21b702410821b802411421b902410421ba02411021bb02410921bc0241ffffffff0321bd02417021be02200521bf02410921220c7f0b201b450db401200510190cb4010b200241306a28020021142002412c6a280200213e200241286a280200213f200228022421132003450d0e0c0d0b02402089032081036a280200450d0020890328020010190b02402089032082036a2802002204450d0020890328020c210120042081037421040340024020012d0000208503470d0020012086036a28020020870371450d0020012081036a28020010190b20012083036a210120042088036a22040d000b0b20890320ff026a210102402089032083036a280200450d002089032084036a28020010190b20012189032001208003470d6f0c1d0b410d211820570d070c080b20022802242218410876210a200241306a280200210c2002412c6a280200213a200241206a41086a280200213b20570d060c070b410d211320610d190c1a0b410d2101410021600c8a010b410d21220c8e010b410d21182059450d010b20594104742104205b21010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010190b200141106a2101200441706a22040d000b0b4100210a0240205a450d00205b10190b2057450d010b411c21f40220052057411c6c6a21f502410c21f602410821f702411421f802410421f902411021fa02410921fb0241ffffffff0321fc02417021fd02200521fe02410f21220c7d0b2015450dac01200510190cac010b410d21010c83010b024020584109470d00205c41ffffffff0371450d00205d10190b4115213e418080c000213f410421132003450d010b205f21010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010190b200141106a2101200441706a22040d000b0b02402059450d00205f10190b205a450d0920b30210190c090b410d2113200228020c0d090c0b0b410d21130b200141087621030c050b200241013a00a88004200241346a410136020020024101360204200241306a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a102420022902bc8004216220022802b880042101410521130c030b411821130c010b410621130b0b20014108762103200441ff017141087420137221132062422088a721142062a7213e0b2003410874200141ff017172213f205a450d0020b3021019200228020c0d010c030b200228020c450d020b200228020810190c010b200220aa0220a30220202001461b3a00a88004200241346a410136020020024101360204200241206a41106a200236020020024201370224200241c4d6c3003602202002200241a880046a360200200241b880046a200241206a1024200241b880046a41086a280200211420022802bc8004213e20022802b88004213f02402003450d00200441106a21034100210103400240205f20016a22042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010190b2003200141106a2201470d000b0b02402059450d00205f10190b41052113205a0d010b2061450d020c010b20b30210192061450d010b411821ff022005206141186c6a218003410421810341142182034110218303410c2184034109218503410821860341ffffffff0321870341702188032005218903411021220c6b0b20b102450d8601200510190c86010b417f200141016a1027000b200141016a20061028000b417f200141016a1027000b200141016a20251028000b417f20031027000b200320581028000b417f20031027000b200320581028000b417f202341016a1027000b202341016a202e1028000b20044104101c000b417f20041027000b200420081028000b417f20011027000b200120061028000b20034104101c000b417f200141016a1027000b200141016a20031028000b417f200141016a1027000b200141016a20041028000b417f200141016a1027000b200141016a20041028000b417f20321027000b203220061028000b417f200341016a1027000b200341016a20061028000b200420231027000b2023202e1028000b417f20011027000b200120581028000b417f200141016a1027000b200141016a20041028000b417f20011027000b200120031028000b417f200141016a1027000b200141016a20041028000b20044101101c000b417f20041027000b200420031028000b417f205c41016a1027000b205c41016a20201028000b20014104101c000b20014104101c000b417f20011027000b200120041028000b200120611027000b206120581028000b20014101101c000b20014104101c000b20034104101c000b20014104101c000b20224101101c000b417f203241016a1027000b203241016a20061028000b20014104101c000b417f20011027000b200120031028000b417f205c1027000b205c20031028000b417f20031027000b2003205d1028000b417f20011027000b2001205d1028000b20044104101c000b20014108101c000b20014104101c000b410021220c120b410221220c130b410321220c130b410421220c130b410521220c130b410621220c130b410721220c130b410821220c130b410921220c140b410a21220c140b410b21220c150b410c21220c160b410d21220c170b410e21220c170b410f21220c180b411021220c190b410021010c190b410121010c180b410221010c170b410321010c160b410321010c150b410321010c140b410321010c130b410321010c120b410321010c110b410321010c100b410321010c0f0b410321010c0e0b410321010c0d0b410321010c0c0b410321010c0b0b410321010c0a0b410321010c090b410321010c080b410321010c070b410321010c060b410321010c050b410321010c040b410321010c030b410321010c020b410321010c010b410321010c000b0b101d000b200241206a41086a20043602002022418080807871215e20224180807c712158202241087621040b20022062370320200229022421092062a721230c070b20604108742001722101200220093703a880042009a7212b0240205e450d00206110190b20022802ac8004210320db01450d010b2005210403400240200441046a280200450d00200428020010190b200441146a2104202a416c6a222a0d000b0b20da01450d1b200510190c1b0b200229020c210920022802082123410521224100215e410021580c030b2033450d1320900210190c130b0b41002158410021040b202241ff0171200441ff0171410874722058418080fc077172205e7221012009422088a721032009a7212002402057450d00205910190b2061450d010b205f10190b20b801450d010b2005210403400240200441046a280200450d00200428020010190b0240200441106a280200450d002004410c6a28020010190b200441286a2104201f41586a221f0d000b0b20b701450d16200510190c160b201120c00288210941052110410021012033450d0c200510190c0c0b200510190c120b2032202f46210102402030450d00203110190b02402001450d002004ad42208620fa01ad84210b410221040c050b20024103410220011b3a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022903b88004210920022802c08004210302402004450d00200441047421042005210103400240200141046a280200450d00200128020010190b200141106a2101200441706a22040d000b0b2009422088210b410521014100210420fa01450d0e200510190c0e0b200241c480046a28020020022802c88004462104024020022802bc8004450d0020022802b8800410190b02402004450d002001ad42208620da01ad84210b410821040c040b20024103410220041b3a00a88004200241206a41146a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a1024200229030821092002280210210302402001450d00200141146c21042005210103400240200141046a280200450d00200128020010190b200141146a21012004416c6a22040d000b0b2009422088210b410521014100210420da01450d0f200510190c0f0b2029202446210102402026450d00202710190b02402001450d0020c801ad42208620c901ad84210b410421040c030b20024103410220011b3a0008200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241086a36020020022002360230200241b880046a200241206a102420022903b880042209422088210b20022802c080042103410521014100210420c901450d10200510190c100b200241c480046a28020020022802c88004462104024020022802bc8004450d0020022802b8800410190b02402004450d002001ad42208620b701ad84210b410321040c020b20024103410220041b3a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a1024200229030821092002280210210302402001450d00200141286c21042005210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101200441586a22040d000b0b2009422088210b410521014100210420b701450d11200510190c110b200241c480046a28020020022802c88004462101024020022802bc8004450d0020022802b8800410190b02402001450d002004ad4220862022ad84210b410521040c010b20024103410220011b3a00a88004200241346a41013602002002410136020420024201370224200241c4d6c3003602202002200241a880046a36020020022002360230200241086a200241206a102420022903082209422088210b2002280210210341052101410021042022450d14200510190c140b200020043a000420004100360200200041056a20022f00b880043b0000200041186a2009370200200041146a20013602002000410c6a200b370200200041086a2005360200200041206a2002290220370200200041076a200241ba80046a2d00003a0000200041286a200241206a41086a290200370200200241d080046a24000f0b2023ad422086202dad8421092025450d00200610190b20004101360200200041106a2001360200200041086a200937020020002008410874200741ff017172360204200241d080046a24000f0b20134108762101203ead220b422086203fad8421092037450d00203810190b20004101360200200041106a2014360200200041086a200b422086200942ffffffff0f838437020020002001410874201341ff017172360204200241d080046a24000f0b201041087621012034ad22094220862035ad84211120022802bc8004450d0020022802b8800410190b20004101360200200041106a2012360200200041086a2009422086201142ffffffff0f838437020020002001410874201041ff017172360204200241d080046a24000f0b200441ffffff07712204410874202541ff01717221012008ad220b4220862006ad84210920022802bc8004450d0020022802b8800410190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b200141087621042022ad220b4220862020ad8421092030450d00203110190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b20014108762104202bad220b4220862023ad84210920022802bc8004450d0020022802b8800410190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b2022ad220b4220862004ad842109410021042026450d00202710190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b200141087621042020ad220b4220862023ad84210920022802bc8004450d0020022802b8800410190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b200d410874201e41ff0171722101203cad2209422086203dad84210e20022802bc8004450d0020022802b8800410190b20004101360200200041106a200f360200200041086a2009422086200e42ffffffff0f83843702002000200d410874200141ff017172360204200241d080046a24000f0b200141ffffff07712204410874200841ff0171722101201aad220b4220862019ad84210920022802bc8004450d0020022802b8800410190b20004101360200200041106a2003360200200041086a200b422086200942ffffffff0f838437020020002004410874200141ff017172360204200241d080046a24000f0b200a410874201841ff0171722101203aad2209422086203bad84210b200228020c450d00200228020810190b20004101360200200041106a200c360200200041086a2009422086200b42ffffffff0f83843702002000200a410874200141ff017172360204200241d080046a24000f0b200241d080046a24000b160020002001280208360204200020012802003602000bf30f01347f0240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00002201410d4b0d00024020010e0e000203040506070809140a0b0c0d000b200041086a280200450d13200041046a28020010190f0b0240200041086a280200450d00200041046a28020010190b0240200041146a2802002201450d00200041186a280200450d00200110190b200041246a280200450d12200041206a28020010190f0b0240200041086a280200450d00200041046a28020010190b200041146a280200450d11200041106a28020010190f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d00200128020010190b200141106a2101200241706a22020d000b0b200041086a280200450d10200041046a28020010190f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101200241586a22020d000b0b200041086a280200450d0f200041046a28020010190f0b200041086a280200450d0e200041046a28020010190f0b200041086a280200450d0d200041046a28020010190f0b200041086a280200450d0c200041046a28020010190f0b2000410c6a2802002201450d0a41042103200041046a280200220420014104746a210541102106410921074108210841ffffffff0321094170210a410021010c050b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d00200128020010190b200141146a21012002416c6a22020d000b0b200041086a280200450d0a200041046a28020010190f0b410c210b2000410c6a2802002201450d07411c210c4104210d200041046a280200220e2001411c6c6a210f4108211041142111411021124109211341ffffffff03211441702115410121010c030b410c21162000410c6a2802002201450d054118211741042118200041046a2802002219200141186c6a211a4114211b4110211c4109211d4108211e41ffffffff03211f41702120410221010c020b410c21212000410c6a2802002201450d03411c212241042123200041046a28020022242001411c6c6a21254108212641142127411021284109212941ffffffff03212a4170212b410321010c010b024002400240200041046a2d000022014102460d0020014101460d0120010d022000410c6a280200450d09200041086a28020010190f0b200041146a2802002201450d03410c212c2000410c6a280200222d20014104746a212e4110212f410821304104213141742132410421010c020b0240200041146a2802002202450d002000410c6a28020021012002410c6c21020340024020012802002206450d00200141046a280200450d00200610190b2001410c6a2101200241746a22020d000b0b200041106a280200450d072000410c6a28020010190f0b2000410c6a280200450d06200041086a28020010190f0b0340024002400240024002400240024002400240024020010e050001020304040b024020042802082202450d0020042802002101200220037421020340024020012d00002007470d00200120086a280200200971450d00200120036a28020010190b200120066a21012002200a6a22020d000b0b200420066a21010240200420036a280200450d00200428020010190b2001210420012005470d040c0e0b0240200e200b6a2802002202450d00200e28020421012002200d7421020340024020012d00002013470d00200120106a280200201471450d002001200d6a28020010190b200120126a2101200220156a22020d000b0b0240200e20106a280200450d00200e200d6a28020010190b200e200c6a21010240200e20116a280200450d00200e28021010190b2001210e2001200f470d040c0c0b0240201920186a280200450d00201928020010190b02402019201b6a2802002202450d00201928020c2101200220187421020340024020012d0000201d470d002001201e6a280200201f71450d00200120186a28020010190b2001201c6a2101200220206a22020d000b0b201920176a210102402019201c6a280200450d00201920166a28020010190b200121192001201a470d040c0a0b0240202420216a2802002202450d0020242802042101200220237421020340024020012d00002029470d00200120266a280200202a71450d00200120236a28020010190b200120286a21012002202b6a22020d000b0b0240202420266a280200450d00202420236a28020010190b202420226a21010240202420276a280200450d00202428021010190b2001212420012025470d040c080b202d2233202f6a212d024020332802042201450d0002402033202c6a2802002202450d002002202c6c21020340024020012802002234450d00200120316a280200450d00203410190b2001202c6a2101200220326a22020d000b0b203320306a280200450d00203320316a28020010190b202d202e470d040c060b410021010c040b410121010c030b410221010c020b410321010c010b410421010c000b0b200041106a280200450d042000410c6a28020010190c040b200041086a280200450d03200041046a28020010190f0b200041086a280200450d02200041046a28020010190f0b200041086a280200450d01200041046a28020010190f0b200041086a280200450d00200041046a28020010190f0b0bbf10070b7f017e017f017e147f017e0b7f230041a0016b2202240002400240024002402000280200220341a0c0c100460d00200028020421040c010b41ec00101b2203450d0141002104200341003b010620034100360200200341086a200241086a41e4001095031a20004100360204200020033602000b200141ff017121050c010b41ec004104101c000b41002107024003400240024002400240024002400240024020070e020001010b200341086a210820032f0106210641002107024002400240034020062007460d014100417f4101200820076a2d0000220920054b1b20092005461b2209450d02200741016a210720094101460d000b2007417f6a21060b02402004450d002004417f6a2104200320064102746a41ec006a2802002103410021070c0a0b2000200028020841016a36020820032f01062207410b4f0d01200341086a2209200641016a220a6a200920066a2209200720066b1096031a200920013a0000200341146a2207200a4103746a200720064103746a2209200341066a22072f010020066b4103741096031a20094101360200200720072f010041016a3b0100200241a0016a24000f0b200320074103746a41146a42013702000c090b41ec00101b220b450d04200b41003b0106200b4100360200200b41086a200241086a41e40010950321092003410e6a2d0000210c2003290244210d20092003410f6a200341066a220a2f010041796a22071095032109200b41146a200341cc006a2007410374109503210e200a41063b0100200b20073b0106200d422088210f02400240200641064b0d00200341086a2207200641016a22096a200720066a220a200341066a22072f010020066b1096031a200a20013a0000200341146a220a20094103746a200a20064103746a220920072f010020066b4103741096031a200941013602000c010b20092006417a6a220a6a2009200641796a22066a2209200741ffff037120066b1096031a200920013a0000200e200a4103746a200e20064103746a2209200b41066a22072f010020066b4103741096031a200941013602000b200fa72110200da721114101210a200720072f010041016a3b010020032802002212450d014104210e410a2113419c01211441002115410821164194012117410e211841c4002119410f211a4106211b4179211c41cc00211d4114211e4103211f418801212041ec002121417a2122410221234220212441ffff03212541f0002126416c212741d4002128200341046a2f0100212920122f01062207410a4b0d060c020b2014101b2208450d02200820153b010620082015360200200820166a200241086a20171095032106201220186a2d0000212a201220196a290200210d20062012201a6a2012201b6a222b2f01002209201c6a2207109503212c2008201e6a2012201d6a2007201f74109503212d200820216a201220206a200920226a222e202374109503212f202b201b3b0100200820073b01060240202e450d0041002107202f210603402006280200220920073b0104200920083602002006200e6a2106202e2007200a6a2207470d000b0b200d202488210f024002402029201b4b0d00201220166a22062029200a6a22076a200620296a2206202b2f0100220920296b222e1096031a2006200c3a00002012201e6a22062007201f746a20062029201f746a2206202e201f741096031a2006201136020020062010360204202b2009200a6a22063b0100201220216a22092029202374222b6a20166a200920072023746a222e2006202571220920076b2023741096031a202e200b360200202920094f0d012012202b6a20266a21070340200728020022062029200a6a22293b0104200620123602002007200e6a210720092029470d000c020b0b202c202920226a22066a202c2029201c6a22076a222e2008201b6a22092f010020076b1096031a202e200c3a0000202d2006201f746a202d2007201f746a222e20092f010020076b201f741096031a202e2011360200202e2010360204200920092f0100200a6a222e3b0100202f2029202374222b6a20276a202f20062023746a2209202e202571222920066b2023741096031a2009200b360200200620294b0d002008202b6a20286a21060340200628020022092007200a6a22073b0104200920083602002006200e6a210620292007470d000b0b200da72111200fa72110024020122802002207450d00202a210c2008210b2012200e6a2f01002129200722122f0106220720134d0d02410121070c070b2008210b202a210c0b419c01101b2207450d03200741003b010620074100360200200741086a200241086a419401109503210920072000280200220636026c200020073602002000200028020441016a360204200641003b010420062007360200200720072f010622064103746a220a41186a2010360200200a41146a2011360200200920066a200c3a0000200741ec006a200641016a22064102746a200b360200200720063b0106200b20063b0104200b2007360200200241a0016a24000f0b201241086a2209202941016a22066a200920296a2209200720296b220a1096031a2009200c3a0000201241146a220920064103746a200920294103746a2209200a4103741096031a2009201136020020092010360204201241066a200741016a22073b0100201241ec006a220920294102746a41086a200920064102746a2209200741ffff0371220a20066b4102741096031a2009200b3602002029200a4f0d0520122006417f6a22074102746a41f0006a2106034020062802002209200741016a22073b010420092012360200200641046a2106200a2007470d000c060b0b419c014104101c000b41ec004104101c000b419c014104101c000b410121070c000b0b200241a0016a24000b8f4701af017f230041f0016b2202240020024184016a4200370200200241fc006a4280808080c000370200200241ec006a4200370200200241e4006a4280808080c000370200200241d0006a4200370300200241c0006a4200370300200241386a4280808080c000370300200241286a4200370300200241206a4280808080c000370300200241106a4200370300200242043702742002420437025c20024204370348200242043703302002420437031820024280808080c000370308200242043703002001410c6a28020021032001280208210441002105024002400240200141106a2802002206450d0041012107200241c0016a410172210841002109417f210a412c210b4109210c4108210d20024190016a41086a210e4111210f20024190016a41106a2110411921114118211220024190016a41186a21134121211420024190016a41206a21154127211620024190016a41276a2117410f2118417e2119410a211a410d211b4114211c200241c0016a41146a211d200241e4016a211e200241c0016a410c6a211f411c21204104212141ffffffff03212241702123410221244174212541582126416c212741002128410021294100212a4100212b4100212c4100212d4100212e4100212f4100213041002131410021320c010b4100210941002128410021294100212a4100212b4100212c4100212d4100212e4100212f4100213041002131410021010c010b410121010b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e020001010b410421820120022802002183010240200241086a2802002201450d0020014104742132208301210103400240200141046a280200450d00200128020010190b200141106a2101203241706a22320d000b0b02402002280204450d0020830110190b2002410c6a2802002183010240200241146a2802002201450d00200141286c2132208301210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101203241586a22320d000b0b0240200241106a280200450d0020830110190b02402002411c6a280200450d00200241186a28020010190b0240200241286a280200450d00200241246a28020010190b0240200241346a280200450d00200241306a28020010190b2002413c6a280200218301200241c4006a2802002201450d01410421840120830120014104746a21850141102186014109218701410821880141ffffffff032189014170218a01208301218b01410121320c2d0b0240024020320e050001030507070b200e20042006200a6a2206200b6c6a2201200c6a29000037030020102001200f6a2900003703002013200120116a2900003703002015200120146a2900003703002017200141286a2800003600002002200129000137039001024020012d000022332018460d0020082002290390013700002008200d6a200e290300370000200841106a2010290300370000200820126a2013290300370000200841206a2015290300370000200820166a2017280000360000200220333a00c00141012134203320196a2235201a4b22360d3c02400240024002400240024002400240024002400240024002400240024002400240024020350e0b000102030405060708090a000b201f2802002137200241c0016a200d6a280200213820022802c40121392030450d0a0240203a450d00203a202174213b2030210103400240200120216a280200450d00200128020010190b200141106a2101203b20236a223b0d000b0b4100213b0240203c450d00203010190b2037213a2038213c203921300c4e0b201f2802002137200241c0016a200d6a280200213820022802c4012139202f450d0a0240203d450d00203d41286c213b202f210103400240200120216a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101203b20266a223b0d000b0b4100213e0240203f450d00202f10190b2037213d2038213f2039212f4101213b0c4e0b201f2802002140200241c0016a200d6a280200210120022802c401213302402041450d00202e450d00202e10190b2033212e2001214120060d200c2f0b201f2802002142200241c0016a200d6a280200210120022802c401213302402043450d00202d450d00202d10190b2033212d2001214320060d1e0c2d0b201f2802002144200241c0016a200d6a280200210120022802c401213302402045450d00202c450d00202c10190b2033212c2001214520060d1c0c2b0b201f2802002146200241c0016a200d6a280200214720022802c4012148202b450d072049450d42202b20492021746a214a202b214b4100214c0c4b0b201f2802002137200241c0016a200d6a280200213820022802c4012139202a450d0702402052450d002052201c6c213b202a210103400240200120216a280200450d00200128020010190b2001201c6a2101203b20276a223b0d000b0b4100214f02402053450d00202a10190b20372152203821532039212a4101213b4101213e4101214d41012150410121512036450d430c420b4101213120022802c401215420060d130c220b201f2802002155200241c0016a200d6a280200215620022802c40121572029450d062058450d422029205820206c6a21592029215a4101214c0c490b201f280200215c200241c0016a200d6a280200215d20022802c401215e2028450d06205f450d422028205f20126c6a2160202821614102214c0c490b201f2802002163200241c0016a200d6a280200216420022802c40121652009450d062066450d422009206620206c6a2167200921684103214c0c490b203921302038213c2037213a20060d190c280b2039212f2038213f2037213d20060d170c260b2048212b2047214e2046214920060d120c210b2039212a203821532037215220060d100c1f0b205721292056215b2055215820060d0e0c1d0b205e2128205d2162205c215f20060d0c0c1b0b20652109206421692063216620060d0a0c190b20062105410021010c430b0240208b012802082232450d00208b01280200210120322084017421320340024020012d0000208701470d0020012088016a28020020890171450d0020012084016a28020010190b20012086016a21012032208a016a22320d000b0b208b012086016a21010240208b012084016a280200450d00208b0128020010190b2001218b012001208501470d120b0240200241c0006a280200450d0020830110190b200241c8006a280200218c010240200241d0006a2802002201450d00200141146c2132208c01210103400240200141046a280200450d00200128020010190b200141146a21012032416c6a22320d000b0b0240200241cc006a280200450d00208c0110190b200241dc006a280200218c01200241e4006a2802002201450d01411c218d01208c012001411c6c6a218e01410c218f014108219001411421910141042192014110219301410921940141ffffffff032195014170219601208c01219701410221320c2d0b0240209701208f016a2802002232450d00209701280204210120322092017421320340024020012d0000209401470d0020012090016a28020020950171450d0020012092016a28020010190b20012093016a210120322096016a22320d000b0b02402097012090016a280200450d002097012092016a28020010190b209701208d016a210102402097012091016a280200450d0020970128021010190b20012197012001208e01470d110b0240200241e0006a280200450d00208c0110190b200241e8006a280200219801200241f0006a2802002201450d014118219901209801200141186c6a219a014104219b014114219c014110219d01410c219e014109219f01410821a00141ffffffff0321a101417021a20120980121a301410321320c2d0b024020a301209b016a280200450d0020a30128020010190b024020a301209c016a2802002232450d0020a30128020c21012032209b017421320340024020012d0000209f01470d00200120a0016a28020020a10171450d002001209b016a28020010190b2001209d016a2101203220a2016a22320d000b0b20a3012099016a2101024020a301209d016a280200450d0020a301209e016a28020010190b200121a3012001209a01470d100b0240200241ec006a280200450d0020980110190b41800121a401200241f4006a28020021a501200241fc006a2802002201450d01411c21a60120a5012001411c6c6a21a701410c21a801410821a901411421aa01410421ab01411021ac01410921ad0141ffffffff0321ae01417021af0120a50121b001410421320c2d0b024020b00120a8016a2802002232450d0020b0012802042101203220ab017421320340024020012d000020ad01470d00200120a9016a28020020ae0171450d00200120ab016a28020010190b200120ac016a2101203220af016a22320d000b0b024020b00120a9016a280200450d0020b00120ab016a28020010190b20b00120a6016a2101024020b00120aa016a280200450d0020b00128021010190b200121b001200120a701470d0f0b200220a4016a21010240200241f8006a280200450d0020a50110190b2066410020091b21322069410020091b218601205f410020281b218a012062410020281b2187012058410020291b219d01205b410020291b21960120524100202a1b21940120534100202a1b21930120494100202b1b21a201204e4100202b1b219f0120444100202c1b21af0120454100202c1b21ad0120424100202d1b21ac0120434100202d1b21890120404100202e1b21880120414100202e1b218301203d4100202f1b219001203f4100202f1b21a901203a410020301b219501203c410020301b218401200920820120091b21a101202820820120281b21a001202920820120291b21ae01202a208201202a1b219201202b208201202b1b218b01202c208201202c1b219b01202d208201202d1b219701202e208201202e1b21ab01202f208201202f1b21a301203020820120301b21b001200110ff02024020024184016a2201280200450d0020024180016a28020010190b20024188016a20053602002001200336020020024180016a2004360200200241fc006a2032360200200241f8006a208601360200200241f4006a20a101360200200241f0006a208a01360200200241ec006a208701360200200241e8006a20a001360200200241e4006a209d01360200200241e0006a209601360200200241dc006a20ae01360200200241d8006a2054360200200241d4006a2031360200200241d0006a209401360200200241cc006a209301360200200241c8006a209201360200200241c4006a20a201360200200241c0006a209f013602002002413c6a208b01360200200241386a20af01360200200241346a20ad01360200200241306a209b013602002002412c6a20ac01360200200241286a208901360200200241246a209701360200200241206a2088013602002002411c6a208301360200200241186a20ab01360200200241146a209001360200200241106a20a9013602002002410c6a20a301360200200241086a2095013602002002208401360204200220b00136020020002002418c011095031a200241f0016a24000f0b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410021320c190b410121320c1a0b410221320c1b0b410321320c1c0b410421320c1d0b410021010c2b0b410021010c2a0b410021010c290b410021010c280b410021010c270b410021010c260b410021010c250b410021010c240b410021010c230b410021010c220b410021010c210b410121010c200b410121010c1f0b410121010c1e0b410121010c1d0b410121010c1c0b410121010c1b0b410121010c1a0b410121010c190b410121010c180b410121010c170b410121010c160b410121010c150b410121010c140b410121010c130b410121010c120b410121010c110b410121010c100b410121010c0f0b410121010c0e0b410021010c0c0b410821010c0b0b410121010c0a0b410221010c090b410321010c080b410421010c070b410521010c060b410621010c050b410721010c040b410921010c030b410921010c020b410921010c010b410921010b0340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e0a00010203040f10111234340b4100214d0240204e450d00202b10190b204621492047214e2048212b4101213b4101213e4101214f410121504101215120360d70410121010c87010b024020350e0b00040506070809720a0b0c000b203b450d4220022802c40121360240201f2802002201450d00200120217421332036210103400240200120216a280200450d00200128020010190b200141106a2101203320236a22330d000b0b200241c0016a200d6a280200450d422036101920060d160c210b410021500240205b450d00202910190b205521582056215b205721294101213b4101213e4101214d4101214f410121512036450d6d0c6c0b4100215102402062450d00202810190b205c215f205d2162205e21284101213b4101213e4101214d4101214f410121502036450d6a0c690b410021342069450d09200910192063216620642169206521094101213b4101213e4101214d4101214f4101215041012151410021342036450d670c660b203e450d3e20022802c40121360240201f2802002201450d00200141286c21332036210103400240200120216a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101203320266a22330d000b0b200241c0016a200d6a280200450d3e2036101920060d110c1c0b200241c0016a200d6a280200450d3d20022802c401101920060d0f0c1a0b200241c0016a200d6a280200450d3c20022802c401101920060d0d0c180b200241c0016a200d6a280200450d3b20022802c401101920060d0b0c160b204d450d3a20022802c401216a201f2802002201450d2b206a20012021746a216b206a216c4104214c0c6e0b204f450d3920022802c40121360240201f2802002201450d002001201c6c21332036210103400240200120216a280200450d00200128020010190b2001201c6a2101203320276a22330d000b0b200241c0016a200d6a280200450d392036101920060d080c130b2050450d3820022802c401216d201f2802002201450d2b206d200120206c6a216e206d216f4105214c0c6e0b2051450d3720022802c4012170201f2802002201450d2c2070200120126c6a2171207021724106214c0c6f0b2034450d3620022802c4012173201f2802002201450d2d2073200120206c6a2174207321754107214c0c700b206321662064216920652109410521010c790b4101213b410621010c780b4101213e410721010c770b4101214d4101214f41012150410121512036450d60410821010c760b024002400240024002402033201b4b0d000240024020330e0e0001020202020202023803040506000b200241c0016a200d6a280200450d3720022802c401101920060d0f0c1a0b0240200241c0016a200d6a280200450d0020022802c40110190b201d280200450d36200241c0016a41106a280200101920060d0d0c180b0240200241c0016a200d6a280200450d0020022802c40110190b0240201d2802002201450d00200241c0016a20126a280200450d00200110190b201e280200450d35200241c0016a41206a280200101920060d0e0c190b20022802c4012176201f2802002201450d2d2076200120206c6a2177207621784108214c0c700b20022802c4012179201f2802002201450d2e2079200120126c6a217a2079217b4109214c0c710b20022802c401217c201f2802002201450d2f207c200120206c6a217d207c217e410a214c0c720b02400240024020022d00c40122012024460d0020012007460d0120010d02201f280200450d34200241c0016a200d6a280200101920060d0a0c150b201f280200217f201d2802002201450d32207f20012021746a218001207f218101410b214c0c750b201f28020021350240201d2802002201450d002001410c6c2133203521010340024020012802002236450d00200120216a280200450d00203610190b2001410c6a2101203320256a22330d000b0b200241c0016a41106a280200450d322035101920060d070c120b201f280200450d31200241c0016a200d6a28020010190c310b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021320c150b410021010c6a0b410021010c690b410021010c680b410021010c670b410021010c660b410021010c650b410021010c640b410021010c630b410021010c620b410021010c610b410021010c600b410121010c5f0b410121010c5e0b410121010c5d0b410121010c5c0b410121010c5b0b410121010c5a0b410121010c590b410121010c580b410121010c570b410121010c560b410121010c550b02400240024002400240204c0e0c000102030406080a0c0e1012120b0240204b2802082237450d00204b2802002101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b204b41106a21010240204b20216a280200450d00204b28020010190b2001214b2001204a470d2e410021010c570b0240205a410c6a2802002237450d00205a2802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b0240205a200d6a280200450d00205a20216a28020010190b205a20206a21010240205a201c6a280200450d00205a28021010190b2001215a20012059470d2e410221010c560b0240206120216a280200450d00206128020010190b02402061201c6a2802002237450d00206128020c2101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b206120126a21010240206141106a280200450d002061410c6a28020010190b2001216120012060470d2e410321010c550b02402068410c6a2802002237450d0020682802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b02402068200d6a280200450d00206820216a28020010190b206820206a210102402068201c6a280200450d00206828021010190b2001216820012067470d2e410421010c540b0240206c2802082237450d00206c2802002101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b206c41106a21010240206c20216a280200450d00206c28020010190b2001216c2001206b470d2e0b200241c0016a200d6a280200450d0e206a101920060d120c1b0b0240206f410c6a2802002237450d00206f2802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b0240206f200d6a280200450d00206f20216a28020010190b206f20206a21010240206f201c6a280200450d00206f28021010190b2001216f2001206e470d2d0b200241c0016a200d6a280200450d0c206d101920060d0f0c180b0240207220216a280200450d00207228020010190b02402072201c6a2802002237450d00207228020c2101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b207220126a21010240207241106a280200450d002072410c6a28020010190b2001217220012071470d2c0b200241c0016a200d6a280200450d0a2070101920060d0c0c150b02402075410c6a2802002237450d0020752802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b02402075200d6a280200450d00207520216a28020010190b207520206a210102402075201c6a280200450d00207528021010190b2001217520012074470d2b0b200241c0016a200d6a280200450d082073101920060d090c120b02402078410c6a2802002237450d0020782802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b02402078200d6a280200450d00207820216a28020010190b207820206a210102402078201c6a280200450d00207828021010190b2001217820012077470d2a0b200241c0016a200d6a280200450d062076101920060d0b0c140b0240207b20216a280200450d00207b28020010190b0240207b201c6a2802002237450d00207b28020c2101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b207b20126a21010240207b41106a280200450d00207b410c6a28020010190b2001217b2001207a470d290b200241c0016a200d6a280200450d042079101920060d0a0c130b0240207e410c6a2802002237450d00207e2802042101203720217421370340024020012d0000200c470d002001200d6a280200202271450d00200120216a28020010190b200141106a2101203720236a22370d000b0b0240207e200d6a280200450d00207e20216a28020010190b207e20206a21010240207e201c6a280200450d00207e28021010190b2001217e2001207d470d280b200241c0016a200d6a280200450d02207c101920060d090c120b208101223941106a218101024020392802042201450d0002402039410c6a2802002237450d002037410c6c21370340024020012802002238450d00200120216a280200450d00203810190b2001410c6a2101203720256a22370d000b0b2039200d6a280200450d00203920216a28020010190b208101208001470d270b200241c0016a41106a280200450d00207f101920060d080c110b2006450d08410021320c110b410021320c110b410021320c110b410021320c110b410021320c110b410021320c110b410021320c110b410021320c110b410021320c110b410021010c3b0b410021010c3a0b410021010c390b410021010c380b410021010c370b410021010c360b410021010c350b410021010c340b410021010c330b410121010c320b410121010c310b410121010c300b410121010c2f0b410121010c2e0b410121010c2d0b410121010c2c0b410121010c2b0b410121010c2a0b4100214c0c140b4101214c0c140b4102214c0c140b4103214c0c140b4104214c0c150b4105214c0c160b4106214c0c170b4107214c0c180b4108214c0c190b4109214c0c1a0b410a214c0c1b0b410b214c0c1c0b410821010c1c0b410121010c1b0b410821010c1a0b410121010c190b410821010c180b410121010c170b410821010c160b410121010c150b410821010c140b410921010c130b410921010c120b410921010c110b410921010c100b410921010c0f0b410921010c0e0b410921010c0d0b410921010c0c0b410921010c0b0b410921010c0a0b410921010c090b410921010c080b410921010c070b410921010c060b410921010c050b410921010c040b410921010c030b410921010c020b410921010c010b410921010c000b0b0b9a0c02297f017e230041106b22022400024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042101200241086a200010d20220022802082208200228020c22094104746a210a4100210b20094104490d0141ff01210c200341ff0171210d4101210e410d210f411c211041182111411d2112412c21134128211441202115412d2116413c211741c0002118413821194130211a413d211b413f211c4101211d0c020b20012802042104200241106a240020040f0b410021090c010b410121090b02400240024003400240024002400240024002400240024002400240024002400240024002400240024020090e020001010b2008200a460d01410421210240200741ff017122224104470d0041102123200341ff0171212441012125410d21264100211d0c0c0b41102127200341ff0171212841012129410d212a4102211d0c0f0b024002400240201d0e03010002020b024020082d000c200d470d0020082802082004470d002008280200211e4100210902400340200920044f0d01200120096a211f201e20096a21202009200e6a210920202d0000201f2d0000460d000c020b0b2007200c71220941044622202008200f6a2d0000221f410446221e470d00201f2009460d0720200d07201e0d070b0240200820106a2d0000200d470d00200820116a2802002004470d00200841106a280200211e4100210902400340200920044f0d01200120096a211f201e20096a21202009200e6a210920202d0000201f2d0000460d000c020b0b2007200c7122094104462220200820126a2d0000221f410446221e470d00201f2009460d0420200d04201e0d040b0240200820136a2d0000200d470d00200820146a2802002004470d00200820156a280200211e4100210902400340200920044f0d01200120096a211f201e20096a21202009200e6a210920202d0000201f2d0000460d000c020b0b2007200c7122094104462220200820166a2d0000221f410446221e470d00201f2009460d0520200d05201e0d050b0240200820176a2d0000200d470d00200820196a2802002004470d002008201a6a280200211e4100210902400340200920044f0d01200120096a211f201e20096a21202009200e6a210920202d0000201f2d0000460d000c020b0b2007200c71220941044622202008201b6a2d0000221f410446221e470d00201f2009460d0620200d06201e0d060b200b41046a210b200a200820186a22086b201c4b0d0a410021090c110b024020082d000c2024470d0020082802082004470d00200828020021204100210902400340200920044f0d01200120096a211d202020096a211f200920256a2109201f2d0000201d2d0000460d000c020b0b200820266a2d00002021460d060b200b20256a210b200820236a2208200a470d080c010b024020082d000c2028470d0020082802082004470d00200828020021204100210902400340200920044f0d01200120096a211d202020096a211f200920296a2109201f2d0000201d2d0000460d000c020b0b2008202a6a2d000022092022470d0020092021470d050b200b20296a210b200820276a2208200a470d090b024002400240200041046a28020020002802082208470d00200841016a22092008490d082008410174220e20092009200e491b220ead420486222b422088a70d08202ba7221d4100480d082008450d0120002802002008410474201d101a2209450d020c120b200028020021090c120b201d101b22090d100b201d4104101c000b200b410172210b20050d030c100b200b410272210b20050d020c0f0b200b410372210b0b2005450d0d0b20011019200241106a2400200b0f0b101d000b4100211d0c030b4101211d0c030b4102211d0c030b410121090c040b410121090c030b410121090c020b410121090c010b410121090c000b0b20002009360200200041046a200e360200200041086a28020021080b200920084104746a220820063b010e200820073a000d200820033a000c200820043602082008200536020420082001360200200041086a2204200428020041016a3602002002200010d2022002280204417f6a210b0b200241106a2400200b0bac24032d7f017e2b7f230041306b220224002001280204210320012802002104410121050240024002400240024020012802082206450d00412c101b2207450d02200720022f002d3b0001200741023a00002007200636000c200720033600082007200436000420072002290208370210200741036a2002412d6a41026a2d00003a0000200741186a200241106a290200370200200741206a200241186a290200370200200741286a200241086a41186a28020036020041002108410121090c010b4104210741002109410121080b200141106a280200210a200128020c210b024002400240200141146a280200220c450d002009410174220d200941016a220e200e200d491b220d412c6c210e2009450d0120072009412c6c200e101a2207450d020c040b2009210d0c040b200e101b22070d020b200e4104101c000b412c4104101c000b20072009412c6c6a220e20022f002d3b0001200e41033a0000200e200c36000c200e200a360008200e200b360004200e2002290208370210200e41036a2002412f6a2d00003a0000200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200941016a2109410021050b2001411c6a280200210f2001280218211041002111024002400240024002400240024002400240200141206a2802002212450d00200d2009470d0441000d0641000d06200d410174220e200d41016a22132013200e491b220ead422c7ea722134100480d06200d450d012007200d412c6c2013101a2207450d020c030b410021140c040b2013101b22070d010b20134104101c000b200e210d0b20072009412c6c6a220e41043a0000200e201236000c200e200f360008200e2010360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e200229020837021041012114200941016a21090b200141286a28020021152001280224211602402001412c6a2802002212450d000240200d2009470d0041000d0241000d02200d410174220e200d41016a22132013200e491b220ead422c7ea722134100480d02024002400240200d450d002007200d412c6c2013101a2207450d010c020b2013101b22070d010b20134104101c000b200e210d0b20072009412c6c6a220e41053a0000200e201236000c200e2015360008200e2016360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e200229020837021041012111200941016a21090b200141346a280200211720012802302118024002400240024002400240200141386a2802002212450d00200d2009470d0441000d0641000d06200d410174220e200d41016a22132013200e491b220ead422c7ea722134100480d06200d450d012007200d412c6c2013101a2207450d020c030b410021190c040b2013101b22070d010b20134104101c000b200e210d0b20072009412c6c6a220e41063a0000200e201236000c200e2017360008200e2018360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e200229020837021041012119200941016a21090b200141c0006a280200211a200128023c211b4101211c024002400240024002400240200141c4006a280200221d450d00200d2009470d0441000d0641000d06200d410174220e200d41016a22122012200e491b220ead422c7ea722124100480d06200d450d012007200d412c6c2012101a2207450d020c030b4101211e0c040b2012101b22070d010b20124104101c000b200e210d0b20072009412c6c6a220e41073a0000200e201d36000c200e201a360008200e201b360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a21094100211e0b200141cc006a280200211f200128024821200240200141d0006a2802002221450d000240200d2009470d0041000d0241000d02200d410174220e200d41016a22122012200e491b220ead422c7ea722124100480d02024002400240200d450d002007200d412c6c2012101a2207450d010c020b2012101b22070d010b20124104101c000b200e210d0b20072009412c6c6a220e41083a0000200e202136000c200e201f360008200e2020360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241086a41086a290200370200200e2002290208370210200941016a21094100211c0b41012122024020012802544101470d00200141d8006a28020021120240200d2009470d0041000d0241000d02200d410174220e200d41016a22132013200e491b220ead422c7ea722134100480d02024002400240200d450d002007200d412c6c2013101a2207450d010c020b2013101b22070d010b20134104101c000b200e210d0b20072009412c6c6a220e41093a0000200e2012360204200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41206a280200360200200e41206a200241086a41186a290200370200200e41186a200241086a41106a290200370200200e41106a200241106a290200370200200e2002290208370208200941016a21090b200141e0006a2802002123200128025c21240240200141e4006a2802002225450d000240200d2009470d0041000d0241000d02200d410174220e200d41016a22122012200e491b220ead422c7ea722124100480d02024002400240200d450d002007200d412c6c2012101a2207450d010c020b2012101b22070d010b20124104101c000b200e210d0b20072009412c6c6a220e410a3a0000200e202536000c200e2023360008200e2024360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a2109410021220b200141ec006a28020021262001280268212741012128024002400240024002400240200141f0006a2802002229450d00200d2009470d0441000d0641000d06200d410174220e200d41016a22122012200e491b220ead422c7ea722124100480d06200d450d012007200d412c6c2012101a2207450d020c030b4101212a0c040b2012101b22070d010b20124104101c000b200e210d0b20072009412c6c6a220e410b3a0000200e202936000c200e2026360008200e2027360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a21094100212a0b200141f8006a2802002112200128027421130240200141fc006a280200222b450d000240200d2009470d0041000d0241000d02200d410174220e200d41016a22282028200e491b220ead422c7ea722284100480d02024002400240200d450d002007200d412c6c2028101a2207450d010c020b2028101b22070d010b20284104101c000b200e210d0b20072009412c6c6a220e410c3a0000200e202b36000c200e2012360008200e2013360004200e41036a2002412f6a2d00003a0000200e20022f002d3b0001200e41286a200241086a41186a280200360200200e41206a200241186a290200370200200e41186a200241106a290200370200200e2002290208370210200941016a2109410021280b20014184016a280200212c200128028001210e024002400240200d20096b20014188016a280200412c6c222d412c6d22014f0d00200920016a22012009490d03200d410174222e20012001202e491b222ead422c7e222f422088a70d03202fa722304100480d03200d450d012007200d412c6c2030101a2207450d020c040b200920016a21010c040b2030101b22070d020b20304104101c000b101d000b202e210d0b20072009412c6c6a200e202d1095031a0240202c450d00200e10190b0240024002400240024041c005101b2209450d002000200736020820004280c2cdeb16370200200241086a410c6a4210370200200041106a20013602002000410c6a200d3602002002200936021020024280c2cdeb16370308200241106a10ff02200910192028450d02202b450d01411c21312013202b411c6c6a2132410c2133410821344114213541042136411021374109213841ffffffff0321394170213a2013213b4100213c0c030b41c0054104101c000b410021010c020b410121010c010b410221010b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020010e03000102020b2012450d0e20131019410121010c160b202a450d022029450d014118213d2027202941186c6a213e4104213f4114214041102141410c2142410921434108214441ffffffff03214541702146202721474101213c0c0f0b02400240203c0e0400010407070b0240203b20336a2802002209450d00203b2802042101200920367421090340024020012d00002038470d00200120346a280200203971450d00200120366a28020010190b200120376a21012009203a6a22090d000b0b0240203b20346a280200450d00203b20366a28020010190b203b20316a21010240203b20356a280200450d00203b28021010190b2001213b20012032470d09410021010c150b02402047203f6a280200450d00204728020010190b0240204720406a2802002209450d00204728020c21012009203f7421090340024020012d00002043470d00200120446a280200204571450d002001203f6a28020010190b200120416a2101200920466a22090d000b0b2047203d6a21010240204720416a280200450d00204720426a28020010190b200121472001203e470d090b2026450d00202710190b2022450d022025450d01411c214820242025411c6c6a2149410c214a4108214b4114214c4104214d4110214e4109214f41ffffffff03215041702151202421524102213c0c0e0b02402052204a6a2802002209450d00205228020421012009204d7421090340024020012d0000204f470d002001204b6a280200205071450d002001204d6a28020010190b2001204e6a2101200920516a22090d000b0b02402052204b6a280200450d002052204d6a28020010190b205220486a210102402052204c6a280200450d00205228021010190b2001215220012049470d070b2023450d00202410190b0240201c450d0002402021450d00202141146c21092020210103400240200141046a280200450d00200128020010190b200141146a21012009416c6a22090d000b0b201f450d00202010190b201e450d02201d450d0141042153201b201d4104746a215441102155410921564108215741ffffffff03215841702159201b215a4103213c0c0d0b0240205a2802082209450d00205a2802002101200920537421090340024020012d00002056470d00200120576a280200205871450d00200120536a28020010190b200120556a2101200920596a22090d000b0b205a20556a21010240205a20536a280200450d00205a28020010190b2001215a20012054470d050b201a450d00201b10190b02402017410047201941017371450d00201810190b02402015410047201141017371450d00201610190b0240200f410047201441017371450d00201010190b02402005450d000240200c450d00200c41286c2109200b210103400240200141046a280200450d00200128020010190b0240200141106a280200450d002001410c6a28020010190b200141286a2101200941586a22090d000b0b200a450d00200b10190b02402008450d0002402006450d00200641047421092004210103400240200141046a280200450d00200128020010190b200141106a2101200941706a22090d000b0b2003450d00200410190b200241306a24000f0b4100213c0c040b4101213c0c050b4102213c0c060b4103213c0c070b410121010c070b410221010c060b410221010c050b410221010c040b410221010c030b410221010c020b410221010c010b410221010c000b0bb505000240024002400240024002400240024002400240200041ff0171417f6a220041aa014b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020000eab014a00000000000000000000000000010101010103030404050506060707080809094b0a0a0b0b0c0c0d0d4c4d0e0e0f0f10101111121213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f20204e212122224f2323242450252526262727282829292a2a512b2b2c2c2d2d2e2e2f2f30303131323233333434353536363737383839393a3a3b3b3c3c3d3d3e3e523f3f404041414242434344444545464647474848020202024a0b410a0f0b41080f0b41100f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41050f0b41050f0b41050f0b41050f0b41060f0b41070f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b41000f0b41010f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b41000f0b41010f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410f0f0b410f0f0b410e0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b410f0f0b41110f0b41120f0b41050f0b41130f0b41140f0b41000f0b41020f0b41000f0b41020f0b410e0b800203047f017e017f024002400240200041086a28020022032001490d0002400240024002402003200041046a280200470d00200341016a22042003490d0320034101742205200420042005491b2206ad4204862207422088a70d032007a722084100480d032003450d01200028020020034104742008101a2205450d020c050b200341016a2104200028020021050c050b2008101b22050d030b20084108101c000b101d000b41fcd5c3001029000b20002005360200200041046a20063602000b200520014104746a220541106a2005200320016b4104741096031a200541086a200241086a29030037030020052002290300370300200041086a20043602000b9e0503057f017e017f230041306b22022400200241106a200141246a290200370300200241086a2001411c6a29020037030020022001290214370300200241186a41106a200141106a280200360200200241186a41086a200141086a290200370300200220012902003703182000200241186a10d6022103024002400240024002400240024002402000411c6a280200200041206a2802002204470d00200441016a22052004490d0520044101742206200520052006491b2206ad4202862207422088a70d052007a722084100480d052004450d01200041186a28020020044102742008101a2205450d020c030b200041186a28020021050c030b2008101b22050d010b20084104101c000b2000411c6a2006360200200041186a2005360200200041206a28020021040b200520044102746a2003360200200041206a2204200428020041016a360200200241186a41106a200241106a290300370300200241186a41086a200241086a29030037030020022002290300370318024002400240200041ec006a280200200041f0006a2802002204470d00200441016a22052004490d0320044101742203200520052003491b2203ad42187e2207422088a70d032007a722064100480d032004450d01200041e8006a280200200441186c2006101a2205450d020c040b200041e8006a28020021050c040b2006101b22050d020b20064104101c000b101d000b200041ec006a2003360200200041e8006a2005360200200041f0006a28020021040b2005200441186c6a22042002290318370200200441106a200241186a41106a290300370200200441086a200241186a41086a290300370200200041f0006a22042004280200220441016a360200024020012d002c450d0020004101360254200041d8006a20043602000b200241306a24000baa950115097f017e5a7f037e047f017e2f7f027e207f027e1f7f037e3e7f027e017f017e057f047e287f017e227f23002203210420034180096b416071220324000240024002400240024002400240024002404110101b2205450d00200541063a00004120101b2206450d01200641063a001020064100360204200620032f00c0053b00012006412d3a0000200641036a200341c2056a2d00003a0000024020052d00004109470d00200528020841ffffffff0371450d00200528020410190b20051019200141106a2802002207412c6c21052001280208220841586a210902400240024002400240024003402005450d01200541546a2105200941286a210a2009412c6a220b2109200a2d00004107470d000b200320032f01a0033b01c005200b41046a280200200b41086a2802002205470d01200541016a22092005490d0e2005410174220a20092009200a491b220aad420486220c422088a70d0e200ca722074100480d0e2005450d04200b28020020054104742007101a2209450d050c0b0b4110101b2209450d0720094180023b010c200942828080802037020420092006360200200920032f01a0033b010e2001410c6a2802002007470d09200741016a22052007490d0d2007410174220a20052005200a491b2205ad422c7e220c422088a70d0d200ca7220a4100480d0d2007450d0120082007412c6c200a101a2208450d020c080b200b28020021090c0a0b200a101b22080d060b200a4104101c000b2007101b22090d060b20074104101c000b41104108101c000b41204108101c000b41104104101c000b2001410c6a2005360200200141086a20083602000b200141106a200741016a220d36020020082007412c6c6a220520032f00b0043b0001200541073a0000200542818080801037000820052009360004200520032902c005370210200541036a200341b2046a2d00003a0000200541186a200341c8056a290200370200200541206a200341c0056a41106a290200370200200541286a200341c0056a41186a2802003602004100210e0c020b200b2009360200200b41046a200a360200200b41086a28020021050b200920054104746a22054180023b010c200542828080802037020420052006360200200520032f01c0053b010e200b41086a2205200528020041016a360200200341c0006a200b10d2022003280244417f6a210e200141106a280200210d200141086a28020021080b200d412c6c2105200841586a210902400340410021062005450d01200541546a2105200941286a210a2009412c6a220b2109200a2d00004103470d000b200b41086a2802002205450d00200541286c2109200b28020041186a2105410021060340200620052d0000456a2106200541286a2105200941586a22090d000b0b200d412c6c2105200841586a2109024003404100210a2005450d01200541546a2105200941286a210b2009412c6a22072109200b2d00004103470d000b200741086a2802002205450d00200541286c2109200728020041186a21054100210a0340200a20052d0000456a210a200541286a2105200941586a22090d000b0b200d412c6c2105200841606a21090240024003402005450d01200541546a2105200941206a210b2009412c6a22072109200b2d00004104470d000b200728020021050c010b410021050b02402005200a6a220fad220c421e88a70d00200c420286a72205417f4c0d0002400240024002400240024002402005450d00200510df012207450d02200f0d010c030b41042107200f450d030b2007200f4102746a2110410021114101211241042113200141106a2114412c211541082116200141086a211741582118415421194128211a410b211b4118211c4103211d2007211e4100211f0c030b20054104101c000b410021050c020b410021050c010b410121050b034002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e020001010b200141086a2802002121412c2123200141106a2802002220450d2a0c010b024002400240024002400240024002400240201f0e050001030405050b024020112006490d002014280200222020156c220a21052017280200222120186a220b210902400340410021082005450d01200520196a21052009201a6a210d200920156a22222109200d2d0000201d470d000b202220166a2802002205450d002005201a6c21092022280200201c6a2105410021080340200820052d0000456a21082005201a6a2105200920186a22090d000b0b201120086b220820114b0d060340200a450d03200a20196a210a200b201a6a2105200b20156a2209210b20052d0000201b470d000b200920166a28020020084d0d0720092802002008201c6c6a2802082109200341c0056a2008200110f60220032802c405210520032802c0052012460d08201e200520096a3602000b201120126a2111201e20136a221e2010470d0c410021050c360b20212d0000202a470d2f202128020c2205450d2f202128020422702005202b6c6a2171410021720c170b412c101b2205450d07200541286a41002800e9f741360000200541206a41002900e1f741370000200541186a41002900d9f741370000200541106a41002900d1f741370000200541086a41002900c9f741370000200541002900c1f7413700000c290b02400240024002400240024002400240024002400240024002400240024020ce01209a01712205209301460d002005209b01470d01208b0121d60120c80121d70120cc0121d80120cd0121d901410021050c2f0b20cd01209a01712205209b01460d012005209301470d0220ca01208f01460d31034020ca01209c016a280200450d06208f0120ca012097016a22ca01470d000c320b0b20c601209a01712205209b01460d022005209301470d03410121c60120c301208f01460d05034020c301209c016a280200450d0a208f0120c3012097016a22c301470d000b208b0121d601208f012190010c060b20cc01209301470d0a208b0120db01460d0a0c2b0b024020c901208f01460d00034020c901209c016a280200450d07208f0120c9012097016a22c901470d000b208f01219001208f0121c3010b20c801209301470d0a208b0120db01460d0a0c290b20c501209301470d16208b0120db01460d15410321050c2a0b0240209001208f01460d000340209001209c016a280200450d08208f012090012097016a229001470d000b0b20c201209301470d17208b0120db01460d16410421050c290b20ca012097016a219001410121cd01208b0121d60120ca01209d016a21050c030b208b0121d6010b208f0121c30120c80121d701208f0121c901208f0121ca0120cc0121d801410121d9012095010d170c290b20c9012097016a219001410021cd01208b0121d60120c901209d016a21050b20900121c30120900121c90120900121ca0120d601218b012003200528020022da0136027c20070d180c250b20c301209d016a2105410121c60120c3012097016a22900121c30120900121c90120900121ca01410121cd01208b0122d601218b012003200528020022da0136027c20070d150c240b209001209d016a2105410021c6012090012097016a22c30121900120c30121c90120c30121ca01410021cd01208b0122d601218b012003200528020022da0136027c20070d150c230b034020cb01209901460d25200341286a20cb0110f7022003280228228b01450d25410121c20120cb012098016a22920121c401410121c50120920121c701410121c80120920121cb01208b01208b01200328022c209b01746a22db01470d210c000b0b034020c701209901460d24200341206a20c70110f7022003280220228b01450d24410121c20120c7012098016a22920121c401410121c50120920121c70120920121cb01208b01208b012003280224209b01746a22db01470d1f0c000b0b20d401220520fb016a21d401200528020021cb02200341e0006a21cc02200328026421cd020c0e0b024020da022d0000220520dc02460d000240200520e802460d00200520e002470d2220da0228020c2205450d2220da0228020422ea02200520e9026c6a21eb02410921720c1b0b20da0228020421ef02200341e0006a21f002200328026421f1020c0f0b20da0228020c2205450d2020da0228020422f202200520dd026c6a21f302410b21720c1b0b412c101b2205450d04200541286a41002800bdf741360000200541206a41002900b5f741370000200541186a41002900adf741370000200541106a41002900a5f741370000200541086a410029009df74137000020054100290095f7413700000c250b411e101b2205450d04200541166a4100290083f841370000200541106a41002900fdf741370000200541086a41002900f5f741370000200541002900edf741370000429e808080e003210c0c250b200341c8056a290300210c2007101920050d2541002107412c21232020450d290b2021202020236c6a212441142125200341b0046a41146a2126200341b0076a212741012128200341c0056a4101722129410b212a4118212b410c212c4104212d4102212e200341a4076a212f200341a0076a21304113213120034190076a213241d700213320034184076a213420034180076a2135412d2136200341f4066a2137200341f0066a213841122139200341e4066a213a200341e0066a213b200341d0066a213c4106213d200341c0066a213e4100213f200341b0066a21404184082141200341a0066a21424137214320034194066a214420034190066a214520034184066a214620034180066a2147200341f4056a2148200341f0056a21494120214a200341c0056a41206a214b41d600214c4110214d200341c0056a41106a214e4108214f200341b0046a41086a215041ac0121514109215241ffffffff032153200341e8056a2154200341e4056a2155200341f8056a215620034188066a215720034198066a2158200341a8066a2159200341a4066a215a200341b8066a215b200341b4066a215c200341c8066a215d200341c4066a215e200341d8066a215f200341d4066a2160200341e8066a2161200341f8066a216220034188076a216320034198076a216420034194076a2165200341a8076a21664208216742042168422021694103216a4170216b41ff01216c4121216d4201216e41b4d5c300216f4101211f0c040b412c4101101c000b412c4101101c000b411e4101101c000b4100211f410121050c290b410121050c280b410321720c0a0b410421720c0a0b410521720c0a0b410621720c0a0b410721720c0a0b410a21720c0b0b410121050c0e0b410221050c0d0b410221050c0c0b410221050c0b0b410521050c0a0b410521050c090b410521050c080b410521050c070b410521050c060b410521050c050b410521050c040b410521050c030b410521050c020b208b01450d04410121c801410221c601208f0121c901208f0121ca01410121cc01410221cd01208b0128020021da01208b012091016a22d601218b01200320da0136027c2007450d02410221050c010b208b01450d03410221cd01410121cc01208b0128020021da01208b012091016a22d601218b01200320da0136027c2007450d01410221050b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e06000102030410100b209501450d3a410121050c370b410221ce01410021950120d70121c80120d80121cc0120d90121cd0120940121da01410021940120d601218b01200320da0136027c2007450d37410221050c360b200f20da014d0d06200720da01209b01746a2802002209450d0c20d00120cf01470d0520cf012093016a220520cf01490d4a20cf0120930174220a20052005200a491b22d001ad209e0186220c209f0188a70d4a200ca72205208e01480d4a20cf01450d0320d20120cf01209b01742005101a22d1010d040c090b208b012091016a21d601410221c601410121c501410121d7010c010b208b012091016a21d601410221c601410121c201208f01219001208f0121c301410121c501410121d701208f0121c901208f0121ca010b410121d801410221d901410121c801410121cc01410221cd01208b01450d11208b0128020021da0120d601218b01200320da0136027c20070d160c330b2005101b22d101450d050b20d10121d20120d10121d30120d10121d4010b20d40120cf01209b01746a20da01360200200341c0056a200328027c22dc01200341c8006a10f90220a10128020021dd0120032802c40521d50120032802c00522de01209301460d0120d501280208220520a2014c0d4320d501280200210a20d5012d000c210b024002402005450d002005101b22080d010c060b410121080b2008200a2005109503210a20d50120a3016a2d000021082003200936029c012003200328027c360298012003208e0136029001200320083a008d012003200b3a008c01200320053602880120032005360284012003200a3602800102400240200328027022df01209601460d00200328027421e0010c010b20a401101b22df01450d06410021e00120df0141003b010620df01410036020020df0120a0016a200341c0056a20a5011095031a20034100360274200320df013602700b20cf012093016a21cf010c080b200341d4056a4101360200200341023602a403200341d0056a200341a0036a360200200342023702c40520034194d6c3003602c0052003200341fc006a3602a003200341b0046a200341c0056a102420032902b404220c422088a7210920032802b00421d501200ca721dd010c010b200341c0056a209c016a28020021090b20032802702003280274200341f8006a28020010fa02024020d001450d0020d10110190b0240208c01450d00208c01412c6c218b01208d0121050340200510d3022005412c6a2105208b0141546a228b010d000b0b0240200341d4006a280200450d00208d0110190b200020d50136020420004101360200200041086a2009ad42208620dd01ad843702002007450d38200f450d3820071019200424000f0b20054104101c000b20054101101c000b4194034104101c000b4102211f410121050c3b0b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020720e0c000102060708090a0b0c0d0e0e0b207020256a22732802002274450d492070202c6a2175410021760c3d0b20df0120a0016a210a20df012f01062208209b01742109417f21050240024002400240024003402009450d0120052093016a2105208e0120a201209301200a280200220b20dc014b1b200b20dc01461b220b450d04200920bf016a2109200a2091016a210a200b209301460d000b20e0010d010c020b2008210520e001450d010b20e00120a2016a21e00120df012005209b01746a20a4016a28020021df01410121720c340b200341f0006a20a0016a220920092802002093016a360200200329039801210c20032903900121e10120032903880121e20120032903800121e30120df012f0106220920a7014f0d0120df0120a0016a220a20052093016a220b209b01746a200a2005209b01746a220a200920056b209b01741096031a200a20dc0136020020df0120a9016a2209200b20a801746a2009200520a801746a220920df0120a6016a220a2f010020056b20a801741096031a200920aa016a200c370200200920e101370210200920e201370208200920e301370200200a200a2f01002093016a3b010020de010d440c1f0b20df01200520a801746a220520b3016a200329039801370200200520b4016a220929020021e1012009200329039001370200200520b5016a200329038801370200200520a9016a2205290200210c200520032903800137020020e10120c10183209e0185500d42200c20c00183500d42200ca710190c420b20a401101b2209450d192009208e013b01062009208e01360200200920a0016a200341c0056a20a501109503210b200341c0056a20aa016a22e40120df0120ab016a290200370300200341c0056a209d016a22e50120df0120ac016a29020037030020a10120df0120ad016a290200370300200320df012902f4013703c00520df0128022021e601200b20df0120ae016a20df0120a6016a22082f010020af016a220a209b0174109503210b200920a9016a20df0120b0016a200a20a80174109503210d200820a6013b01002009200a3b0106200341b0046a20aa016a22e70120e401290300370300200341b0046a209d016a22e80120e501290300370300200341b0046a20a0016a22e90120a101290300370300200320032903c0053703b00402400240200520a6014b0d0020df0120a0016a220a20052093016a220b209b01746a200a2005209b01746a220820df0120a6016a220a2f010020056b209b01741096031a200820dc0136020020df0120a9016a2208200b20a801746a2008200520a801746a220b200a2f010020056b20a801741096031a200b20aa016a200c370200200b20e101370210200b20e201370208200b20e3013702000c010b200b200520bc016a221f209b01746a200b200520af016a2208209b01746a2205200a20b6017120086b209b01741096031a200520dc01360200200d201f20a801746a200d200820a801746a2205200920a6016a220a2f010020086b20a801741096031a200520aa016a200c370200200520e101370210200520e201370208200520e3013702000b200a200a2f01002093016a3b0100200341a0036a20aa016a22ea0120e701290300370300200341a0036a209d016a22eb0120e801290300370300200341a0036a20a0016a22ec0120e901290300370300200320032903b0043703a00320034190026a20aa016a22ed0120ea0129030037030020034190026a209d016a22ee0120eb0129030037030020034190026a20a0016a22ef0120ec01290300370300200320032903a0033703900220df0128020022f001450d0120df012f010421f101200921f2010c230b20ea0120ed0129030037030020eb0120ee0129030037030020ec0120ef0129030037030020032003290390023703a00320f10120b60171210820f0012f0106220520b7014d0d0220b101101b220b450d19200b208e013b0106200b208e01360200200b20a0016a200341c0056a20b201109503210920f00120b9016a280200212220e40120f00120ab016a29020037030020e50120f00120ac016a29020037030020a10120f00120ad016a290200370300200320f00120ba016a2902003703c005200920f00120ae016a20f00120a6016a221f2f0100220a20af016a2205209b0174109503218901200b20a9016a20f00120b0016a200520a80174109503218a01200b20a4016a20f00120bb016a200a20bc016a220d209b01741095032120201f20a6013b0100200b20053b01060240200d450d00410021052020210903402009280200220a20053b0104200a200b36020020092091016a2109200d20052093016a2205470d000b0b20e70120e40129030037030020e80120e50129030037030020e90120a101290300370300200320032903c0053703b00420e40120e70129030037030020e50120e80129030037030020a10120e901290300370300200320032903b0043703c0050240024020f10120b60171220920a6014b0d0020f00120a0016a220520082093016a220d209b0174220a6a20052008209b017422206a2205201f2f010022890120086b228a01209b01741096031a200520e60136020020f00120a9016a2205200d20a801746a2005200820a801746a2205208a0120a801741096031a200520aa016a20ea012903003702002005209d016a20eb01290300370200200520a0016a20ec01290300370200200520032903a003370200201f2089012093016a22053b010020f00120a4016a221f20206a20a0016a201f200a6a221f200520b60171220a200d6b209b01741096031a201f20f2013602002009200a4f0d0120f00120206a20b8016a210503402005280200220920082093016a22083b0104200920f00136020020052091016a2105200a2008470d000c020b0b208901200820bc016a220a209b0174221f6a208901200820af016a2205209b01746a2209200b20a6016a220d2f010020056b209b01741096031a200920e601360200208a01200a20a801746a208a01200520a801746a2209200d2f010020056b20a801741096031a200920aa016a20ea012903003702002009209d016a20eb01290300370200200920a0016a20ec01290300370200200920032903a003370200200d200d2f01002093016a22093b010020202008209b01742289016a20bd016a2020201f6a220d200920b601712208200a6b209b01741096031a200d20f201360200200a20084b0d00200b2089016a20be016a210903402009280200220a20052093016a22053b0104200a200b36020020092091016a210920082005470d000b0b20ed0120e40129030037030020ee0120e50129030037030020ef0120a101290300370300200320032903c00537039002024020f0012802002205450d0020f0012f010421f101200521f001202221e601200b21f201410221720c330b202221e60120b101101b22050d010c1a0b2009210b20b101101b2205450d190b2005208e013b01062005208e01360200200520a0016a200341c0056a20b201109503210820052003280270220936029403200320032802742093016a3602742009208e013b01042003200536027020092005360200200520052f0106220a20a801746a220920b3016a20ed01290300370200200920b4016a20ee01290300370200200920b5016a20ef01290300370200200920a9016a2003290390023702002008200a209b01746a20e601360200200520a4016a200a2093016a2209209b01746a200b360200200520093b0106200b20093b0104200b200536020020de010d3f0c190b20f00120a0016a220920082093016a220a209b0174220b6a20092008209b0174220d6a2209200520086b221f209b01741096031a200920e60136020020f00120a9016a2209200a20a801746a2009200820a801746a2209201f20a801741096031a200920aa016a20ea012903003702002009209d016a20eb01290300370200200920a0016a20ec01290300370200200920032903a00337020020f00120a6016a20052093016a22053b010020f00120a4016a2209200d6a20a0016a2009200b6a2209200520b60171220b200a6b209b01741096031a200920f2013602002008200b4f0d3d20f001200a20a2016a2205209b01746a20b8016a210903402009280200220a20052093016a22053b0104200a20f00136020020092091016a2109200b2005470d000c3e0b0b410121c501410421720c300b410221c6010240024020c401209901460d00200341186a20c40110f70220c4012098016a21920120032802182205450d01410121c20120920121c40120920121c70120920121cb012005228b012005200328021c209b01746a22db01470d2a0c200b208b0121d60120990121c40120990121c70120c50121d70120990121cb0120c50121d801410221d9012095010d250c470b208b0121d60120920121c40120920121c70120c50121d70120920121cb0120c50121d801410221d9012095010d230c460b410121c201410621720c300b410221c60102400240209201209901460d00200341106a20920110f7022092012098016a21920120032802102205450d0120920121c40120920121c70120920121cb012005228b0120052003280214209b01746a22db01470d290c1f0b208b0121d601209901219201208f01219001208f0121c30120990121c40120c20121c50120990121c70120c20121d701208f0121c901208f0121ca0120990121cb0120c20121d801410221d9012095010d250c450b208b0121d601208f01219001208f0121c30120920121c40120c20121c50120920121c70120c20121d701208f0121c901208f0121ca0120920121cb0120c20121d801410221d9012095010d230c440b20cc02280200220b20f5016a210a200b2f0106220d20f701742109417f210502400240024003402009450d01200520fe016a210520ff0120fc0120fe01200a280200220820cb024b1b200820cb02461b2208450d0320092080026a2109200a20fb016a210a200820fe01460d000b20cd020d010c090b200d210520cd02450d080b20cd0220fc016a21cd02200b200520f701746a20fd016a21cc02410721720c300b200b2082026a2005208102746a22ce02450d0620ce02280218210920ce0228021c2105208302200e3602002084022085023a00002086022087023a00002088022005360200208902208a023a0000208b02200e360200208c02208d023a0000208e022009360200208f022090023a00002091022092023a000020930220ff013a00002094022095023b01002096022097023a00002098022002360200209902208a023a0000209a02200e360200209b02208d023a0000200341c0056a2082026a22cf02200e360200209c022085023a0000209e02209f023a000020a102200536020020f401208a023a00002003200e3602c4052003208d023a00c00520ce02280208220b20f3016a22d002ad220c20a30288a70d54200c20a20286a7220520fc014c0d5420ce0220f5016a21d102024002400240024002402005450d002005101b22d202450d0f20d102280200220b450d020c010b410821d202200b450d010b4100210a4100210503400240200520d002470d0020d00220fe016a220920d002490d5a20d00220fe01742208200920092008491b2209ad20a20286220c20a50288a70d5a200ca7220820ff01480d5a0240024020d002450d0020d20220d00220fb01742008101a22d2020d010c0c0b2008101b22d202450d0b0b200921d0020b20d202200a6a220920a4023a0000200920fb016a2005360200200920ca026a200341a0036a20f7016a2d00003a0000200920fe016a20032f01a0033b0000200a20f3016a210a200520fe016a22d3022105200b20d302470d000b20d00220d3026b20a4024f0d020c010b410021d30220d00241006b20a4024f0d010b20d30220a4026a220520d302490d5620d00220fe01742209200520052009491b2205ad20a20286220c20a50288a70d56200ca7220920ff01480d560240024020d002450d0020d20220d00220fb01742009101a22d2020d010c100b2009101b22d202450d0f0b200521d0020b20d20220d30220fb01746a21d402200341c0056a21d5020c1d0b20d302210b024002400240024020d5022d0000220a20a6026a220820a7024b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020080e2f291c202d2d121d162d1b082d2d0b0a1a2417091319211f0f0e2526031807060d2214230211041e050100152827100c290b20d5022d00012109412b210a0c2c0b20d50241046a280200210520d502350208210c412a210a0c2a0b20d50241046a280200210520d502350208210c4125210a0c290b20d50241046a280200210520d502350208210c411d210a0c280b20d50241046a280200210520d502350208210c4127210a0c270b20d50241046a280200210520d502350208210c4129210a0c260b20d50241046a280200210520d502350208210c4120210a0c250b20d50241046a280200210520d502350208210c411f210a0c240b20d50241046a280200210520d5022d00012109410c210a0c240b20d50241046a280200210520d502350208210c4114210a0c220b20d50241046a28020021054110210a0c210b20d50241046a2802002105410f210a0c200b20d502290308210c4130210a0c1e0b20d50241046a280200210520d502350208210c4121210a0c1e0b20d50241046a280200210520d502350208210c411a210a0c1d0b20d50241046a280200210520d502350208210c4119210a0c1c0b20d50241046a2802002105412f210a0c1b0b20d50241046a280200210520d502350208210c4126210a0c1a0b20d50241046a28020021054107210a0c190b20d50241046a280200210520d502350208210c4115210a0c180b20d50241046a280200210520d502350208210c4123210a0c170b20d5022d00012109412c210a0c170b20d502280208220aad220c421e88a70d6a200c420286a72209417f4c0d6a4104210502402009450d002009101b2205450d1e0b0240200a450d0020d50241046a2802002109200a41027421082005210a0340200a2009280200360200200a41046a210a200941046a21092008417c6a22080d000b0b20d502410c6a350200422086200c84210c4109210a0c150b20d50241046a28020021054113210a0c140b20d50241046a280200210520d502350208210c411e210a0c130b20d50241046a280200210520d502350208210c4116210a0c120b20d50241046a28020021054111210a0c110b20d50241046a2802002105410b210a0c100b20d5022d000121094103210a0c100b20d50241046a28020021054108210a0c0e0b20d50241046a280200210520d502350208210c4128210a0c0d0b20d50241046a280200210520d502350208210c4118210a0c0c0b20d5022d000121094104210a0c0c0b20d50241046a280200210520d502350208210c4117210a0c0a0b20d50241046a280200210520d502350208210c4122210a0c090b20d50241046a280200210520d502350208210c4124210a0c080b20d50241046a28020021054112210a0c070b20d50241046a280200210520d502350208210c411b210a0c060b20d50241046a280200210520d502350208210c411c210a0c050b20d502290308210c412e210a0c030b20d50241046a2802002105412d210a0c030b20d5022d000121094102210a0c030b0b0b0b20d40220093a000120d402200a3a000020d40220f5016a200c37030020d40220fb016a2005360200200b20fe016a21d30220d40220f3016a21d40220d50220f3016a22d50220fa01470d1d024002400240024020d00220d302470d0020d00220fe016a220520d002490d5820d00220fe01742209200520052009491b220dad20a20286220c20a50288a70d58200ca7220520ff01480d5820d002450d0120d20220d00220fb01742005101a22d2020d020c110b20d002210d0c020b2005101b22d202450d0f0b20d00221d3020b20d20220d30220fb01746a22052092023a0000200520f5016a20a802290000370000200520032900b004370001200341b0046a20034180016a20a9021095031a20f301101b2209450d0720092092023a0000200341a0036a200341b0046a20a9021095031a20d102280200220520fc014c0d5320ce02280200211f4101210a4101210802402005450d002005101b2208450d0b0b2008201f2005109503210802400240024020050d004100211f4101200820051095031a20050d010c020b2005101b220a450d0d2005211f200a200820051095031a2005450d010b200810190b200341b0046a200341a0036a20a9021095031a20ce0231000d210c200341a0036a200341b0046a20a9021095031a200341b0046a200341a0036a20a9021095031a20034190026a200341b0046a20a9021095031a20f301101b2208450d08200b20f7016a210b20d60220aa027121d60220d70220ab028322d7022005ad84200c20ad02868420ae0284210c20082092023a000020081019200341a0036a20034190026a20a9021095031a200341b0046a200341a0036a20a9021095031a024020092d000020af02470d00200928020820b00271450d00200928020410190b2009101920034190026a200341b0046a20a9021095031a200341b0046a20034190026a20a9021095031a20b10220d60236020020b302200b36020020b502200d360200200341a0036a209d026a20d20236020020b60220ff01360200200341a0036a20a0026a20a20237020020b702200c370200200341a0036a20f5016a201f3602002003200a3602a403200320fe013602a003200341b0046a200341a0036a10da0220034180016a200341b0046a20a9021095031a20ce0220fe0136021020ce0220f901360214024020032d00c00520af02470d0020f60128020020b00271450d0020032802c40510190b024020f4012d000020af02470d0020b80228020020b00271450d0020a10228020010190b0240209e022d000020af02470d00200341c0056a20b2026a28020020b00271450d00200341c0056a20b4026a28020010190b0240209c022d000020af02470d0020b90228020020b00271450d0020cf0228020010190b0240209b022d000020af02470d0020ba0228020020b00271450d00209a0228020010190b02402099022d000020af02470d0020bb0228020020b00271450d0020980228020010190b02402096022d000020af02470d0020bc0228020020b00271450d0020bd0228020010190b02402094022d000020af02470d0020be0228020020b00271450d0020bf0228020010190b02402093022d000020af02470d0020c00228020020b00271450d0020c10228020010190b02402091022d000020af02470d0020c20228020020b00271450d0020c30228020010190b0240208f022d000020af02470d0020c40228020020b00271450d00208e0228020010190b0240208c022d000020af02470d0020c50228020020b00271450d00208b0228020010190b02402089022d000020af02470d0020c60228020020b00271450d0020880228020010190b02402086022d000020af02470d0020c70228020020b00271450d0020c80228020010190b02402084022d000020af02470d0020c90228020020b00271450d0020830228020010190b20d70220ac028421d70220f90120fe016a21f90120d40120f801470d140c430b20ea0228020c0d3520ea0228021021ec02200341e0006a21ed02200328026421ee020c320b20f002280200220b20e0026a210a200b2f0106220d20de02742109417f21050240024003402009450d01200520e3026a210520e40220e10220e302200a280200220820ef024b1b200820ef02461b2208450d04200920e5026a2109200a20df026a210a200820e302460d000b20f1020d010c410b200d210520f102450d400b20f10220e1026a21f102200b200520de02746a20e2026a21f002410a21720c2f0b20f2022802182205450d3220f20228021022f402200520de02746a21f502410221050c310b200b20e7026a200520e602746a2205450d3d2005280210450d0a20da0220df026a20052802143602000c3d0b20084108101c000b41ccfbc1004180011030000b20094104101c000b41104108101c000b41104108101c000b20054108101c000b20054101101c000b20054101101c000b20094108101c000b20054108101c000b41ccfcc10041351030000b4194034104101c000b41c4034104101c000b41c4034104101c000b4102211f0c020b4102211f0c020b4103211f0c020b410121050c3c0b410121050c3b0b410121050c3a0b410121720c0d0b410221720c0e0b410321720c0f0b410521720c100b410821720c120b410821720c120b410021050c200b410121050c1f0b410121050c1e0b410121050c1d0b410121050c1c0b410221050c1b0b410321050c1a0b410421050c190b410521050c180b410521050c170b410521050c160b410521050c150b410521050c140b410521050c130b410521050c120b410521050c110b410521050c100b410521050c0f0b410521050c0e0b410521050c0d0b410021050c010b410121050b0340024002400240024002400240024002400240024002400240024002400240024002400240024020050e03000102020b207620744f0d020240024002400240024020752802002076202d74220d6a22052d0000202a470d0020032005202d6a2205360290022007450d08200f200528020022054d0d0420072005202e746a2802002209450d00202f200e360200203020313a0000203220333a000020342009360200203520363a00002037200e360200203820393a0000203a2005360200203b202a3a0000203c203d3a0000203e203f3a0000204020413b0100204220433a000020442002360200204520363a00002046200e360200204720393a00002048200e360200204920313a0000204b204c3a0000200341c0056a20256a22772009360200204e20363a0000202920032f00b0043b00002029202e6a200341b0046a202e6a2d00003a0000200320393a00c0052003200e3602c40520732802002278207620286a2279490d092073207636020020752802002105200341b0046a202b6a227a2027360200200341b0046a204d6a227b207536020020502005200d6a2208204d6a220b360200200320793602b004200341b0046a202c6a227c20052079202d74227d6a221f3602002026200341c0056a3602002003207820796b227e3602b404200b2105024020082d0000220a2051460d00410021050340200820056a21090240200a206c712052470d002009204f6a280200205371450d002009202d6a28020010190b2005450d0320502009204a6a3602002005204d6a21052009204d6a2d0000220a2051470d000b200820056a204d6a21050b2005201f470d020c030b410121050c150b2009204d6a2205201f460d010b0340205020052209204d6a22053602000240024020092d0000220a2052460d00200a2051470d010c030b2009204f6a280200205371450d002009202d6a28020010190b200b2005470d000b0b02400240207e450d00207920702802142205470d012027227f200341c0056a2280016b202d762281010d0b0c100b2075202610fb0220502802002205207c280200220b470d110c120b200d2005202d7422056b218201207528020020056a218301200341c0056a2284012027460d0741002185010c0b0b200341c0056a20256a20283602002003206d3602a403204e200341a0036a3602002003206e3702c4052003206f3602c005200320034190026a3602a003200341b0046a200341c0056a102420032802b0042205450d1c20032902b404210c2000200536020420004101360200200041086a200c3702002007450d28200f450d28200710190c280b20ed02280200220b20e0026a210a200b2f0106220d20de02742109417f210502400240024003402009450d01200520e3026a210520e40220e10220e302200a280200220820ec024b1b200820ec02461b2208450d03200920e5026a2109200a20df026a210a200820e302460d000b20ee020d010c160b200d210520ee02450d150b20ee0220e1026a21ee02200b200520de02746a20e2026a21ed02410121050c120b200b20e7026a200520e602746a2205450d132005280210450d0420ea0220d8026a20052802143602000c130b20f40222f60220df026a21f40220f60228020021f702200341e0006a21f802200328026421f9020c050b41a4d5c30020762074104a000b41ecf5c10041cc001030000b41e4d5c3001029000b41ccfcc10041351030000b41012185010c020b41042185010c030b410021050c030b410121050c020b410121050c010b410121050b034002400240024002400240024002400240024002400240024020050e020001010b02400240024002400240207b280200228601202d6a2209280200220520786b2081014f0d0020782081016a220a2078490d362005202874220b200a200a200b491b220aad206886220c206988a70d36200ca7220b203f480d362005450d012086012802002005202d74200b101a22050d020c040b20860128020021050c020b200b101b2205450d020b20860120053602002009200a3602000b200520792081016a2209202d746a2005207d6a207e202d741096031a200320093602b00420092086012802082205460d0d20762081016a202d742005202d7422056b21870120860128020020056a218801208001207f470d030c020b200b4108101c000b024002400240024002400240024002402085010e050001030406060b2026208401204d6a3602000c010b41002184010b200341a0036a20840110fc0220032d00a0032051460d1120830120032903a003370300208301204f6a200341a0036a204f6a2903003703002073207328020020286a3602000240208201450d00208301204d6a218301208201206b6a2182012026280200228401207a280200470d0541012185010c090b207a280200227f20262802002280016b202d76228101450d10410021050c0f0b2026208001204d6a3602000c010b41002180010b200341a0036a20800110fc0220032d00a0032051460d0e20880120032903a003370300208801204f6a200341a0036a204f6a290300370300208601204f6a2205200528020020286a360200208701450d0d208801204d6a218801208701206b6a2187012026280200228001207a280200227f460d0441022185010c0a0b20f802280200220b20e0026a210a200b2f0106220d20de02742109417f210502400240024002400240024003402009450d01200520e3026a210520e40220e10220e302200a280200220820f7024b1b200820f702461b2208450d03200920e5026a2109200a20df026a210a200820e302460d000b20f9020d010c030b200d210520f902450d020b20f90220e1026a21f902200b200520de02746a20e2026a21f80241042185010c0e0b200b20e7026a200520e602746a2205450d002005280210450d0120f60220052802143602000b20f40220f502470d010c140b41ccfcc10041351030000b410221050c110b41002185010c040b41032185010c040b41022185010c040b41032185010c040b410121050c060b410121050c050b410121050c040b410121050c030b410121050c020b410121050c010b410121050c000b0b200341a0036a204f6a2205203f360200200320673703a003200341a0036a202610fb0220032802a003222220052802002209202d7422086a210b20032802a403218901202221050240024002400240024002402009450d000240024002400240207b2802002220202d6a2274280200220520032802b404220d20032802b00422096a221f6b2008202d75220a4f0d00201f200a6a228a01201f490d2e2005202874221f208a01208a01201f491b221fad206886220c206988a70d2e200ca7228a01203f480d2e2005450d0120202802002005202d74208a01101a22050d020c050b202028020021050c020b208a01101b2205450d030b202020053602002074201f3602000b20052009200a6a220a202d74221f6a20052009202d746a200d202d741096031a2003200a3602b00420222105200a20202802082209460d0020202802002205201f6a217420052009202d746a210a2022210903402008450d04200341a0036a202e6a22052009206a6a2d00003a0000200320092f00013b01a00320092d0000220d2051460d032009202d6a290200210c2009202c6a280200211f200a200d3a0000200a202c6a201f360200200a202d6a200c37020020032f01a003210d200a206a6a20052d00003a0000200a20286a200d3b00002020204f6a2205200528020020286a3602002008206b6a21082009204d6a22052109200a204d6a220a2074470d000b0b2005200b460d040c030b208a014108101c000b2009204d6a2205200b470d010c020b200b2205200b460d010b03400240024020052d000022092052460d0020092051470d010c030b2005204f6a280200205371450d002005202d6a28020010190b2005204d6a2205200b470d000b0b208901450d00202210190b20502802002205207c280200220b460d010b0340205020052209204d6a22053602000240024020092d0000220a2052460d00200a2051470d010c030b2009204f6a280200205371450d002009202d6a28020010190b200b2005470d000b0b024020032802b4042205450d00024020032802b004220b207b2802002208204f6a220a2802002209460d00200828020022082009202d746a2008200b202d746a2005202d741096031a0b200a200520096a3602000b024020032d00c0052052470d00200341c0056a204f6a280200205371450d0020032802c40510190b0240204e2d00002052470d00200341c0056a202b6a280200205371450d00207728020010190b0240204b2d00002052470d002054280200205371450d00205528020010190b024020492d00002052470d002056280200205371450d00204828020010190b024020472d00002052470d002057280200205371450d00204628020010190b024020452d00002052470d002058280200205371450d00204428020010190b024020422d00002052470d002059280200205371450d00205a28020010190b024020402d00002052470d00205b280200205371450d00205c28020010190b0240203e2d00002052470d00205d280200205371450d00205e28020010190b0240203c2d00002052470d00205f280200205371450d00206028020010190b0240203b2d00002052470d002061280200205371450d00203a28020010190b024020382d00002052470d002062280200205371450d00203728020010190b024020352d00002052470d002063280200205371450d00203428020010190b024020322d00002052470d002064280200205371450d00206528020010190b024020302d00002052470d002066280200205371450d00202f28020010190b410f21050b200520766a2276207328020022744f0d0a410021050c000b0b20f20220dd026a22f20220f302460d0b410b2172410521050c090b20ea0220e9026a22ea0220eb02460d0a41092172410521050c080b20de01450d010b20dd01450d0120d50110194102211f0c020b4102211f0c020b4102211f0c020b410121050c160b410121050c150b410121050c140b2070202b6a22702071460d0d41002172410521050c000b0b41ecf5c10041cc001030000b20da0220d9026a22da0220db02460d024104211f410121050c100b200341e0006a41086a200341f0006a41086a28020036020020032003290370370360208c01412c6c2105208d0141586a2109024003404100210a2005450d01200541546a2105200941286a210b2009412c6a22082109200b2d00004103470d000b200841086a2802002205450d00200541286c2109200828020041186a21054100210a0340200a20052d0000456a210a200541286a2105200941586a22090d000b0b208c01412c6c2105208d0141606a21090240024003402005450d01200541546a2105200941206a210b2009412c6a22082109200b2d00004104470d000b200828020021050c010b410021050b411021f301200341c0056a41106a22f401200341c8006a41106a280200360200410821f501200341c0056a41086a22f601200341c8006a41086a290300370300200320032903483703c00520034180016a200341c0056a10d50220cf01450d00410221f70120d40120cf014102746a21f8012005200a6a21f901200341b0076a21fa01410421fb01417f21fc0141940321fd01410121fe01410021ff01417c21800241052181024134218202200341a4076a218302200341a0076a218402411321850220034190076a21860241d70021870220034184076a21880220034180076a218902412d218a02200341f4066a218b02200341f0066a218c024112218d02200341e4066a218e02200341e0066a218f02410b219002200341d0066a2191024106219202200341c0066a219302200341b0066a219402418408219502200341a0066a219602413721970220034194066a21980220034190066a21990220034184066a219a0220034180066a219b02200341f0056a219c024120219d02200341c0056a41206a219e0241d600219f02411421a002200341c0056a41146a21a102420421a202421c21a302410f21a402422021a502417e21a602412e21a702200341b7046a21a802418c0121a90241807e21aa02428080808080804021ab024280808080808c0121ac02422821ad024280808080800c21ae02410921af0241ffffffff0321b002200341cc036a21b102412821b202200341a0036a41286a21b302412421b402200341a0036a41246a21b502200341bc036a21b602200341ac036a21b702200341d8056a21b802200341f8056a21b90220034188066a21ba0220034198066a21bb02200341a8066a21bc02200341a4066a21bd02200341b8066a21be02200341b4066a21bf02200341c8066a21c002200341c4066a21c102200341d8066a21c202200341d4066a21c302200341e8066a21c402200341f8066a21c50220034188076a21c60220034198076a21c70220034194076a21c802200341a8076a21c902410321ca020c020b024020d001450d0020d30110190b200341c0056a20034180016a418c011095031a200341b0046a200341c0056a10d702411021d802200341b0046a41106a2802002205450d00412c21d90220032802b80422da022005412c6c6a21db02410a21dc02411c21dd02410221de02410421df02410821e002417f21e10241940321e202410121e302410021e402417c21e502410521e602413421e702410921e802411421e9024104211f0c020b200341bc046a290200210c20032802b004210520032902b404216920032802602003280264200328026810fa02200020d8026a200c370200200041086a206937020020002005360204200041003602002007450d06200f450d0620071019200424000f0b4103211f410121050c0c0b410121050c0b0b42ac808080c005210c0b200710190b2000200536020420004101360200200041086a200c3702000b200141086a280200218b010240200141106a2802002203450d002003412c6c2105208b0121030340200310d3022003412c6a2103200541546a22050d000b0b2001410c6a280200450d00208b0110190b200424000f0b202120236a22212024470d010b200341c8006a41106a2205200141106a280200360200200341c8006a41086a228b01200141086a290200370300200320012902003703482005280200228c0120236c2105208b01280200228d0141586a218b010240024003402005450d01200541546a2105208b0141286a2109208b0120236a228e01218b0120092d00004108470d000b200341386a208e0110d20220032802382109200328023c21050c010b410021090b2005410020091b218f01208c01412c6c2105208d0141586a218b01200941d889c20020091b2190010240024003402005450d01200541546a2105208b0141286a2109208b01412c6a228e01218b0120092d0000410a470d000b200341306a208e0110d20220032802302109200328023421050c010b410021090b2005410020091b219101208c01412c6c2105208d0141586a218b01200941d889c20020091b2192010240024003404100218e012005450d01200541546a2105208b0141286a2109208b01412c6a229301218b0120092d00004109470d000b20930128020021940141012195010c010b41002195010b2003420037027441a0c0c100219601200341a0c0c1003602704114219701209001208f0141146c6a218f01411c219801209201209101411c6c6a219901410421910141ff01219a0141012193014102219b01410c219c014110219d014202219e014220219f01410821a001200341c0056a41086a21a101417f21a201410d21a30141940321a401418c0321a501410621a601410b21a701410521a801413421a901411821aa01418c0221ab0141840221ac0141fc0121ad01412421ae01417921af0141940221b00141c40321b10141bc0321b20141cc0021b30141c40021b401413c21b50141ffff0321b601410a21b70141980321b801412021b90141f40121ba0141b00321bb01417a21bc01416c21bd0141fc0221be01417c21bf0142808080807021c00142ffffffff0f21c101410021c20120900121c30120920121c401410021c501410021c60120920121c701410021c80120900121c90120900121ca0120920121cb01410021cc01410021cd01410021ce01410021cf01410021d001410421d101410421d201410421d301410421d4010c010b4101211f0c010b4102211f0c010b410121050c010b410121050c000b0b102b000b101d000b90c102132c7f017e697f017e4b7f017e397f027e247f017e797f017e0c7f017e0d7f017e0b7f017e507f230041e0006b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2204410d4b0d00024020040e0e00090607030a0c080e050d02040b000b200141186a2802002105200141146a2802002106200141106a28020021072001410c6a2802002108200141086a2802002109200141046a280200210a200241046a280200200241086a2802002204470d16200441016a220b2004490d5a2004410174220c200b200b200c491b220c4100480d5a2004450d2d20022802002004200c101a220b450d2e0c570b2001410c6a280200210b200141086a2802002107200141046a280200210520012d0001210d200241046a280200200241086a2802002204470d0d200441016a22062004490d592004410174220e20062006200e491b220e4100480d592004450d1c20022802002004200e101a2206450d1d0c540b2001410c6a280200210f200141086a2802002110200141046a2802002111200241046a280200200241086a2802002204470d0d200441016a220b2004490d5820044101742205200b200b2005491b22054100480d582004450d1d200228020020042005101a220b450d1e0c510b2001410c6a2802002112200141086a2802002113200141046a2802002114200241046a280200200241086a2802002204470d0d200441016a220b2004490d5720044101742205200b200b2005491b22054100480d572004450d1e200228020020042005101a220b450d1f0c4e0b200141146a2802002115200141106a28020021162001410c6a2802002117200141086a2802002118200141056a2d00002119200141046a2d0000211a200241046a280200200241086a2802002204470d0d200441016a220b2004490d5620044101742205200b200b2005491b22054100480d562004450d1f200228020020042005101a220b450d200c4b0b2001410c6a280200211b200141086a280200211c200141046a280200211d200241046a280200200241086a2802002204470d0d200441016a220b2004490d5520044101742205200b200b2005491b22054100480d552004450d20200228020020042005101a220b450d210c480b2001410c6a2802002106200141086a280200211e200141046a280200211f200241046a280200200241086a2802002204470d0d200441016a220b2004490d5420044101742205200b200b2005491b22054100480d542004450d21200228020020042005101a220b450d220c450b2001410c6a2802002106200141086a2802002120200141046a2802002121200241046a280200200241086a2802002204470d0d200441016a220b2004490d5320044101742205200b200b2005491b22054100480d532004450d22200228020020042005101a220b450d230c420b2001410c6a2802002106200141086a2802002122200141046a2802002123200241046a280200200241086a2802002204470d0d200441016a220b2004490d5220044101742205200b200b2005491b22054100480d522004450d23200228020020042005101a220b450d240c3f0b2001410c6a2802002106200141086a2802002124200141046a2802002125200241046a280200200241086a2802002204470d0e200441016a220b2004490d5120044101742205200b200b2005491b22054100480d512004450d26200228020020042005101a220b450d270c3c0b2001410c6a2802002126200141086a2802002127200141046a2802002128200241046a280200200241086a2802002204470d0e200441016a220b2004490d5020044101742205200b200b2005491b22054100480d502004450d27200228020020042005101a220b450d280c390b200141286a2802002129200141246a280200212a200141206a280200212b2001411c6a280200212c200141186a280200212d200141146a280200212e2001410c6a290200212f200141086a2802002109200141046a2802002108200241046a280200200241086a2802002204470d0e200441016a220b2004490d4f20044101742205200b200b2005491b22054100480d4f2004450d28200228020020042005101a220b450d290c360b2001410c6a2802002130200141086a2802002131200141046a2802002132200241046a280200200241086a2802002204470d0e200441016a220b2004490d4e20044101742205200b200b2005491b22054100480d4e2004450d29200228020020042005101a220b450d2a0c330b2001410c6a2802002133200141086a2802002134200141046a2802002135200241046a280200200241086a2802002204470d0e200441016a220b2004490d4d20044101742205200b200b2005491b22054100480d4d2004450d2a200228020020042005101a220b450d2b0c300b200141046a2802002104200241046a280200200241086a280200220b470d0e200b41016a2205200b490d4c200b4101742206200520052006491b22064100480d4c200b450d2b2002280200200b2006101a2205450d2c0c2d0b200228020021060c470b2002280200210b0c440b2002280200210b0c410b2002280200210b0c3e0b2002280200210b0c3b0b2002280200210b0c380b2002280200210b0c350b2002280200210b0c320b2002280200210b0c410b2002280200210b0c2e0b2002280200210b0c2b0b2002280200210b0c280b2002280200210b0c250b2002280200210b0c220b200228020021050c1f0b200e101b22060d370b200e4101101c000b2005101b220b0d330b20054101101c000b2005101b220b0d2f0b20054101101c000b2005101b220b0d2b0b20054101101c000b2005101b220b0d270b20054101101c000b2005101b220b0d230b20054101101c000b2005101b220b0d1f0b20054101101c000b2005101b220b0d1b0b20054101101c000b200c101b220b0d290b200c4101101c000b2005101b220b0d150b20054101101c000b2005101b220b0d110b20054101101c000b2005101b220b0d0d0b20054101101c000b2005101b220b0d090b20054101101c000b2005101b220b0d050b20054101101c000b2006101b22050d010b20064101101c000b20022005360200200241046a2006360200200241086a280200210b0b200241086a200b41016a3602002005200b6a41083a00004101210e410021064100210b024002400240024003400240200b2006470d0020064101742205200641016a220720072005491b22054100480d24024002402006450d00200e20062005101a220e0d010c040b2005101b220e450d030b200521060b200e200b6a200441807f72200441ff0071200441077622051b3a0000200b41016a210b2005210420050d000b200b417f6a210a200241086a2107200241046a2108200b210503400240024002400240200828020020072802002204470d00200441016a220d2004490d2720044101742209200d200d2009491b22094100480d272004450d01200228020020042009101a220d0d020c060b2002280200210d0c020b2009101b220d450d040b2002200d36020020082009360200200728020021040b2007200441016a360200200d20046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b0240200241046a2802002205200241086a28020022046b200a4d0d00200228020021050c040b2004200b6a22072004490d2220054101742204200720072004491b22044100480d22024002402005450d00200228020020052004101a2205450d010c040b2004101b22050d030b20044101101c000b20054101101c000b20094101101c000b20022005360200200241046a2004360200200241086a28020021040b200241086a2004200b6a360200200520046a200e200b1095031a4101210d02402006450d00200e10190b4101210e410821040c1c0b2002200b360200200241046a2005360200200241086a28020021040b4101218d024108218e02200241086a200441016a360200200b20046a410a3a00004100218f022003412c6a229002410036020020034201370224200320023602202035203341186c6a219102410721920241ff0021930241807f2194024100219502410021960220332197020240024041004100460d00411621410c010b41152141410f21040c1b0b410f21040c1a0b2002200b360200200241046a2005360200200241086a28020021040b41012180024108218102200241086a200441016a360200200b20046a41063a00004100218202200341dc006a22830241003602002003420137025420032002360250203220304104746a218402410721850241ff0021860241807f218702410021880241002189022030218a020240024041004100460d00411221410c010b41112141410f21040c190b410f21040c180b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41003a0000202f422088a72107410121fc014100210b4100210541002104202fa722fd0121060240024002400340024020052004470d00200441016a220b2004490d1d200441017422fe01200b200b20fe01491b220b4100480d1d024002402004450d0020fc012004200b101a22fc010d010c040b200b101b22fc01450d030b200b21040b20fc0120056a200641807f72200641ff0071200641077622fe011b3a0000200541016a210520fe01210620fe010d000b200420056b20fd014f0d02200520fd016a220b2005490d1b20044101742206200b200b2006491b220b4100480d1b024002402004450d0020fc012004200b101a22fc01450d010c030b200b101b22fc010d020b200b4101101c000b200b4101101c000b200b21040b20fc0120056a200820fd011095031a02402009450d0020081019200b21040b20fd0120056a21fe01024002400240024002400340024020fe012004470d00200441016a220b2004490d1f20044101742205200b200b2005491b220b4100480d1f024002402004450d0020fc012004200b101a22fc010d010c040b200b101b22fc01450d030b200b21040b20fc0120fe016a200741807f72200741ff0071200741077622051b3a000020fe0141016a21fe012005210720050d000b024002400240202e450d00202c210503400240024002400240200b20fe01470d00200b41016a2204200b490d25200b4101742206200420042006491b22044100480d25200b450d0120fc01200b2004101a22fc010d020c090b200b21040c020b2004101b22fc01450d070b200b21fe012004210b0b20fc0120fe016a200541807f72200541ff0071200541077622061b3a000020fe0141016a21fe012006210520060d000b200420fe016b202c4f0d0620fe01202c6a220b20fe01490d2020044101742205200b200b2005491b220b4100480d202004450d0120fc012004200b101a22fc01450d020c050b200b2104410121ff010c060b200b101b22fc010d030b200b4101101c000b200b4101101c000b20044101101c000b200b21040b20fc0120fe016a202e202c1095031a20fe01202c6a21fe01410021ff01202d450d00202e10190b202b20294104746a21e2022029210b0240024003400240024002400240200420fe01470d00200441016a22052004490d1f20044101742206200520052006491b222c4100480d1f2004450d0120fc012004202c101a22fc010d020c050b2004212c0c020b202c101b22fc01450d030b200421fe01202c21040b20fc0120fe016a200b41807f72200b41ff0071200b41077622051b3a000020fe0141016a21fe012005210b20050d000b02402029450d00411021e302410821e402410c21e502417f21e602410621e702410121e802410021e902410721ea0241ff0021eb0241807f21ec02410221ed02410321ee0241c00021ef0241ff0121f002410421f102410521f202202b21fd01411921410c020b202b21fd01410721040c180b202c4101101c000b410f21040c160b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41053a000020282026410c6c6a21ed014100210b410021ee01410021ef01410121f00120262104024002400340024020ee0120ef01470d00200b20ee0141016a22052005200b491b22ef014100480d190240200b450d0020f00120ee0120ef01101a22f0010d010c030b20ef01101b22f001450d020b20f00120ee016a200441807f72200441ff0071200441077622051b3a0000200b41026a210b20ee0141016a21ee012005210420050d000b02402026450d00410c21f101410221f201410121f301410821f401410021f501410421f601410721f70141ff0021f80141807f21f901202821fa01411021410c020b202821fb01410621040c160b20ef014101101c000b410f21040c140b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41013a0000202520064104746a21d8014100210b410021d901410021da01410121db0120062104024002400340024020d90120da01470d00200b20d90141016a22052005200b491b22da014100480d170240200b450d0020db0120d90120da01101a22db010d010c030b20da01101b22db01450d020b20db0120d9016a200441807f72200441ff0071200441077622051b3a0000200b41026a210b20d90141016a21d9012005210420050d000b02402006450d00411021dc01410521dd01410121de01410021df01410421e001410221e101410721e20141ff0021e30141807f21e40142808080801021e501410321e601411821e70141fdf9ff7721e801413f21e90141c00021ea01202521eb01410f21410c020b202521ec01410521040c140b20da014101101c000b410f21040c120b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41073a00002023200641146c6a21bc014100210b410021bd01410021be01410121bf0120062104024002400340024020bd0120be01470d00200b20bd0141016a22052005200b491b22be014100480d150240200b450d0020bf0120bd0120be01101a22bf010d010c030b20be01101b22bf01450d020b20bf0120bd016a200441807f72200441ff0071200441077622051b3a0000200b41026a210b20bd0141016a21bd012005210420050d000b02402006450d00411421c001410421c101410121c201411021c301410721c40141ff0021c50141807f21c601410021c701410221c801202321c901410e21410c020b202321ca01410421040c120b20be014101101c000b410f21040c100b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41033a0000202120064102746a21b0014100210b410021b101410021b201410121b301200621040240024002400340024020b10120b201470d00200b20b10141016a22052005200b491b22b2014100480d140240200b450d0020b30120b10120b201101a22b3010d010c030b20b201101b22b301450d020b20b30120b1016a200441807f72200441ff0071200441077622051b3a0000200b41026a210b20b10141016a21b1012005210420050d000b2006450d01410121b401410721b50141ff0021b60141807f21b701410021b801410221b901410421ba01202121bb01410d21410c020b20b2014101101c000b410121040c0f0b410f21040c0e0b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41023a0000201f200641286c6a218d014100210b4100218e014100218f014101219001200621040240024003400240208e01208f01470d00200b208e0141016a22052005200b491b228f014100480d110240200b450d00209001208e01208f01101a2290010d010c030b208f01101b229001450d020b209001208e016a200441807f72200441ff0071200441077622051b3a0000200b41026a210b208e0141016a218e012005210420050d000b02402006450d00411b21910141102192014119219301412821940141042195014120219601411c219701411421980142202199014107219a0141ff00219b0141807f219c014101219d014100219e014102219f0141f00021a001410321a101411821a201417f21a301413f21a40141c00021a5014180fe0321a601201f21a701410c21410c020b201f21a701410321040c0e0b208f014101101c000b410f21040c0c0b2002200b360200200241046a2005360200200241086a28020021040b4101216d4108216e200241086a200441016a360200200b20046a41093a00004100216f200341dc006a227041003602002003420137025420032002360250201d201b411c6c6a21714107217241ff00217341807f21744100217541002176201b21770240024041004100460d00410821410c010b41072141410f21040c0b0b410f21040c0a0b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41003a00000240024002400240024002404104101b2261450d00206141eec2b5ab06360000024002400240024002400240024002400240201a4101460d000240201a4102460d00201a4103470d0241002162410121632018216420172165201621664101216741012168410121694101101b226a450d1b410021040c180b2003410036024820034201370340200341c8006a21094101210741002105410021042018210b0340024020042005470d00200541016a22062005490d1b20054101742208200620062008491b22064100480d1b024002402005450d00200720052006101a22070d010c0b0b2006101b2207450d0a0b2003200636024420032007360240200621050b2009200441016a2208360200200720046a200b41807f72200b41ff0071200b41077622061b3a0000200821042006210b20060d000b201720154104746a219c032015450d032017219d032018450d044104219e03201720154104746a229f0341706a21a003410021a103410121a203411021a303417f21a403410821a503410721a60341ff0021a70341807f21a803411a21a903201821aa03410021ab03201721ac03410621410c0c0b410021632003410036024820034201370340200341146a2015360200200341086a41086a20163602002003201736020c20032018360208200341d0006a200341086a200341c0006a107420032d005022ad03411a470d01200341c0006a41086a2802002166200328024421652003280240216441012167410021684100216241012119410121694101101b226a0d090c190b41012164410021044100210b20162105034002400240024002402004200b470d00200441016a220b2004490d1c20044101742206200b200b2006491b22654100480d1c2004450d01206420042065101a22640d020c0b0b200421650c020b2065101b2264450d090b2004210b206521040b2064200b6a200541807f72200541ff0071200541077622061b3a0000200b41016a210b2006210520060d000b2065200b6b20164f0d0c200b20166a2204200b490d1720654101742205200420042005491b22044100480d172065450d03206420652004101a2264450d040c0b0b20032d0053411074210420032f0051210b200341d0006a41086a29030021e603200328025421e70302402003280244450d00200328024010190b200b20047221e803410c21040c140b2017219d030b209d03209c03460d06410d21040c120b2004101b22640d070b20044101101c000b20064101101c000b20654101101c000b41044101101c000b410021040c0c0b410e21040c0b0b410f21040c0a0b200421650b2064200b6a201820161095031a200b20166a21664101216302402017450d00201810190b41002168410121674101216241002119410121694101101b226a450d0b410021040c080b2002200b360200200241046a2005360200200241086a28020021040b200241086a200441016a360200200b20046a41043a000020142012410c6c6a21514100210b41002152410021534101215420122104024002400340024020522053470d00200b205241016a22052005200b491b22534100480d0b0240200b450d00205420522053101a22540d010c030b2053101b2254450d020b205420526a200441807f72200441ff0071200441077622051b3a0000200b41026a210b205241016a21522005210420050d000b02402012450d00410c21554102215641082157410121584100215941f000215a4104215b4107215c41ff00215d41807f215e2014215f410521410c020b20142160410221040c080b20534101101c000b410f21040c060b2002200b360200200241046a2005360200200241086a28020021040b4101213641082137200241086a200441016a360200200b20046a410b3a000041002138200341dc006a2239410036020020034201370254200320023602502011200f411c6c6a213a4107213b41ff00213c41807f213d4100213e4100213f200f21400240024041004100460d00410121410c010b41002141410f21040c050b410f21040c040b20022006360200200241046a200e360200200241086a28020021040b200241086a220e200441016a360200200620046a200d3a000002400240024002400240200241046a2802002206200e28020022046b200b4f0d002004200b6a220d2004490d0820064101742204200d200d2004491b22044100480d082006450d01200228020020062004101a2206450d020c030b200228020021060c030b2004101b22060d010b20044101101c000b20022006360200200241046a2004360200200241086a28020021040b200241086a2004200b6a360200200620046a2005200b1095031a4101210e4100210d02402007450d0020051019410821040c030b410821040c020b2002200b360200200241046a200c360200200241086a28020021040b4101210c200241086a200441016a360200410021cb01200b20046a41003a00002003411c6a2005360200200341186a200636020020032007360214200320083602102003200936020c2003200a360208200341d0006a200341086a200210e302200320032900513703402003200341d0006a41086a29000037004702400240024020032d00502204411a470d00410021cc014101210d4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d201410121d301410121d401410121d501410121d601410121d7010c010b20002003290340370001200020043a0000200041086a20032900473700000c010b410921040c010b410b21040b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e10000102030405060708090a0b24282930300b206a20193a0000410121044101210b20662105034002400240024002402004200b470d00200420696a220b2004490dff0220042069742206200b200b2006491b226b4100480dff022004450d01206a2004206b101a226a0d020c320b2004216b0c020b206b101b226a450d300b2004210b206b21040b206a200b6a200541807f72200541ff0071200541077622061b3a0000200b20696a210b2006210520060d000b206b200b6b20664f0d1d200b20666a2204200b490dfa02206b4101742205200420042005491b22044100480dfa02206b450d1b206a206b2004101a226a450d1e0c1c0b02402020450d00202110190b200241086a2105200241046a210720b101210b03400240024002400240200728020020052802002204470d00200441016a22062004490dfd022004410174220d20062006200d491b220d4100480dfd022004450d0120022802002004200d101a22060d020c2d0b200228020021060c020b200d101b2206450d2b0b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20b1014f0d00200420b1016a22052004490df902200b4101742204200520052004491b22044100480df902200b450d132002280200200b2004101a220b450d160c140b2002280200210b0c140b20142012410c6c6a20606b2104024003402004450d01200441746a21042060280204210b2060410c6a2160200b4102470d000b0b02402013450d00201410190b200241086a2105200241046a21072052210b03400240024002400240200728020020052802002204470d00200441016a22062004490dfc022004410174220d20062006200d491b220d4100480dfc022004450d0120022802002004200d101a22060d020c2d0b200228020021060c020b200d101b2206450d2b0b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20524f0d00200420526a22052004490df802200b4101742204200520052004491b22044100480df802200b450d0e2002280200200b2004101a220b450d110c0f0b2002280200210b0c0f0b20a701208d01460d2d034020a70141186a2d00004104460d2e20a70141106a280200210420a701410c6a280200210b024020a70141046a280200450d0020a70128020010190b02402004450d00200b10190b20a70141286a22a701208d01470d000c2e0b0b20ca0120bc01460d2d034020ca01410c6a2802004104460d2e024020ca0141046a280200450d0020ca0128020010190b20ca0141146a22ca0120bc01470d000c2e0b0b20ec0120d801460d2d034020ec01410d6a2d00004105460d2e024020ec0141046a280200450d0020ec0128020010190b20ec0141106a22ec0120d801470d000c2e0b0b20282026410c6c6a20fb016b2104024003402004450d01200441746a210420fb01280204210b20fb01410c6a21fb01200b4102470d000b0b02402027450d00202810190b200241086a2105200241046a210720ee01210b03400240024002400240200728020020052802002204470d00200441016a22062004490df8022004410174220d20062006200d491b220d4100480df8022004450d0120022802002004200d101a22060d020c2a0b200228020021060c020b200d101b2206450d280b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20ee014f0d00200420ee016a22052004490df402200b4101742204200520052004491b22044100480df402200b450d062002280200200b2004101a220b450d090c070b2002280200210b0c070b202b20294104746a210b02400340200b20fd01460d0120fd01280200210420fd0141106a21fd0120044108470d000b0b0240202a450d00202b10190b200241086a2105200241046a210720fe01210b03400240024002400240200728020020052802002204470d00200441016a22062004490df8022004410174220d20062006200d491b220d4100480df8022004450d0120022802002004200d101a22060d020c2a0b200228020021060c020b200d101b2206450d280b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20fe014f0d00200420fe016a22052004490df402200b4101742204200520052004491b22044100480df402200b450d112002280200200b2004101a220b450d140c120b2002280200210b0c120b410121cd010c430b2000411a3a0000024020012d00002204410e4b0d000240024002400240024002400240024002400240024002400240024020040e0f0009080703050a0b0d0e0c02060401000b200d450deb02200141086a280200450deb02200141046a2802001019200341e0006a24000f0b200e450dea020240200141086a280200450d00200141046a28020010190b0240200141146a2802002202450d00200141186a280200450d00200210190b200141246a280200450dea02200141206a2802001019200341e0006a24000f0b20cf01450de902410c21f3022001410c6a2802002204450d43411821f402410421f502200141046a28020022f602200441186c6a21f702411421f802411021f902410921fa02410821fb0241ffffffff0321fc02417021fd02411a21410cb2020b20d501450de802200141086a280200450de802200141046a2802001019200341e0006a24000f0b20cd01450de702200141046a2d000022044102460d2620044101460d2520040d272001410c6a280200450de702200141086a2802001019200341e0006a24000f0b20d401450de602200141086a280200450de602200141046a2802001019200341e0006a24000f0b20ce01450de502410c21fe022001410c6a2802002204450d41411c21ff024104218003200141046a2802002281032004411c6c6a218203410821830341142184034110218503410921860341ffffffff032187034170218803411b21410cb0020b20d601450de40202402001410c6a2802002204450d00200141046a2802002102200441286c210403400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241286a2102200441586a22040d000b0b200141086a280200450de402200141046a2802001019200341e0006a24000f0b20d701450de30202402001410c6a2802002204450d00200141046a28020021022004410474210403400240200241046a280200450d00200228020010190b200241106a2102200441706a22040d000b0b200141086a280200450de302200141046a2802001019200341e0006a24000f0b20cc01450de2020240200141086a280200450d00200141046a28020010190b200141146a280200450de202200141106a2802001019200341e0006a24000f0b20d301450de102200141086a280200450de102200141046a2802001019200341e0006a24000f0b20d201450de0022001410c6a2802002204450d3e4104218903200141046a280200228a0320044104746a218b034110218c034109218d034108218e0341ffffffff03218f034170219003411c21410cad020b20d001450ddf02410c2191032001410c6a2802002204450d3f411c2192034104219303200141046a2802002294032004411c6c6a219503410821960341142197034110219803410921990341ffffffff03219a034170219b03411d21410cae020b20d101450dde0202402001410c6a2802002204450d00200141046a2802002102200441146c210403400240200241046a280200450d00200228020010190b200241146a21022004416c6a22040d000b0b200141086a280200450dde02200141046a2802001019200341e0006a24000f0b200110d3020cdd020b02402031450d00203210190b200341d0006a41086a28020021d601200328025421cc012003280250220541046a210d200341dc006a28020022d701210b03400240024002400240200d280200200541086a22062802002204470d00200441016a22072004490df4022004410174220e20072007200e491b220e4100480df4022004450d0120052802002004200e101a22070d020c290b200528020021070c020b200e101b2207450d270b20052007360200200d200e360200200628020021040b2006200441016a360200200720046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200541046a280200220b200541086a28020022046b20d7014f0d00200420d7016a22062004490df002200b4101742204200620062004491b22044100480df002200b450d162005280200200b2004101a220b450d190c170b2005280200210b0c170b410121050c4e0b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420ee016a360200200b20046a20f00120ee011095031a410021d3014101210d024020ef01450d0020f00110190b4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d2010ce2020b20044101101c000b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420526a360200200b20046a205420521095031a410021d4014101210d02402053450d00205410190b4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d201410121d3010cdf020b20044101101c000b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420b1016a360200200b20046a20b30120b1011095031a410021d5014101210d024020b201450d0020b30110190b4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d201410121d301410121d4010cdc020b20044101101c000b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420fe016a360200200b20046a20fc0120fe011095031a0240202c450d0020fc0110190b4100210e4101210d202e450de30120ff01450de401202d450de501202e1019410821040cde020b20044101101c000b2004101b226a450d020b2004216b0b206a200b6a206420661095031a02402065450d00206410190b200b20666a216c024002400240201a4102460d000240201a4101460d00201a0d02206220174572450d030c300b2063450d2f2015450d2e2015410c6c210b201721040340024020042802002205450d00200441046a280200450d00200510190b2004410c6a2104200b41746a220b0d000c2f0b0b2067450d2e2015450d2d410421ae03201720154104746a21af03411021b003410c21b103410821b203417421b303201721b403412521410ca4020b2068201745720d2d0b201810190c2c0b20044101101c000b2004101b220b450d020b2005200b360200200541046a2004360200200541086a28020021040b200541086a200420d7016a360200200b20046a20cc0120d7011095031a024020d601450d0020cc0110190b410021d2014101210d4101210e410121cd01410121ce01410121cf01410121d001410121d1010ccd020b20044101101c000b200041086a20e603370200200041046a20e703360200200020e80341087420ad0372360200206110190c470b0240200141146a2802002204450d002001410c6a28020021022004410c6c2104034002402002280200220b450d00200241046a280200450d00200b10190b2002410c6a2102200441746a22040d000b0b200141106a280200450dc1022001410c6a2802001019200341e0006a24000f0b200141146a2802002204450d4b410c2192042001410c6a28020022930420044104746a2194044110219504410821960441042197044174219804412221410c95020b2001410c6a280200450dbf02200141086a2802001019200341e0006a24000f0b4110219904410c219a044174219b044104219c04412321410c96020b2016450d4f201710190c4f0b200d4101101c000b200d4101101c000b200d4101101c000b200d4101101c000b206b4101101c000b200e4101101c000b02400240024002400240024002400240024002400240024002400240024002400240024002400240024020410e280100031a39042c0605081e3c090a0b0c0d0f0e343612111422232426282a515253545557582d595b5b0b200328025421040c010b203e20366a2204203e490ddd02203e203674220b20042004200b491b220b2038480ddd0202400240203e450d002003280254203e200b101a22040d010c83010b200b101b2204450d82010b200341d0006a20376a200b360200200320043602542039280200213f0b2039203f20366a3602002004203f6a2040203d722040203c712040203b7622041b3a000002402004450d0020042140200341d0006a20376a280200223e2039280200223f470daf01410021410ceb010b200f450d15411c21424118214341142144410821454107214641ff00214741807f2148200341dc006a21494101214a4100214b411a214c2011214d410221410cec010b204d20426a214e204d280204220a450d15204d20436a2802002108204d20446a280200214f204d20456a290200212f204d280200210b204d280210210903400240024002400240200341d0006a20456a220528020020492802002204470d002004204a6a22062004490de0022004204a742207200620062007491b2207204b480de0022004450d01200328025420042007101a22060d020c680b200328025421060c020b2007101b2206450d660b2005200736020020032006360254204928020021040b20492004204a6a360200200620046a200b204872200b204771200b20467622041b3a00002004210b20040d000b2003202f3702442003200a360240200341086a200341c0006a200341d0006a101720032d00082250204c470d342008210b03400240024002400240200528020020492802002204470d002004204a6a22062004490de0022004204a742207200620062007491b2207204b480de0022004450d01200328025420042007101a22060d020c6a0b200328025421060c020b2007101b2206450d680b2005200736020020032006360254204928020021040b20492004204a6a360200200620046a200b204872200b204771200b20467622041b3a00002004210b20040d000b02400240024002402005280200220b204928020022046b20084f0d00200420086a22062004490ddf02200b204a742204200620062004491b2204204b480ddf02200b450d012003280254200b2004101a220b0d020c96010b2003280254210b0c020b2004101b220b450d94010b200520043602002003200b360254204928020021040b2049200420086a360200200b20046a200920081095031a0240204f450d00200910190b204e214d204e203a470dae010c170b205f20556a2160205f28020422092056460dd501205f20576a2802002108205f280200210402400240024020532052470d00205220586a220b2052490ddc0220522058742205200b200b2005491b220b2059480ddc022052450d0120542052200b101a22540d020c89010b2053210b0c010b200b101b2254450d87010b205420526a205a3a00000240024002400240200b205220586a2205470d00200b20586a2205200b490ddd02200b2058742206200520052006491b22532059480ddd02200b450d012054200b2053101a22540d020c8b010b200b21530c020b2053101b2254450d89010b200b21050b205420056a20092058463a0000200520586a21522005205874220b205b6a2107200b20566a210503402007210b024020522053470d00205220586a22062052490ddb022005200620062005491b22532059480ddb0202402052450d00205420522053101a22540d010c630b2053101b2254450d620b205420526a2004205e722004205d712004205c7622061b3a0000200b20566a2107200520566a2105205220586a21522006210420060d000b024020092058470d000340024020522053470d00205220586a22042052490ddc02200b20042004200b491b22532059480ddc0202402052450d00205420522053101a22540d010c6a0b2053101b2254450d690b205420526a2008205e722008205d712008205c7622041b3a0000200b20566a210b205220586a21522004210820040d000b0b2060215f20602051470db001205121600cd4010b200328025421040c010b2075206d6a22042075490dd8022075206d74220b20042004200b491b220b206f480dd802024002402075450d0020032802542075200b101a22040d010c7f0b200b101b2204450d7e0b200341d0006a206e6a200b36020020032004360254207028020021760b20702076206d6a360200200420766a20772074722077207371207720727622041b3a000002402004450d0020042177200341d0006a206e6a280200227520702802002276470db001410721410cf0010b201b450d14411c2178411821794114217a4108217b4107217c41ff00217d41807f217e200341dc006a217f41012180014100218101411a21820141022183014104218401201d218501410921410cf1010b20850120786a2186012085012802042208450d1420850120796a2802002107208501207a6a280200218701208501207b6a290200212f208501280210218801208501280200210b03400240024002400240200341d0006a207b6a228901280200207f2802002204470d0020042080016a22052004490ddb022004208001742206200520052006491b2206208101480ddb022004450d01200328025420042006101a22050d020c640b200328025421050c020b2006101b2205450d620b208901200636020020032005360254207f28020021040b207f20042080016a360200200520046a200b207e72200b207d71200b207c7622041b3a00002004210b20040d000b2003202f37024420032008360240200341086a200341c0006a200341d0006a101720032d0008228a01208201470d322088012007208301746a218b012007210b03400240024002400240208901280200207f2802002204470d0020042080016a22052004490ddb022004208001742206200520052006491b2206208101480ddb022004450d01200328025420042006101a22050d020c660b200328025421050c020b2006101b2205450d640b208901200636020020032005360254207f28020021040b207f20042080016a360200200520046a200b207e72200b207d71200b207c7622041b3a00002004210b20040d000b2007450dc702208801218c01410021040ca2020b20a70122042094016a21a70120042d001822a801209501460dd10120042093016a2f000020042091016a2d0000209201747221a90120042097016a280000210620042098016a28020021aa0120042092016a28020021ab01200428020c21ac01200428020421ad01200428020021ae0141012109208e01410174210720042096016a290000222f20990188a7210a202fa721af01208e01210b2004280208224f21050340200921040240200b208f01470d00200b209d016a228f01200b490dd6022007208f01208f012007491b228f01209e01480dd6020240200b450d00209001200b208f01101a2290010d010c590b208f01101b229001450d580b209001200b6a2005209c01722005209b01712005209a017622081b3a00002004209d016a21092007209f016a2107200b209d016a210b2008210520080d000b0240208f01200b6b204f4f0d00200b204f6a2205200b490dd502208f01209d01742207200520052007491b2205209e01480dd50202400240208f01450d00209001208f012005101a2290010d010c87010b2005101b229001450d86010b2005218f010b209001200b6a20ae01204f1095031a024020ad01450d0020ae0110190b208e01204f6a2107209e01208e016b204f6b210820aa01210b03400240200720046a2205208f01470d002005209d016a228e012005490dd6022005209d0174228f01208e01208e01208f01491b228f01209e01480dd602024020082004470d00208f01101b2290010d010c5a0b2090012005208f01101a229001450d590b20900120076a20046a200b209c0172200b209b0171200b209a017622051b3a00002004209d016a21042005210b20050d000b0240024002402008208f016a20046b20aa014f0d00200720046a220520aa016a220b2005490dd702208f01209d01742205200b200b2005491b220b209e01480dd702208f01450d01209001208f01200b101a2290010d020c88010b208f01210b0c010b200b101b229001450d86010b20900120076a20046a20ac0120aa011095031a200720aa016a2205200b6b2107024020ab01450d0020ac0110190b200520046a2105200720046a2104024002400240024002400240024002400240024002400240024002400240024002400240024020a801209d01460d00024020a801209f01460d0020a80120a101470d022004450d05200b21060c0f0b2004450d02200b21040c080b2004450d02200b21070c0a0b2004450d03200b218f010c0f0b200b209d016a2204200b490de402200b209d01742205200420042005491b2204209e01480de402200b450d03209001200b2004101a2290010d040ca9010b200b209d016a2204200b490de302200b209d01742205200420042005491b2207209e01480de302200b450d05209001200b2007101a2290010d060ca9010b200b209d016a2204200b490de202200b209d01742205200420042005491b2206209e01480de202200b450d07209001200b2006101a2290010d080ca9010b200b209d016a2204200b490de102200b209d01742205200420042005491b228f01209e01480de102200b450d09209001200b208f01101a2290010d0a0ca9010b2004101b229001450da5010b200b21050b20900120056a209f013a0000024002400240024020042005209d016a220b470d002004209d016a220b2004490de2022004209d01742205200b200b2005491b228f01209e01480de2022004450d012090012004208f01101a2290010d020ca1010b2004218f010c020b208f01101b229001450d9f010b2004210b0b209001200b6a20af01209d01463a0000200b209d016a218e01200b209d017422042095016a21072004209f016a210b0340200721040240208e01208f01470d00208e01209d016a2205208e01490de002200b20052005200b491b228f01209e01480de0020240208e01450d00209001208e01208f01101a2290010d010c710b208f01101b229001450d700b209001208e016a2006209c01722006209b01712006209a017622051b3a00002004209f016a2107200b209f016a210b208e01209d016a218e012005210620050d000b20af01209d01470d0903400240208e01208f01470d00208e01209d016a220b208e01490de0022004200b200b2004491b228f01209e01480de0020240208e01450d00209001208e01208f01101a2290010d010c760b208f01101b229001450d750b209001208e016a200a209c0172200a209b0171200a209a0176220b1b3a00002004209f016a2104208e01209d016a218e01200b210a200b0d000c0a0b0b2007101b229001450da3010b200b21050b20900120056a209d013a0000024002400240024020072005209d016a220b470d002007209d016a22042007490ddf022007209d0174220b20042004200b491b2204209e01480ddf022007450d0120900120072004101a2290010d020c9f010b200721040c020b2004101b229001450d9d010b2007210b0b209001200b6a20a0013a000002400240024002402004200b209d016a220b470d002004209d016a220b2004490ddf022004209d01742205200b200b2005491b228f01209e01480ddf022004450d012090012004208f01101a2290010d020ca0010b2004218f010c020b208f01101b229001450d9e010b2004210b0b209001200b6a20af01209d01463a0000200b209d016a218e01200b209d017422042095016a21072004209f016a210b0340200721040240208e01208f01470d00208e01209d016a2205208e01490ddd02200b20052005200b491b228f01209e01480ddd020240208e01450d00209001208e01208f01101a2290010d010c6f0b208f01101b229001450d6e0b209001208e016a2006209c01722006209b01712006209a017622051b3a00002004209f016a2107200b209f016a210b208e01209d016a218e012005210620050d000b20af01209d01470d0603400240208e01208f01470d00208e01209d016a220b208e01490ddd022004200b200b2004491b228f01209e01480ddd020240208e01450d00209001208e01208f01101a2290010d010c740b208f01101b229001450d730b209001208e016a200a209c0172200a209b0171200a209a0176220b1b3a00002004209f016a2104208e01209d016a218e01200b210a200b0d000c070b0b2006101b229001450da1010b200b21050b20900120056a20a1013a0000024002400240024020062005209d016a220b470d002006209d016a22042006490ddc022006209d0174220b20042004200b491b2204209e01480ddc022006450d0120900120062004101a2290010d020c9e010b200621040c020b2004101b229001450d9c010b2006210b0b209001200b6a20a90120a30173220520a4017120a50172200520a90120a2017420a2017520a3014a1b3a000002400240024002402004200b209d016a220b470d002004209d016a220b2004490ddc022004209d01742205200b200b2005491b228f01209e01480ddc022004450d012090012004208f01101a2290010d020c9f010b2004218f010c020b208f01101b229001450d9d010b2004210b0b209001200b6a20a90120a60171209e01473a0000200b209d016a218e0120a701208d01470db5010c0f0b208f01101b229001450d9f010b200b21050b20900120056a209e013a00002005209d016a218e012005209d0174209f016a210403400240208e01208f01470d00208e01209d016a220b208e01490dd7022004200b200b2004491b228f01209e01480dd7020240208e01450d00209001208e01208f01101a2290010d010c6a0b208f01101b229001450d690b209001208e016a2006209c01722006209b01712006209a0176220b1b3a00002004209f016a2104208e01209d016a218e01200b2106200b0d000b0b20a701208d01470db0010c0b0b20b10120b40174210b20bb0128020021040340024020b10120b201470d0020b10120b4016a220520b101490dd502200b20052005200b491b22b20120b801480dd502024020b101450d0020b30120b10120b201101a22b3010d010c570b20b201101b22b301450d560b20b30120b1016a200420b70172200420b60171200420b5017622051b3a0000200b20b9016a210b20b10120b4016a21b1012005210420050d000b20bb0120ba016a22bb0120b001470db101410121040cd2020b20c90120c0016a21ca0120c90128020c220920c101460dd00120c901280204210a20c901280200210820bd0120c20174210520c90120c3016a280200210b20c901280208220721040340024020bd0120be01470d0020bd0120c2016a220620bd01490dd4022005200620062005491b22be0120c701480dd402024020bd01450d0020bf0120bd0120be01101a22bf010d010c590b20be01101b22bf01450d580b20bf0120bd016a200420c60172200420c50171200420c4017622061b3a0000200520c8016a210520bd0120c2016a21bd012006210420060d000b02400240024020be0120bd016b20074f0d0020bd0120076a220420bd01490dd50220be0120c201742205200420042005491b220420c701480dd50220be01450d0120bf0120be012004101a22bf010d020c87010b20be0121040c010b2004101b22bf01450d85010b20bf0120bd016a200820071095031a200720046b20bd016a21050240200a450d00200810190b024002402005450d00200720bd016a2105200421be010c010b200420c2016a22052004490dd302200420c201742206200520052006491b22be0120c701480dd302024002402004450d0020bf01200420be01101a22bf010d010c8c010b20be01101b22bf01450d8b010b200421050b20bf0120056a20093a0000200520c2016a21bd01200520c2017420c8016a21040340024020bd0120be01470d0020bd0120c2016a220520bd01490dd4022004200520052004491b22be0120c701480dd402024020bd01450d0020bf0120bd0120be01101a22bf010d010c5a0b20be01101b22bf01450d590b20bf0120bd016a200b20c60172200b20c50171200b20c4017622051b3a0000200420c8016a210420bd0120c2016a21bd012005210b20050d000b20ca0121c90120ca0120bc01470db1010c0a0b20eb0120dc016a21ec0120eb012d000d220a20dd01460dd00120eb01280208210820eb01290200212f20eb012d000c2104024020da0120d901470d0020d90120de016a220b20d901490dd20220d90120de01742205200b200b2005491b22da0120df01480dd202024020d901450d0020db0120d90120da01101a22db010d010c86010b20da01101b22db01450d85010b202fa7210920db0120d9016a20043a000020d90120de016a210420d90120de0174220b20e0016a21d901200b20e1016a21052008210b034020d90121070240200420da01470d00200420de016a22062004490dd3022005200620062005491b22da0120df01480dd30202402004450d0020db01200420da01101a22db010d010c5a0b20da01101b22db01450d590b20db0120046a200b20e40172200b20e30171200b20e2017622061b3a0000200720e1016a21d901200520e1016a2105200420de016a21042006210b20060d000b0240024002402008450d004100210b024003402004200b6a21052009200b6a2d0000220620e001460d010240200520da01470d00200520de016a22d9012005490dd702200720d90120d9012007491b22da0120df01480dd70202402005450d0020db01200520da01101a22db010d010c670b20da01101b22db01450d660b20db0120046a200b6a20e801200620e6017420e7017120dc01737620e9017120ea01723a0000200720e1016a21072008200b20de016a220b470d000b2004200b6a21050b202f20e501540d020c010b20042105202f20e501540d010b200910190b024002400240024002400240200a20e001470d0020da012005470d02200520de016a22042005490dd702200520de0174220b20042004200b491b22da0120df01480dd7022005450d0120db01200520da01101a22db010d020c92010b024020da012005470d00200520de016a22042005490dd702200520de0174220b20042004200b491b220420df01480dd7022005450d0320db0120052004101a22db010d040c93010b20da0121040c030b20da01101b22db01450d90010b20db0120056a20df013a00000c020b2004101b22db01450d8f010b20db0120056a20de013a000002400240024002402004200520de016a2205470d00200420de016a220b2004490dd602200420de01742205200b200b2005491b22da0120df01480dd6022004450d0120db01200420da01101a22db010d020c93010b200421da010c020b20da01101b22db01450d91010b200421050b20db0120056a200a20e2017120e301733a00000b200520de016a21d90120ec0121eb0120ec0120d801470db1010c0a0b20fa0120f1016a21fb0120fa01280204220920f201460dd10120fa0120f4016a280200210820fa01280200210b024020ef0120ee01470d0020ee0120f3016a220420ee01490dd10220ee0120f301742205200420042005491b22ef0120f501480dd102024020ee01450d0020f00120ee0120ef01101a22f0010d010c81010b20ef01101b22f001450d80010b20f00120ee016a200920f301463a000020ee0120f3016a210420ee0120f30174220520f6016a21ee01200520f2016a2106034020ee0121050240200420ef01470d00200420f3016a22072004490dd2022006200720072006491b22ef0120f501480dd20202402004450d0020f001200420ef01101a22f0010d010c5b0b20ef01101b22f001450d5a0b20f00120046a200b20f90172200b20f80171200b20f7017622071b3a0000200520f2016a21ee01200620f2016a2106200420f3016a21042007210b20070d000b02400240200920f301470d00200421ee010340024020ee0120ef01470d0020ee0120f3016a220420ee01490dd4022005200420042005491b22ef0120f501480dd402024020ee01450d0020f00120ee0120ef01101a22f0010d010c630b20ef01101b22f001450d620b20f00120ee016a200820f90172200820f80171200820f7017622041b3a0000200520f2016a210520ee0120f3016a21ee012004210820040d000b20fb0121fa0120fb0120ed01470db3010c010b200421ee0120fb0121fa0120fb0120ed01470db3010b20ed0121fb010cd0010b200328025421040c010b2088022080026a2204208802490dce0220880220800274220b20042004200b491b220b208202480dce0202400240208802450d002003280254208802200b101a22040d010c770b200b101b2204450d760b200341d0006a2081026a200b360200200320043602542083022802002189020b2083022089022080026a36020020042089026a208a0220870272208a0220860271208a022085027622041b3a000002402004450d002004218a02200341d0006a2081026a280200228802208302280200228902470db101411121410cf5010b2030450d0e203041047441706a21094110218b02203221040340200341086a41086a2208200441086a280200360200200320042902003703082004410d6a2d0000220a4102460d222004410c6a2d0000218c02200341306a41086a220b200828020036020020032003290308370330200341206a41086a224f200b280200360200200320032903303703200240024002400240200341d0006a41086a2206280200200341d0006a410c6a2205280200220b470d00200b41016a2207200b490dd202200b41017422aa012007200720aa01491b22aa014100480dd202200b450d012003280254200b20aa01101a22070d020c8b010b200328025421070c020b20aa01101b2207450d89010b200620aa01360200200320073602542005280200210b0b2005200b41016a3602002007200b6a41fdf9ff77208c0241037441187141107376413f7141c000723a0000024002400240024020062802002005280200220b470d00200b41016a2207200b490dd202200b410174228c0220072007208c02491b228c024100480dd202200b450d012003280254200b208c02101a22070d020c8c010b200328025421070c020b208c02101b2207450d8a010b2006208c02360200200320073602542005280200210b0b2005200b41016a3602002007200b6a200a4100473a0000200341c0006a41086a204f28020036020020032003290320370340200341086a200341c0006a200341d0006a101720032d0008228c02411a470d25200941706a2109200441106a2204208402470d000cd6010b0b200328022421040c010b209502208d026a2204209502490dcc02209502208d0274220b20042004200b491b220b208f02480dcc0202400240209502450d002003280224209502200b101a22040d010c750b200b101b2204450d740b200341206a208e026a200b360200200320043602242090022802002196020b209002209602208d026a36020020042096026a20970220940272209702209302712097022092027622041b3a000002402004450d002004219702200341206a208e026a280200229502209002280200229602470db101411521410cf8010b2033450d0c4101219802200341086a4101722199024118219a024114219b024110219c02410c219d02200341c0006a410c6a219e024201219f02422021a002410321a102410721a20241ff0021a30241807f21a402410021a502410821a602200341c0006a41086a21a702410421a802410921a90241ffffffff0321aa0241ac0121ab02417021ac02410221ad02200341086a41026a21ae02411a21af0241ffffff0721b002417821b102417c21b20241ff0121b302417f21b402413f21b50241c00021b602203521b702411721410cf9010b20b702209a026a21b80220b70228020022b902450d0c20b702209b026a28020021ba0220b702209c026a28020021bb0220b70228020c21bc0220b702290204212f410021bd02209e0241003602002003209f0237024420b902202f20a00288a722be0220a102746a21bf022003200341206a360240202fa721c002410021c10241004100460d9502410121040c96020b0240201e450d00201f10190b200241086a2105200241046a2107208e01210b03400240024002400240200728020020052802002204470d00200441016a22062004490dcd022004410174220d20062006200d491b220d4100480dcd022004450d0120022802002004200d101a22060d020c760b200228020021060c020b200d101b2206450d740b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b208e014f0d002004208e016a22052004490dc902200b4101742204200520052004491b22044100480dc902200b450d322002280200200b2004101a220b450d350c330b2002280200210b0c330b02402022450d00202310190b200241086a2105200241046a210720bd01210b03400240024002400240200728020020052802002204470d00200441016a22062004490dcc022004410174220d20062006200d491b220d4100480dcc022004450d0120022802002004200d101a22060d020c760b200228020021060c020b200d101b2206450d740b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20bd014f0d00200420bd016a22052004490dc902200b4101742204200520052004491b22044100480dc902200b450d2d2002280200200b2004101a220b450d300c2e0b2002280200210b0c2e0b02402024450d00202510190b200241086a2105200241046a210720d901210b03400240024002400240200728020020052802002204470d00200441016a22062004490dcb022004410174220d20062006200d491b220d4100480dcb022004450d0120022802002004200d101a22060d020c760b200228020021060c020b200d101b2206450d740b200220063602002007200d360200200528020021040b2005200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200241046a280200220b200241086a28020022046b20d9014f0d00200420d9016a22052004490dc702200b4101742204200520052004491b22044100480dc702200b450d282002280200200b2004101a220b450d2b0c290b2002280200210b0c290b2011214e0b204e203a460d01411c21c702411421c802410c21c902410821ca02410421cb02411021cc02410921cd0241ffffffff0321ce02417021cf02410321410cd7010b204e2802042205450d00204e20c8026a2802002106204e20ca026a2802002107204e28021021080240204e20c9026a2802002204450d00200420cb0274210b200521040340024020042d000020cd02470d00200420ca026a28020020ce0271450d00200420cb026a28020010190b200420cc026a2104200b20cf026a220b0d000b0b02402007450d00200510190b204e20c7026a214e02402006450d00200810190b204e203a470d98010b02402010450d00201110190b200341d0006a41086a28020021d601200328025421cc012003280250220541046a210d200341dc006a28020022d701210b03400240024002400240200d280200200541086a22062802002204470d00200441016a22072004490dc8022004410174220e20072007200e491b220e4100480dc8022004450d0120052802002004200e101a22070d020c730b200528020021070c020b200e101b2207450d710b20052007360200200d200e360200200628020021040b2006200441016a360200200720046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240200541046a280200220b200541086a28020022046b20d7014f0d00200420d7016a22062004490dc402200b4101742204200620062004491b22044100480dc402200b450d302005280200200b2004101a220b450d340c310b2005280200210b0c310b201d2186010b2086012071460db302411c21d002411421d102410c21d202410821d302410421d402411021d502410921d60241ffffffff0321d702417021d802410a21410cdc010b2086012802042205450db20220860120d1026a280200210620860120d3026a28020021072086012802102108024020860120d2026a2802002204450d00200420d40274210b200521040340024020042d000020d602470d00200420d3026a28020020d70271450d00200420d4026a28020010190b200420d5026a2104200b20d8026a220b0d000b0b02402007450d00200510190b20860120d0026a21860102402006450d00200810190b2086012071470d99010cb2020b203222d902208402470d130cc7010b203521b8020b20b802209102460daa02411821da02411421db02411021dc02410421dd02410921de02410821df0241ffffffff0321e002417021e102411821410cec010b20b802280200220b450da90220b80220db026a280200210420b80220dc026a280200210620b80228020c2105024020b802280204450d00200b10190b02402004450d00200420dd0274210b200521040340024020042d000020de02470d00200420df026a28020020e00271450d00200420dd026a28020010190b200420dc026a2104200b20e1026a220b0d000b0b20b80220da026a21b80202402006450d00200510190b20b802209102470da2010ca9020b20fd01220520e3026a21fd012005280200220620e402460dbd01200520e4026a28020021042005280204210b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200620e6026a220620e7024b0d00200520e5026a2802002108024002400240024020060e0700050203010607000b202c20fe01470d0b202c20e8026a2205202c490ded02202c20e802742206200520052006491b220620e902480ded02202c450d1b20fc01202c2006101a22fc010d1c0cb8010b202c20fe01470d06202c20e8026a2205202c490dec02202c20e802742206200520052006491b220720e902480dec02202c450d0e20fc01202c2007101a22fc010d0f0cb4010b202c20fe01470d06202c20e8026a2205202c490deb02202c20e802742206200520052006491b220720e902480deb02202c450d1020fc01202c2007101a22fc010d110cb4010b202c20fe01470d06202c20e8026a2205202c490dea02202c20e802742206200520052006491b220720e902480dea02202c450d1220fc01202c2007101a22fc010d130cb4010b202c20fe01470d06202c20e8026a2205202c490de902202c20e802742206200520052006491b220620e902480de902202c450d1420fc01202c2006101a22fc010d150cac010b202c20fe01470d07202c20e8026a2205202c490de802202c20e802742206200520052006491b220620e902480de802202c450d1920fc01202c2006101a22fc010d1a0cb4010b202c20fe01470d07202c20e8026a2205202c490de702202c20e802742206200520052006491b220620e902480de702202c450d1b20fc01202c2006101a22fc010d1c0cb4010b202c20fe01470d07202c20e8026a2205202c490de602202c20e802742206200520052006491b220620e902480de602202c450d1d20fc01202c2006101a22fc010d1e0cb4010b202c21070c090b202c21070c0b0b202c21070c0d0b202c21060c0f0b202c21060c110b202c21060c130b202c21060c150b202c21060c170b2007101b22fc01450da5010b202c21fe010b20fc0120fe016a20f2023a000020fe0120e8026a21050340024002400240024020072005470d00200720e8026a22052007490de002200720e802742206200520052006491b220620e902480de0022007450d0120fc0120072006101a22fc010d020c760b200721060c020b2006101b22fc01450d740b20072105200621070b20fc0120056a200b20ec0272200b20eb0271200b20ea027622fe011b3a0000200520e8026a210520fe01210b20fe010d000b0340024002400240024020062005470d00200620e8026a220b2006490de002200620e802742205200b200b2005491b220b20e902480de0022006450d0120fc012006200b101a22fc010d020c770b2006210b0c020b200b101b22fc01450d750b20062105200b21060b20fc0120056a200420ec0272200420eb0271200420ea027622fe011b3a0000200520e8026a210520fe01210420fe010d000b200820ef027121fe01200820eb027121090240024002400240200820ea027522040d0020fe01450d010b0340024020fe0120f00271450d00200420e602460d020b0240024002400240200b2005470d00200b20e8026a2205200b490de302200b20e802742206200520052006491b220620e902480de302200b450d0120fc01200b2006101a22fc010d020c96010b200b21060c020b2006101b22fc01450d94010b200b21052006210b0b20fc0120056a200820ec02723a0000200420ef027121fe01200420eb02712109200520e8026a210520042108200420ea02752207210420070d002006210b2007210420fe010d000b20062005470d020c010b200b22062005470d010b200620e8026a22042006490ddc02200620e80274220b20042004200b491b222c20e902480ddc022006450d1720fc012006202c101a22fc010d180cab010b2006212c0c180b2007101b22fc01450da3010b202c21fe010b20fc0120fe016a20ee023a000020fe0120e8026a21050340024002400240024020072005470d00200720e8026a22052007490ddd02200720e802742206200520052006491b220620e902480ddd022007450d0120fc0120072006101a22fc010d020c750b200721060c020b2006101b22fc01450d730b20072105200621070b20fc0120056a200b20ec0272200b20eb0271200b20ea027622fe011b3a0000200520e8026a210520fe01210b20fe010d000b0340024002400240024020062005470d00200620e8026a220b2006490ddd02200620e802742205200b200b2005491b220b20e902480ddd022006450d0120fc012006200b101a22fc010d020c760b2006210b0c020b200b101b22fc01450d740b20062105200b21060b20fc0120056a200420ec0272200420eb0271200420ea027622fe011b3a0000200520e8026a210520fe01210420fe010d000b200820ef027121fe01200820eb027121090240024002400240200820ea027522040d0020fe01450d010b0340024020fe0120f00271450d00200420e602460d020b0240024002400240200b2005470d00200b20e8026a2205200b490de002200b20e802742206200520052006491b220620e902480de002200b450d0120fc01200b2006101a22fc010d020c94010b200b21060c020b2006101b22fc01450d92010b200b21052006210b0b20fc0120056a200820ec02723a0000200420ef027121fe01200420eb02712109200520e8026a210520042108200420ea02752207210420070d002006210b2007210420fe010d000b20062005470d020c010b200b22062005470d010b200620e8026a22042006490dd902200620e80274220b20042004200b491b222c20e902480dd9022006450d1720fc012006202c101a22fc010d180ca9010b2006212c0c180b2007101b22fc01450da1010b202c21fe010b20fc0120fe016a20f1023a000020fe0120e8026a21050340024002400240024020072005470d00200720e8026a22052007490dda02200720e802742206200520052006491b220620e902480dda022007450d0120fc0120072006101a22fc010d020c740b200721060c020b2006101b22fc01450d720b20072105200621070b20fc0120056a200b20ec0272200b20eb0271200b20ea027622fe011b3a0000200520e8026a210520fe01210b20fe010d000b0340024002400240024020062005470d00200620e8026a220b2006490dda02200620e802742205200b200b2005491b220b20e902480dda022006450d0120fc012006200b101a22fc010d020c750b2006210b0c020b200b101b22fc01450d730b20062105200b21060b20fc0120056a200420ec0272200420eb0271200420ea027622fe011b3a0000200520e8026a210520fe01210420fe010d000b200820ef027121fe01200820eb027121090240024002400240200820ea027522040d0020fe01450d010b0340024020fe0120f00271450d00200420e602460d020b0240024002400240200b2005470d00200b20e8026a2205200b490ddd02200b20e802742206200520052006491b220620e902480ddd02200b450d0120fc01200b2006101a22fc010d020c92010b200b21060c020b2006101b22fc01450d90010b200b21052006210b0b20fc0120056a200820ec02723a0000200420ef027121fe01200420eb02712109200520e8026a210520042108200420ea02752207210420070d002006210b2007210420fe010d000b20062005470d020c010b200b22062005470d010b200620e8026a22042006490dd602200620e80274220b20042004200b491b222c20e902480dd6022006450d1720fc012006202c101a22fc010d180ca7010b2006212c0c180b2006101b22fc01450d97010b202c21fe010b20fc0120fe016a20e9023a000020fe0120e8026a21fe0103400240024002400240200620fe01470d00200620e8026a22052006490dd702200620e8027422fe012005200520fe01491b220520e902480dd7022006450d0120fc0120062005101a22fc010d020c690b200621050c020b2005101b22fc01450d670b200621fe01200521060b20fc0120fe016a200b20ec0272200b20eb0271200b20ea027622071b3a000020fe0120e8026a21fe012007210b20070d000b03400240024002400240200520fe01470d00200520e8026a220b2005490dd702200520e802742206200b200b2006491b222c20e902480dd7022005450d0120fc012005202c101a22fc010d020c6a0b2005212c0c020b202c101b22fc01450d680b200521fe01202c21050b20fc0120fe016a200420ec0272200420eb0271200420ea0276220b1b3a000020fe0120e8026a21fe01200b2104200b0d000c0d0b0b2006101b22fc01450d9c010b202c21fe010b20fc0120fe016a20e8023a000020fe0120e8026a21fe0103400240024002400240200620fe01470d00200620e8026a22052006490dd402200620e8027422fe012005200520fe01491b220520e902480dd4022006450d0120fc0120062005101a22fc010d020c700b200621050c020b2005101b22fc01450d6e0b200621fe01200521060b20fc0120fe016a200b20ec0272200b20eb0271200b20ea027622071b3a000020fe0120e8026a21fe012007210b20070d000b03400240024002400240200520fe01470d00200520e8026a220b2005490dd402200520e802742206200b200b2006491b222c20e902480dd4022005450d0120fc012005202c101a22fc010d020c710b2005212c0c020b202c101b22fc01450d6f0b200521fe01202c21050b20fc0120fe016a200420ec0272200420eb0271200420ea0276220b1b3a000020fe0120e8026a21fe01200b2104200b0d000c0a0b0b2006101b22fc01450d9a010b202c21fe010b20fc0120fe016a20ed023a000020fe0120e8026a21fe0103400240024002400240200620fe01470d00200620e8026a22052006490dd102200620e8027422fe012005200520fe01491b220520e902480dd1022006450d0120fc0120062005101a22fc010d020c6f0b200621050c020b2005101b22fc01450d6d0b200621fe01200521060b20fc0120fe016a200b20ec0272200b20eb0271200b20ea027622071b3a000020fe0120e8026a21fe012007210b20070d000b03400240024002400240200520fe01470d00200520e8026a220b2005490dd102200520e802742206200b200b2006491b222c20e902480dd1022005450d0120fc012005202c101a22fc010d020c700b2005212c0c020b202c101b22fc01450d6e0b200521fe01202c21050b20fc0120fe016a200420ec0272200420eb0271200420ea0276220b1b3a000020fe0120e8026a21fe01200b2104200b0d000c070b0b2006101b22fc01450d98010b202c21fe010b20fc0120fe016a20e7023a000020fe0120e8026a21fe0103400240024002400240200620fe01470d00200620e8026a22052006490dce02200620e8027422fe012005200520fe01491b220520e902480dce022006450d0120fc0120062005101a22fc010d020c6e0b200621050c020b2005101b22fc01450d6c0b200621fe01200521060b20fc0120fe016a200b20ec0272200b20eb0271200b20ea027622071b3a000020fe0120e8026a21fe012007210b20070d000b03400240024002400240200520fe01470d00200520e8026a220b2005490dce02200520e802742206200b200b2006491b222c20e902480dce022005450d0120fc012005202c101a22fc010d020c6f0b2005212c0c020b202c101b22fc01450d6d0b200521fe01202c21050b20fc0120fe016a200420ec0272200420eb0271200420ea0276220b1b3a000020fe0120e8026a21fe01200b2104200b0d000c040b0b2006101b22fc01450d96010b202c21fe010b20fc0120fe016a20ea023a000020fe0120e8026a21fe0103400240024002400240200620fe01470d00200620e8026a22052006490dcb02200620e8027422fe012005200520fe01491b220520e902480dcb022006450d0120fc0120062005101a22fc010d020c6d0b200621050c020b2005101b22fc01450d6b0b200621fe01200521060b20fc0120fe016a200b20ec0272200b20eb0271200b20ea027622071b3a000020fe0120e8026a21fe012007210b20070d000b03400240024002400240200520fe01470d00200520e8026a220b2005490dcb02200520e802742206200b200b2006491b222c20e902480dcb022005450d0120fc012005202c101a22fc010d020c6e0b2005212c0c020b202c101b22fc01450d6c0b200521fe01202c21050b20fc0120fe016a200420ec0272200420eb0271200420ea0276220b1b3a000020fe0120e8026a21fe01200b2104200b0d000b0b20fd0120e202470dac010c090b202c101b22fc01450d93010b200621050b20fc0120056a20093a0000200520e8026a21fe0120fd0120e202470daa010c060b202c101b22fc01450d91010b200621050b20fc0120056a20093a0000200520e8026a21fe0120fd0120e202470da9010c030b202c101b22fc01450d8f010b200621050b20fc0120056a20093a0000200520e8026a21fe0120fd0120e202470da5010b20e20221fd010cbc010b024020f60220f5026a280200450d0020f60228020010190b024020f60220f8026a280200220b450d0020f60228020c2104200b20f50274210b0340024020042d000020fa02470d00200420fb026a28020020fc0271450d00200420f5026a28020010190b200420f9026a2104200b20fd026a220b0d000b0b20f60220f4026a2104024020f60220f9026a280200450d0020f60220f3026a28020010190b200421f602200420f702470da5010b200141086a280200450da502200141046a2802001019200341e0006a24000f0b024020810320fe026a280200220b450d002081032802042104200b20800374210b0340024020042d0000208603470d0020042083036a28020020870371450d0020042080036a28020010190b20042085036a2104200b2088036a220b0d000b0b02402081032083036a280200450d002081032080036a28020010190b20810320ff026a210402402081032084036a280200450d0020810328021010190b20042181032004208203470da4010b200141086a280200450da302200141046a2802001019200341e0006a24000f0b0240208a03280208220b450d00208a032802002104200b20890374210b0340024020042d0000208d03470d002004208e036a280200208f0371450d0020042089036a28020010190b2004208c036a2104200b2090036a220b0d000b0b208a03208c036a21040240208a032089036a280200450d00208a0328020010190b2004218a032004208b03470da3010b200141086a280200450da102200141046a2802001019200341e0006a24000f0b02402094032091036a280200220b450d002094032802042104200b20930374210b0340024020042d0000209903470d0020042096036a280200209a0371450d0020042093036a28020010190b20042098036a2104200b209b036a220b0d000b0b02402094032096036a280200450d002094032093036a28020010190b2094032092036a210402402094032097036a280200450d0020940328021010190b20042194032004209503470da2010b200141086a280200450d9f02200141046a2802001019200341e0006a24000f0b20ac032105024003402005209e036a28020022080d0120ab0320a2036a21ab03209f03200520a3036a2205470d000cc1010b0b200520a3036a21ac0320ab0320a2036a210a20aa0320a4036a21aa03200520a5036a290200212f200528020021ad03200341c0006a20a5036a220928020021042003280244210b034002400240024002402004200b470d00200b20a2036a2206200b490db702200b20a203742207200620062007491b220720a103480db702200b450d012003280240200b2007101a22060d020c740b200328024021060c020b2007101b2206450d720b20032007360244200320063602402007210b0b2009200420a2036a2207360200200620046a20ab0320a8037220ab0320a7037120ab0320a6037622061b3a000020072104200621ab0320060d000b200341086a20a5036a202f3703002003200836020c200320ad03360208200341d0006a200341086a200341c0006a107420032d005022ad0320a903470d2d024020a0032005460d00200a21ab0320aa030d8a010b200541106a229d03209c03470dbe010cbd010b20b403220620b0036a21b403024020062802042204450d000240200620b1036a280200220b450d00200b20b1036c210b0340024020042802002205450d00200420ae036a280200450d00200510190b200420b1036a2104200b20b3036a220b0d000b0b200620b2036a280200450d00200620ae036a28020010190b20b40320af03470da7010b2016450d00201710190b2003411c6a206c360200200341186a206b3602002003206a36021420034284808080c00037020c20032061360208200341d0006a200341086a200210e302200320032900513703402003200341d0006a41086a29000037004720032d00502204411a470d01410021cd014101210d4101210e0b410121ce010c1d0b20002003290340370001200020043a0000200041086a20032900473700000c1e0b200441106a22d902208402460db5010b411021b503410d21b603410221b703410421b803410921b903410821ba0341ffffffff0321bb03417021bc03411321410cd3010b20d90220b6036a2d000020b703460db00120d902280204210620d9022802002105024020d9022802082204450d00200420b80374210b200521040340024020042d000020b903470d00200420ba036a28020020bb0371450d00200420b8036a28020010190b200420b5036a2104200b20bc036a220b0d000b0b20d90220b5036a21d90202402006450d00200510190b20d902208402470d8d01410a21040ca8020b20032d000b21bd0320032f000921be03200829030021bf03200328020c21c0032009450d01411021c103200441106a21c203410d21c303410221c403410421c503410921c603410821c70341ffffffff0321c803417021c903411421410cd3010b20c20320c3036a2d000020c403460d0020c203280204210620c2032802002105024020c2032802082204450d00200420c50374210b200521040340024020042d000020c603470d00200420c7036a28020020c80371450d00200420c5036a28020010190b200420c1036a2104200b20c9036a220b0d000b0b20c20320c1036a21c20302402006450d00200510190b20c203208402470d8c010b20bd03208b0274210402402031450d00203210190b20be0320047221040240200341d0006a41086a280200450d00200328025410190b200020043b00012000208c023a0000200041036a20044110763a0000200041086a20bf03370000200041046a20c0033600004100210c410121cb01410b21040ca5020b20032d000b21ca0320032f000921cb03200341106a29030021cc03200328020c21cd030240204f450d00200910190b411021ce03204e203a460d01411c21cf03411421d003410c21d103410821d203410421d303411021d403410921d50341ffffffff0321d603417021d703410421410cba010b204e2802042205450d00204e20d0036a2802002106204e20d2036a2802002107204e28021021080240204e20d1036a2802002204450d00200420d30374210b200521040340024020042d000020d503470d00200420d2036a28020020d60371450d00200420d3036a28020010190b200420d4036a2104200b20d7036a220b0d000b0b02402007450d00200510190b204e20cf036a214e02402006450d00200810190b204e203a470d7a0b20ca0320ce0374210402402010450d00201110190b20cb0320047221040240200341d0006a41086a280200450d00200328025410190b200020043b0001200020503a0000200041036a20044110763a0000200041086a20cc03370000200041046a20cd0336000041002106410121cb014101210c410121054101210b0cf3010b20032d000b21d80320032f000921d903200341106a29030021da03200328020c21db030240208701450d0020880110190b411021dc032086012071460d01411c21dd03411421de03410c21df03410821e003410421e103411021e203410921e30341ffffffff0321e403417021e503410b21410cc0010b2086012802042205450d0020860120de036a280200210620860120e0036a28020021072086012802102108024020860120df036a2802002204450d00200420e10374210b200521040340024020042d000020e303470d00200420e0036a28020020e40371450d00200420e1036a28020010190b200420e2036a2104200b20e5036a220b0d000b0b02402007450d00200510190b20860120dd036a21860102402006450d00200810190b2086012071470d7c0b20d80320dc037421040240201c450d00201d10190b20d90320047221040240200341d0006a41086a280200450d00200328025410190b200020043b00012000208a013a0000200041036a20044110763a0000200041086a20da03370000200041046a20db0336000041002105410121cb014101210c0b4101210b0cee010b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420d9016a360200200b20046a20db0120d9011095031a410021d7014101210d024020da01450d0020db0110190b4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d201410121d301410121d401410121d501410121d6010c97020b20044101101c000b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a200420bd016a360200200b20046a20bf0120bd011095031a410021d1014101210d024020be01450d0020bf0110190b4101210e410121cd01410121ce01410121cf01410121d0010c8d020b20044101101c000b2004101b220b450d020b2002200b360200200241046a2004360200200241086a28020021040b200241086a2004208e016a360200200b20046a209001208e011095031a410021d6014101210d0240208f01450d0020900110190b4101210e410121cd01410121ce01410121cf01410121d001410121d101410121d201410121d301410121d401410121d5010c8e020b20044101101c000b2004101b220b450d030b2005200b360200200541046a2004360200200541086a28020021040b200541086a200420d7016a360200200b20046a20cc0120d7011095031a024020d601450d0020cc0110190b410021ce014101210d4101210e410121cd010b410121cf010cfe010b20044101101c000b41002107410121cb014101210c410121054101210b4101210620012d00002204410e4d0dde010cdf010b024020ec0320eb036a280200450d0020ec0328020010190b024020ec0320ee036a280200220b450d0020ec0328020c2104200b20eb0374210b0340024020042d000020f003470d00200420f1036a28020020f20371450d00200420eb036a28020010190b200420ef036a2104200b20f3036a220b0d000b0b20ec0320ea036a2104024020ec0320ef036a280200450d0020ec0320e9036a28020010190b200421ec03200420ed03470d7c0ce1010b024020f70320f4036a280200220b450d0020f7032802042104200b20f60374210b0340024020042d000020fc03470d00200420f9036a28020020fd0371450d00200420f6036a28020010190b200420fb036a2104200b20fe036a220b0d000b0b024020f70320f9036a280200450d0020f70320f6036a28020010190b20f70320f5036a2104024020f70320fa036a280200450d0020f70328021010190b200421f703200420f803470d7c0ce5010b0240208004280208220b450d002080042802002104200b20ff0374210b0340024020042d0000208304470d0020042084046a28020020850471450d00200420ff036a28020010190b20042082046a2104200b2086046a220b0d000b0b2080042082046a2104024020800420ff036a280200450d0020800428020010190b20042180042004208104470d7c0cea010b0240208a042087046a280200220b450d00208a042802042104200b20890474210b0340024020042d0000208f04470d002004208c046a28020020900471450d0020042089046a28020010190b2004208e046a2104200b2091046a220b0d000b0b0240208a04208c046a280200450d00208a042089046a28020010190b208a042088046a21040240208a04208d046a280200450d00208a0428021010190b2004218a042004208b04470d7c0ceb010b20930422062095046a219304024020062802042204450d00024020062092046a280200220b450d00200b2092046c210b0340024020042802002205450d0020042097046a280200450d00200510190b20042092046a2104200b2098046a220b0d000b0b20062096046a280200450d0020062097046a28020010190b209304209404470d7c0b200141106a280200450df4012001410c6a2802001019200341e0006a24000f0b209d0322042099046a219d03024020042802042206450d002004280208210702402004209a046a2802002204450d002004209a046c210b200621040340024020042802002205450d002004209c046a280200450d00200510190b2004209a046a2104200b209b046a220b0d000b0b2007450d00200610190b209d03209c03470d7b410e21040c85020b20b802280200220b450dd30120b80220a4046a280200210420b802209d046a280200210620b80228020c2105024020b802280204450d00200b10190b02402004450d00200420a50474210b200521040340024020042d000020a604470d00200420a1046a28020020a70471450d00200420a5046a28020010190b2004209d046a2104200b20a8046a220b0d000b0b20b80220a3046a21b80202402006450d00200510190b20b802209102470d7b0cd3010b20aa04220620ac046a21aa04024020062802042204450d000240200620a9046a280200220b450d00200b20a9046c210b0340024020042802002205450d00200420ae046a280200450d00200510190b200420a9046a2104200b20af046a220b0d000b0b200620ad046a280200450d00200620ae046a28020010190b20aa0420ab04470d7c0cea010b20032d005321b00420032f005121b104200341d0006a20a5036a29030021e603200328025421e703410421b204201720154104746a41706a2005460d01411021b304200541106a21b404410c21b504417421b604412721410cce010b20b404220420b3046a21b404024020042802042206450d00200428020821070240200420b5046a2802002204450d00200420b5046c210b200621040340024020042802002205450d00200420b2046a280200450d00200510190b200420b5046a2104200b20b6046a220b0d000b0b2007450d00200610190b20b404209c03470d7b0b02402016450d00201710190b20ad03411a470d010b200341c8006a280200216620032802442165200328024021644102211941002167410121634100216841002162410121694101101b226a0d7a0c82020b20b10420b00420a3037472220441ffffff0771220b411076411074200b41087641ff017141087472210b200441ff0171210402402003280244450d00200328024010190b200b20047221e8030c8a010b20b2014101101c000b208f014101101c000b208f014101101c000b20be014101101c000b20be014101101c000b20da014101101c000b20534101101c000b20ef014101101c000b20074101101c000b20064101101c000b20074101101c000b20064101101c000b20534101101c000b20ef014101101c000b20da014101101c000b208f014101101c000b208f014101101c000b208f014101101c000b20054101101c000b202c4101101c000b208f014101101c000b208f014101101c000b20064101101c000b200b4101101c000b20064101101c000b200b4101101c000b20064101101c000b200b4101101c000b20054101101c000b202c4101101c000b20054101101c000b202c4101101c000b20054101101c000b202c4101101c000b20054101101c000b202c4101101c000b200b4101101c000b200b4101101c000b200b4101101c000b200b4101101c000b200d4101101c000b200d4101101c000b200d4101101c000b200e4101101c000b200b4101101c000b20534101101c000b20ef014101101c000b20054101101c000b200b4101101c000b20044101101c000b20da014101101c000b20064101101c000b20064101101c000b20064101101c000b20be014101101c000b20044101101c000b20aa014101101c000b208c024101101c000b20da014101101c000b20044101101c000b20da014101101c000b20074101101c000b208f014101101c000b20044101101c000b208f014101101c000b20044101101c000b208f014101101c000b20064101101c000b20044101101c000b20074101101c000b20064101101c000b208f014101101c000b20074101101c000b20074101101c000b20074101101c000b20064101101c000b20064101101c000b20064101101c000b20064101101c000b202c4101101c000b202c4101101c000b202c4101101c000b410121410c3c0b410221410c3d0b410321410c3e0b410421410c3f0b410521410c3f0b410621410c3f0b410821410c400b410a21410c420b410b21410c430b410c21410c430b410c21410c430b410d21410c430b410e21410c430b410f21410c430b411021410c430b411021410c430b411221410c440b411321410c450b411421410c460b411621410c470b411821410c490b411921410c490b411921410c490b411921410c490b411921410c490b411a21410c4a0b411b21410c4b0b411c21410c4c0b411d21410c4d0b411e21410c4d0b411f21410c4d0b412021410c4d0b412121410c4d0b412221410c4e0b412321410c4e0b412421410c4f0b412521410c500b412621410c500b412721410c500b410021040c84010b410221040c83010b410221040c82010b410321040c81010b410421040c80010b410521040c7f0b410621040c7e0b410621040c7d0b410721040c7c0b410721040c7b0b410821040c7a0b410821040c790b410821040c780b410a21040c770b410a21040c760b410a21040c750b410a21040c740b410c21040c730b410e21040c720b410d21040c710b410e21040c700b410f21040c6f0b410f21040c6e0b410f21040c6d0b410f21040c6c0b410f21040c6b0b410f21040c6a0b410f21040c690b410f21040c680b410f21040c670b410f21040c660b410f21040c650b410f21040c640b410f21040c630b410f21040c620b410f21040c610b410f21040c600b410f21040c5f0b410f21040c5e0b410f21040c5d0b410f21040c5c0b410f21040c5b0b410f21040c5a0b410f21040c590b410f21040c580b410f21040c570b410f21040c560b410f21040c550b410f21040c540b410f21040c530b410f21040c520b410f21040c510b410f21040c500b410f21040c4f0b410f21040c4e0b410f21040c4d0b410f21040c4c0b410f21040c4b0b410f21040c4a0b410f21040c490b410f21040c480b410f21040c470b410f21040c460b410f21040c450b410f21040c440b410f21040c430b410f21040c420b410f21040c410b410f21040c400b410f21040c3f0b410f21040c3e0b410f21040c3d0b410f21040c3c0b410f21040c3b0b410f21040c3a0b410f21040c390b410f21040c380b410f21040c370b410f21040c360b410f21040c350b410f21040c340b410f21040c330b410221040b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e06000102040607070b208c01280200210b03400240024002400240208901280200207f2802002204470d0020042080016a22052004490d4f2004208001742206200520052006491b2206208101480d4f2004450d01200328025420042006101a22050d020c0d0b200328025421050c020b2006101b2205450d0b0b208901200636020020032005360254207f28020021040b207f20042080016a360200200520046a200b207e72200b207d71200b207c7622041b3a00002004210b20040d000b208c012084016a228c01208b01470d100c3b0b200328024421040c010b20bd022098026a220420bd02490d4820bd0220980274220b20042004200b491b220b20a502480d480240024020bd02450d00200328024420bd02200b101a22040d010c0a0b200b101b2204450d090b20a702200b36020020032004360244209e0228020021c1020b209e0220c1022098026a360200200420c1026a20be0220a4027220be0220a3027120be0220a2027622041b3a000002402004450d00200421be0220a70228020022bd02209e0228020022c102470d0f410221040c140b20bf0220b902460d0120b90221c202410321040c130b20c20220a6026a21c30220c202290200222f20a00288a7220420b3027120a802460d102004209a0274209a02752107202fa7210b0340024002400240024020a702280200209e022802002204470d0020042098026a22052004490d4b2004209802742206200520052006491b220620a502480d4b2004450d01200328024420042006101a22050d020c0a0b200328024421050c020b2006101b2205450d080b20a702200636020020032005360244209e0228020021040b209e0220042098026a360200200520046a200b20a40272200b20a30271200b20a2027622041b3a00002004210b20040d000b024002400240024020a702280200209e022802002204470d0020042098026a220b2004490d4a2004209802742205200b200b2005491b220520a502480d4a2004450d01200328024420042005101a220b0d020c0c0b2003280244210b0c020b2005101b220b450d0a0b20a70220053602002003200b360244209e0228020021040b209e0220042098026a360200200b20046a200720b40273220420b5027120b602722004200720b4024a1b3a000020c30221c20220c30220bf02470d0e20bf0220bf0222c302470d110c030b20b90221c302410421040c110b20bf0220c302460d01410521040c100b20c3022d0004210420c30220a6026a21c302200420a802470d0c0b024020c002450d0020b90210190b20bc0220ba0220a8027422046a2106024002400240024002400240024002400240024020ba02450d0020bc02209a026a210b200420ac026a210720bc022104034020042d0000210520ae02200420a1026a2d00003a0000200320042098026a2f00003b0108200520ab02460d02200341306a20ad026a220820ae022d00003a0000200320032f01083b0130200420a8026a290200212f200341086a209d026a2004209d026a28020036020020990220032f01303b000020990220ad026a20082d00003a0000200320053a00082003202f37020c200341d0006a200341086a200341c0006a102a20032d005022c40220af02462205450d05200b209c026a210b200720ac026a21072004209c026a22042006470d000c040b0b20bc0222042006460d020c010b2004209c026a22042006460d010b03400240024020042d0000220b20a902460d00200b20ab02470d010c030b200420a6026a28020020aa0271450d00200420a8026a28020010190b2004209c026a22042006470d000b0b024020bb02450d0020bc0210190b20a702280200214f2003280244210a20032802402105209e0228020022b702210b03400240024002400240200520a6026a22082802002005209d026a22062802002204470d0020042098026a22072004490d4d2004209802742209200720072009491b220920a502480d4d2004450d01200520a8026a28020020042009101a22070d020c0e0b200520a8026a28020021070c020b2009101b2207450d0c0b20082009360200200520a8026a2007360200200628020021040b200620042098026a360200200720046a200b20a40272200b20a30271200b20a2027622041b3a00002004210b20040d000b02402008280200220b200628020022046b20b7024f0d00200420b7026a22072004490d49200b209802742204200720072004491b220420a502480d49200b450d02200520a8026a280200200b2004101a220b0d030c0c0b200520a8026a280200210b0c030b20032d0053210820032f00512109200341d0006a20a6026a29030021c502200328025421c60202402007450d00034002400240200b20b1026a22042d0000220720a902460d00200720ab02470d010c030b200b28020020aa0271450d00200b20b2026a28020010190b200b209c026a210b2004209c026a2006470d000b0b024020bb02450d0020bc0210190b024020a702280200450d00200328024410190b20050d030c040b2004101b220b450d090b20082004360200200520a8026a200b360200200628020021040b2006200420b7026a360200200b20046a200a20b7021095031a204f450d00200a10190b20b80221b70220b802209102470d070c300b4110219d0420092008209c027472229e0420b002712204209c0276411074219f0441ff0121a004410821a104200420a6027641ff017141087421a20420b802209102460d0f411821a304411421a404410421a504410921a60441ffffffff0321a704417021a804412421410c070b20064101101c000b20064101101c000b200b4101101c000b20094101101c000b20054101101c000b20044101101c000b41172141410f21040c390b410f21040c380b410021040c050b410121040c040b410321040c030b410421040c020b410421040c010b410521040c000b0b209f0420a204722104209e0420a00471210b02402034450d00203510190b2004200b7221040240200341206a41086a280200450d00200328022410190b200020043b0001200020c4023a0000200041036a20044110763a0000200041086a20c502370000200041046a20c6023600004100210b410121cb014101210c410121050b410121060b4101210720012d00002204410e4b0d010b024020040e0f000c0b0a05070d0e12011003080602000b200141086a280200450d1b200141046a2802001019200341e0006a24000f0b200110d302200341e0006a24000f0b0240200141086a280200450d00200141046a28020010190b0240200141146a2802002202450d00200141186a280200450d00200210190b200141246a280200450d19200141206a2802001019200341e0006a24000f0b200b450d18410c21e9032001410c6a2802002204450d00411821ea03410421eb03200141046a28020022ec03200441186c6a21ed03411421ee03411021ef03410921f003410821f10341ffffffff0321f203417021f303411e21410c130b200141086a280200450d17200141046a2802001019200341e0006a24000f0b200141086a280200450d16200141046a2802001019200341e0006a24000f0b2007450d15200141046a2d000022044102460d0d20044101460d0c20040d0f2001410c6a280200450d15200141086a2802001019200341e0006a24000f0b200141086a280200450d14200141046a2802001019200341e0006a24000f0b2006450d13410c21f4032001410c6a2802002204450d00411c21f503410421f603200141046a28020022f7032004411c6c6a21f803410821f903411421fa03411021fb03410921fc0341ffffffff0321fd03417021fe03411f21410c0f0b200141086a280200450d12200141046a2802001019200341e0006a24000f0b02402001410c6a2802002204450d00200141046a2802002102200441286c210403400240200241046a280200450d00200228020010190b0240200241106a280200450d002002410c6a28020010190b200241286a2102200441586a22040d000b0b200141086a280200450d11200141046a2802001019200341e0006a24000f0b02402001410c6a2802002204450d00200141046a28020021022004410474210403400240200241046a280200450d00200228020010190b200241106a2102200441706a22040d000b0b200141086a280200450d10200141046a2802001019200341e0006a24000f0b20cb01450d0f0240200141086a280200450d00200141046a28020010190b200141146a280200450d0f200141106a2802001019200341e0006a24000f0b200141086a280200450d0e200141046a2802001019200341e0006a24000f0b200c450d0d2001410c6a2802002204450d00410421ff03200141046a28020022800420044104746a21810441102182044109218304410821840441ffffffff032185044170218604412021410c0a0b200141086a280200450d0c200141046a2802001019200341e0006a24000f0b2005450d0b410c2187042001410c6a2802002204450d00411c2188044104218904200141046a280200228a042004411c6c6a218b044108218c044114218d044110218e044109218f0441ffffffff032190044170219104412121410c090b200141086a280200450d0a200141046a2802001019200341e0006a24000f0b02402001410c6a2802002204450d00200141046a2802002102200441146c210403400240200241046a280200450d00200228020010190b200241146a21022004416c6a22040d000b0b200141086a280200450d09200141046a2802001019200341e0006a24000f0b0240200141146a2802002204450d002001410c6a28020021022004410c6c2104034002402002280200220b450d00200241046a280200450d00200b10190b2002410c6a2102200441746a22040d000b0b200141106a280200450d082001410c6a2802001019200341e0006a24000f0b200141146a2802002204450d00410c21a9042001410c6a28020022aa0420044104746a21ab04411021ac04410821ad04410421ae04417421af04412621410c060b200141106a280200450d062001410c6a2802001019200341e0006a24000f0b2001410c6a280200450d05200141086a2802001019200341e0006a24000f0b410f21040c160b410f21040c150b410f21040c140b410f21040c130b410f21040c120b200341e0006a24000f0b02402034450d00203510190b200341206a41086a28020021d601200328022421cc012003280220220541046a210d2003412c6a28020022d701210b03400240024002400240200d280200200541086a22072802002204470d00200441016a22062004490d172004410174220e20062006200e491b220e4100480d172004450d0120052802002004200e101a22060d020c070b200528020021060c020b200e101b2206450d050b20052006360200200d200e360200200728020021040b2007200441016a360200200620046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240024002400240200541046a280200220b200541086a28020022046b20d7014f0d00200420d7016a22062004490d16200b4101742204200620062004491b22044100480d16200b450d012005280200200b2004101a220b450d050c020b2005280200210b0c020b2004101b220b450d030b2005200b360200200541046a2004360200200541086a28020021040b200541086a200420d7016a360200200b20046a20cc0120d7011095031a024020d601450d0020cc0110190b410021cf014101210d4101210e410121cd01410121ce010b410121d0010c040b20044101101c000b200e4101101c000b0240208701450d0020880110190b2086012185012086012071470d0b0b0240201c450d00201d10190b200341d0006a41086a28020021d601200328025421cc012003280250220541046a210d200341dc006a28020022d701210b03400240024002400240200d280200200541086a22062802002204470d00200441016a22072004490d122004410174220e20072007200e491b220e4100480d122004450d0120052802002004200e101a22070d020c0e0b200528020021070c020b200e101b2207450d0c0b20052007360200200d200e360200200628020021040b2006200441016a360200200720046a200b41807f72200b41ff0071200b41077622041b3a00002004210b20040d000b0240024002400240200541046a280200220b200541086a28020022046b20d7014f0d00200420d7016a22062004490d11200b4101742204200620062004491b22044100480d11200b450d012005280200200b2004101a220b450d0c0c020b2005280200210b0c020b2004101b220b450d0a0b2005200b360200200541046a2004360200200541086a28020021040b200541086a200420d7016a360200200b20046a20cc0120d7011095031a024020d601450d0020cc0110190b410021d0014101210d4101210e410121cd01410121ce01410121cf010b410121d1010b410121d2010b410121d3010b410121d4010b410121d5010b410121d6010b410121d7010b410121cc01410921040c030b20044101101c000b200e4101101c000b41092141410f21040c000b0b101d000b101d000b41014101101c000bb45105067f067e0a7f027e037f230041b0066b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417e6a220441034b0d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020040e0400030102000b4128210441e580c000210520022d000120022d0000720d39200141c0006a28020021062001413c6a2802002107200141386a2802002108200141306a2903002109200141286a290300210a200141206a290300210b200141186a290300210c200141106a290300210d200141086a290300210e200341c8036a41086a22024200370300200342003703c8034196f2c1004118200341c8036a1001200341a8016a41086a2002290300370300200320032903c8033703a801410021020240200341a8016a411041d889c200410041001000417f460d00200342103702ec022003200341a8016a3602e802200341c8016a200341e8026a10c80220032903c8014201520d1f200341b8056a41286a2204200341f8016a290300370300200341b8056a41206a2205200341c8016a41286a220f290300370300200341b8056a41186a2210200341c8016a41206a2211290300370300200341b8056a41106a2212200341c8016a41186a2213290300370300200341b8056a41086a2214200341c8016a41106a2215290300370300200341e0046a41086a22162003418c026a280200360200200320032903d0013703b80520032003290284023703e00420034180026a2802002102200f2004290300370300201120052903003703002013201029030037030020152012290300370300200341c8016a41086a201429030037030020034184026a2016280200360200200320023602f801200320032903b8053703c801200320032903e0043702fc010b41daf2c1002105413521044101210f0240200220084f0d00200341c8016a410c6a2008360200200341d0016a41033a00002003410b3a00c801200341c8016a103d4104101b2202450d202002200836000020024104410c101a2202450d212002200e3700042002410c4118101a2202450d222002200d37000c200241184130101a2202450d232002200a3700242002200b37001c2002200c3700142002413041e000101a2202450d2420022006360038200220073600342002200937002c200341c8036a41086a22054200370300200342003703c8034196f2c1004118200341c8036a1001200341c8016a41086a2005290300370300200320032903c8033703c801200341c8016a41102002413c100320021019410021050b410121080c360b200141c0006a290300210a200141386a290300210b200141c8006a29030021092003412c6a41026a200141076a2d00003a0000200341306a41086a200141186a290200370300200341306a410d6a2001411d6a2900003700002003200141056a2f00003b012c2003200141106a290200370330200141046a2d00002107200141086a280200210f2001410c6a2802002106200141286a28020021152001412c6a2802002114200141306a2802002113200241096a2800002104200241056a280000210520022d0001211020022d00002108200341e8006a41086a2211200241156a290000370300200341e8006a410d6a22122002411a6a2900003700002003200241046a2d00003a00da042003200241026a2f01003b01d80420032002410d6a2900003703682008450d02410121020c030b200141386a290300210a200141306a290300210b200141c0006a2903002109200341c8006a200141196a290000370300200341c0006a200141116a290000370300200341306a41086a200141096a29000037030020032001290001370330200141246a2802002117200141286a28020021162001412c6a2802002110200241096a2800002104200241056a280000210520022d0001210820022d0000210f200341e8006a41086a2206200241156a290000370300200341e8006a410d6a22072002411a6a2900003700002003200241046a2d00003a00da042003200241026a2f01003b01d80420032002410d6a290000370368200f450d04410121020c050b2001410c6a2802002106200141086a2802002108200141046a2802002107200141106a2903002109200241096a2800002104200241056a280000210520022d0001211020022d0000210f200341e8006a41086a2211200241156a290000370300200341e8006a410d6a22122002411a6a2900003700002003200241046a2d00003a00da042003200241026a2f01003b01d80420032002410d6a290000370368200f450d06410121020c070b200341b8046a41086a2011290300370300200341b8046a410d6a2012290000370000200320032d00da043a00d204200320032f01d8043b01d004200320032903683703b80441012102201041ff01714101470d00200341ea026a20032d00d2043a0000200341c8016a41086a200341b8046a41086a290300370300200341c8016a410d6a200341b8046a410d6a290000370000200320032f01d0043b01e802200320032903b8043703c801410021020c010b412a2104418d81c00021050b200341e0046a41026a2208200341e8026a41026a2d00003a0000200341b8056a41086a2210200341c8016a41086a2211290300370300200341b8056a41106a200341c8016a41106a290300370300200320032f01e8023b01e004200320032903c8013703b80520020d2d200341bb016a2010290300370000200341c0016a200341b8056a410d6a2202290000370000200320032f01e0043b01a801200320043600af01200320053600ab01200320032903b8053700b301200320082d00003a00aa0120082003412c6a41026a2d00003a00002011200341306a41086a290300370300200341c8016a410d6a2204200341306a410d6a290000370000200320032f012c3b01e004200320032903303703c801200741ff01714101470d06200341e8026a200f410676106120032802f002200f413f7122024d0d0c200341c8036a41026a20032802e80220024105746a220241026a2d00003a0000200341c0056a200241136a290000370300200341c5056a200241186a290000370000200320022f00003b01c8032003200229000b3703b805200228000721062002280003210f4101210220032802ec02450d2a0c290b200341b8046a41086a2006290300370300200341b8046a410d6a2007290000370000200320032d00da043a00d204200320032f01d8043b01d004200320032903683703b80441012102200841ff01714101470d00200341ba056a20032d00d2043a0000200341c8016a41086a200341b8046a41086a290300370300200341c8016a410d6a200341b8046a410d6a290000370000200320032f01d0043b01b805200320032903b8043703c801410021020c010b412a2104418d81c00021050b200341d8006a41026a220f200341b8056a41026a2d00003a000020034190046a41086a2208200341c8016a41086a220629030037030020034190046a41106a200341c8016a41106a290300370300200320032f01b8053b0158200320032903c8013703900420020d0e2003419b016a200829030037000020034188016a41186a22022003419d046a290000370000200320032f01583b0188012003200436008f012003200536008b012003200329039004370093012003200f2d00003a008a01200341c8016a20034188016a200910e601200341b8056a41086a200341c8016a41146a290200370300200341b8056a41106a200341c8016a411c6a290200370300200341b8056a41186a2205200341ec016a2802003602002003200341c8016a410c6a2902003703b805410121182006280200210420032802c8014101470d0420032802cc01210520160d0f0c100b200341b8046a41086a2011290300370300200341b8046a410d6a2012290000370000200320032d00da043a00d204200320032f01d8043b01d004200320032903683703b80441012102201041ff01714101470d00200341ea026a20032d00d2043a0000200341c8016a41086a200341b8046a41086a290300370300200341c8016a410d6a200341b8046a410d6a290000370000200320032f01d0043b01e802200320032903b8043703c801410021020c010b418d81c0002105412a21040b200341d0006a41026a220f200341e8026a41026a2d00003a0000200341b8056a41086a2210200341c8016a41086a290300370300200341b8056a41106a200341c8016a41106a290300370300200320032f01e8023b0150200320032903c8013703b80520020d04200341f3046a2010290300370000200341e0046a41186a200341c5056a290000370000200320032f01503b01e004200320043600e704200320053600e304200320032903b8053700eb042003200f2d00003a00e204200341c8036a41086a22024200370300200342003703c8034196f2c1004118200341c8036a1001200341a8016a41086a2002290300370300200320032903c8033703a801200341a8016a411041d889c200410041001000417f460d0220034210370294042003200341a8016a36029004200341c8016a20034190046a10c80220032903c8014201520d11200341b8056a41386a220220034188026a290300370300200341b8056a41306a2204200341c8016a41386a2205290300370300200341b8056a41286a220f200341c8016a41306a2210290300370300200341b8056a41206a2211200341c8016a41286a2212290300370300200341b8056a41186a2213200341c8016a41206a2214290300370300200341b8056a41106a2215200341c8016a41186a2216290300370300200341b8056a41086a2217200341c8016a41106a2218290300370300200320032903d0013703b80520052002290300220a37030020102004290300220b3703002012200f290300220c37030020142011290300220d37030020162013290300220e370300201820152903002219370300200341c8016a41086a2017290300221a370300200341e8026a41086a201a370300200341e8026a41106a2019370300200341e8026a41186a200e370300200341e8026a41206a200d370300200341e8026a41286a200c370300200341e8026a41306a200b370300200341e8026a41386a200a370300200320032903b805220a3703c8012003200a3703e8020c030b200341c8036a41026a200341e0046a41026a2d00003a0000200341b8056a41086a200341c8016a41086a29030037030020022004290000370000200320032f01e0043b01c803200320032903c8013703b8050c240b200341a8016a410c6a200341b8056a41086a220f290300370200200341a8016a41146a200341b8056a41106a290300370200200341a8016a411c6a2005280200360200200320032903b8053702ac01200320043602a801200341c8016a10f5022003200341c8016a3602e4022003200341c8016a360258200341e8026a41146a41d0b4c300360200200341e8026a41086a2204420037030020034198036a2206410036020020034188036a22054200370300200341b0036a20034188016a41086a290300370300200341b8036a20034188016a41106a290300370300200341e8026a41d8006a2002290300370300200341d889c2003602f802200341a0c0c1003602ec02200341003602e80220034208370390032003428080808080013703800320032003290388013703a8032003200341d8006a3602a4032003200341e4026a3602a0032003200341c8016a36029c03200341c8036a200341e8026a200b200a200341a8016a200341306a20172010107720032d00c803221b0d08200f2004290300370300200341e0046a41086a200341c4056a280200360200200320032903e8023703b805200320032902bc053703e0042003200341e0046a10e9022005280200211120034184036a280200220721022003418c036a2802002210450d072007201041d8006c6a2102200341c1056a210f200341c0056a210820072104034020042d00002105200341e0046a200441016a41d7001095031a20054105460d07200820053a00002003410b3a00b805200f200341e0046a41d7001095031a200341b8056a103d200441d8006a22042002470d000c080b0b200341103602a003200342013703900320034201370388032003420137038003200342013703f802200342013703f002200342013703e802200342808080808080c000370398030b200341c8016a200341e0046a200910e601200341d0016a280200210420032802c8014101470d0120032802cc0121050b410021064101210f2008450d1d200710190c1d0b200341e8016a290300210b200341e0016a290300210c200341d8016a2903002109200341d4016a350200210d200341086a20032903e80242002006ad420010990342002009427f200329030820032903104200521b7d220a200a200956200a507222021b2109200d4220862004ad84210a2002450d01412c210441aef2c10021052008450d1a0c190b4100210220032802ec020d1c0c1d0b200341c8016a20072006200341e8026a10d002024020032802c8014101470d00200341d0016a280200210420032802cc01210520080d180c190b200341b8056a41186a2205200341c8016a410472220241186a280200360200200341b8056a41106a2210200241106a290200370300200341b8056a41086a2211200241086a290200370300200320022902003703b805200341c8016a41186a22024200370300200341c8016a41106a22124200370300200341c8016a41086a22134200370300200342003703c80120072006200341c8016a1005200341e8006a41026a221420032d00ca013a0000200341f0036a41086a2215200341db016a290000370300200341f0036a410d6a22162002290000370000200320032f01c8013b0168200320032900d3013703f00320032800cb01210f20032800cf01210420034188016a41026a20142d00003a0000200341c8036a41086a2015290300370300200341c8036a410d6a2016290000370000200320032f01683b018801200320032903f0033703c803200220052802003602002012201029030037030020132011290300370300200320032903b8053703c8014114101b2202450d10200241106a41002800fce341360000200241086a41002900f4e341370000200241002900ece341370000200241144134101a2202450d11200220032f0188013b00142002200436001b2002200f360017200220032903c80337001f200241166a20034188016a41026a22052d00003a0000200241276a200341c8036a41086a2903003700002002412c6a200341c8036a410d6a290000370000200341343602ac01200320023602a801200341c8016a200341a8016a10df02200210190240200341d8016a280200450d0020032802d40110190b2005200341e8006a41026a2d00003a0000200341c8016a41086a200341f0036a41086a290300370300200341c8016a410d6a200341f0036a410d6a290000370000200320032f01683b018801200320032903f0033703c8014115101b2202450d122002410d6a410029009ee441370000200241086a4100290099e44137000020024100290091e441370000200241154135101a2202450d13200220032f0188013b00152002200436001c2002200f360018200220032903c801370020200241176a2003418a016a2d00003a0000200241286a200341c8016a41086a2903003700002002412d6a200341c8016a410d6a290000370000200341003602d003200342013703c803200320063602a801200341a8016a200341c8036a105d024020032802cc03221120032802d00322106b20064f0d00201020066a22052010490d1520114101742212200520052012491b22124100480d152011450d0720032802c80320112012101a2205450d080c160b20032802c80321050c160b200441d8006a21020b2007201041d8006c6a21050240034020052002460d0120022d00002104200241d8006a210220044105470d000b0b410021182011450d00200710190b20034188016a20032903a80120032903b00120032903b801200341a8016a41186a29030010e50120034190036a280200221c2006280200220441f8006c6a211020034194036a280200211d201c21020240024002402004450d00200341c1056a210420034190046a4102722105200341b8056a4101722114200341e1056a2115201c210202400340200341e8006a41186a2208200241186a290300370300200341e8006a41106a2206200241106a290300370300200341e8006a41086a2207200241086a29030037030020032002290300370368200241206a2d0000210f200341e0046a200241216a41d7001095031a200f410e460d01200341f0036a41186a22112008290300370300200341f0036a41106a22122006290300370300200341f0036a41086a22132007290300370300200320032903683703f0032003200f3a00b8052014200341e0046a41d7001095031a20052003290368370000200541086a2007290300370000200541106a2006290300370000200541186a200829030037000020034180023b019004200341206a200341b8056a20034190046a10502003280220210f200341b8056a41086a41043a00002015200f453a0000200420032903f003370000200441086a2013290300370000200441106a2012290300370000200441186a20112903003700002003410b3a00b805200341b8056a103d200241f8006a22022010470d000b201022022010470d020c030b200241f8006a21020b20022010460d010b200341b8056a41206a2106200341b8056a410b6a2105200341b8056a41216a2114200341e8006a410d6a210f200341e8006a41086a21080340200320022f01003b01d8042003200241026a2d00003a00da04200241036a2800002107200241076a2800002111200f200241186a2900003700002008200241136a29000037030020032002410b6a290000370368200241206a2d00002104200341b8056a200241216a41d7001095031a2004410e460d01200341b8046a41086a22122008290300370300200341b8046a410d6a2213200f290000370000200320032d00da043a00d204200320032f01d8043b01d004200320032903683703b804200341e0046a200341b8056a41d7001095031a200620043a0000200520032903b804370000200541086a20122903003700002005410d6a2013290000370000200320113600bf05200320073600bb05200320032d00d2043a00ba05200320032f01d0043b01b8052014200341e0046a41d7001095031a20061043200241f8006a22022010470d000b0b0240201d450d00201c10190b200341d0036a2802002104410021050240201b4101470d0020032802cc0321050b2018450d00200341f4026a280200210720032802ec02210202400240200341f0026a2802002208450d00200821062002210f0340200f28028009210f2006417f6a22060d000b0340200220022f01064102746a4180096a28020021022008417f6a22080d000c020b0b2002210f0b200341b8056a411c6a20022f0106360200200341d0056a4100360200200341cc056a2002360200200320073602d805200341003602c805200342003703c0052003200f3602bc05200341003602b805200341b8056a10ad0220034188036a280200450d00200341e8026a411c6a28020010190b2016450d010b201710190b410021084101210f0c1c0b2012101b22050d0e0b20124101101c000b41fcd4c3001029000b41fcf9c00041331030000b41fcf9c00041331030000b41044101101c000b410c4101101c000b41184101101c000b41304101101c000b41e0004101101c000b41144101101c000b41344101101c000b41154101101c000b41354101101c000b101d000b200320123602cc03200320053602c803201221110b200520106a200720061095031a200341c8036a41086a22124200370300200342003703c80320024135200341c8036a1001200341a8016a41086a2012290300370300200320032903c8033703a801200341a8016a41102005201020066a100302402011450d00200510190b2002101902402008450d00200710190b200341d8006a41026a2202200341e8006a41026a2d00003a000020034190046a41086a2205200341f0036a41086a29030037030020034190046a410d6a2208200341f0036a410d6a290000370000200320032f01683b0158200320032903f00337039004200341c8016a41086a41023a0000200341d8016a2004360200200341d4016a200f360200200341d1016a20032f01583b0000200341dc016a200329039004370200200341e4016a2005290300370200200341e9016a200829000037000020022d000021022003410b3a00c801200341c8016a410b6a20023a0000200341c8016a103d200341e0046a200a2009200c200b10e501410021050c020b200710190b200341e0046a200a2009200c200b10e5010b410021064101210f0b4101210820012d0000220241054d0d080c090b20032802e80210190b20020d00410121024115210641bde3c100210f0c010b200341e8026a41026a200341c8036a41026a2d00003a0000200341c8016a41086a200341b8056a41086a290300370300200341c8016a410d6a200341b8056a410d6a290000370000200320032f01c8033b01e802200320032903b8053703c801410021020b200341d8006a41026a2204200341e8026a41026a2d00003a000020034190046a41086a2205200341c8016a41086a220829030037030020034190046a41106a200341c8016a41106a290300370300200320032f01e8023b0158200320032903c8013703900402402002450d0020062104200f21050c010b200341d0006a41026a20042d00003a000020034188016a41086a200529030037030020034188016a410d6a220520034190046a410d6a290000370000200320032f01583b0150200320032903900437038801200341c8016a200341a8016a200910e601200341b8056a41086a200341c8016a41146a290200370300200341b8056a41106a200341c8016a411c6a290200370300200341b8056a41186a2202200341ec016a2802003602002003200341c8016a410c6a2902003703b8054101211820082802002104024020032802c8014101470d0020032802cc01210520140d020c030b200341f0036a410c6a200341b8056a41086a2208290300370200200341f0036a41146a200341b8056a41106a290300370200200341f0036a411c6a2002280200360200200320032903b8053702f403200320043602f003200341c8016a10f5022003200341c8016a3602542003200341c8016a3602e402200341e8026a41146a41d0b4c300360200200341e8026a41086a2204420037030020034198036a2207410036020020034188036a22104200370300200341b0036a200341a8016a41086a290300370300200341b8036a200341a8016a41106a290300370300200341e8026a41d8006a200341a8016a41186a290300370300200341d889c2003602f802200341a0c0c1003602ec02200341003602e802200342083703900320034280808080800137038003200320032903a8013703a8032003200341e4026a3602a4032003200341d4006a3602a0032003200341c8016a36029c03200341cb056a20034188016a41086a29030037000020022005290000370000200320063600bf052003200f3600bb052003200341d2006a2d00003a00ba05200320032f01503b01b80520032003290388013700c305200341003602e804200342013703e004200341d8006a200341e8026a200341b8056a200b200a200341f0036a20152013200341e0046a108e0102402003280258221b0d0020082004290300370300200341e0046a41086a200341c4056a280200360200200320032903e8023703b805200320032902bc053703e0042003200341e0046a10e9022010280200211120034184036a2802002206210202402003418c036a2802002210450d002006201041d8006c6a2102200341c1056a210f200341c0056a2108200621040240034020042d00002105200341e0046a200441016a41d7001095031a20054105460d01200820053a00002003410b3a00b805200f200341e0046a41d7001095031a200341b8056a103d200441d8006a22042002470d000c020b0b200441d8006a21020b2006201041d8006c6a21050240034020052002460d0120022d00002104200241d8006a210220044105470d000b0b410021182011450d00200610190b200341a8016a20032903f00320032903f803200329038004200341f0036a41186a29030010e50120034190036a280200221c2007280200220441f8006c6a211020034194036a280200211d201c21020240024002402004450d00200341c1056a210420034190046a4102722105200341b8056a4101722116200341e1056a2117201c210202400340200341e8006a41186a2208200241186a290300370300200341e8006a41106a2206200241106a290300370300200341e8006a41086a2207200241086a29030037030020032002290300370368200241206a2d0000210f200341e0046a200241216a41d7001095031a200f410e460d01200341c8036a41186a22112008290300370300200341c8036a41106a22122006290300370300200341c8036a41086a22132007290300370300200320032903683703c8032003200f3a00b8052016200341e0046a41d7001095031a20052003290368370000200541086a2007290300370000200541106a2006290300370000200541186a200829030037000020034180023b019004200341186a200341b8056a20034190046a10502003280218210f200341b8056a41086a41043a00002017200f453a0000200420032903c803370000200441086a2013290300370000200441106a2012290300370000200441186a20112903003700002003410b3a00b805200341b8056a103d200241f8006a22022010470d000b201022022010470d020c030b200241f8006a21020b20022010460d010b200341b8056a41206a2106200341b8056a410b6a2105200341b8056a41216a2116200341e8006a410d6a210f200341e8006a41086a21080340200320022f01003b01d8042003200241026a2d00003a00da04200241036a2800002107200241076a2800002111200f200241186a2900003700002008200241136a29000037030020032002410b6a290000370368200241206a2d00002104200341b8056a200241216a41d7001095031a2004410e460d01200341b8046a41086a22122008290300370300200341b8046a410d6a2213200f290000370000200320032d00da043a00d204200320032f01d8043b01d004200320032903683703b804200341e0046a200341b8056a41d7001095031a200620043a0000200520032903b804370000200541086a20122903003700002005410d6a2013290000370000200320113600bf05200320073600bb05200320032d00d2043a00ba05200320032f01d0043b01b8052016200341e0046a41d7001095031a20061043200241f8006a22022010470d000b0b0240201d450d00201c10190b200341e0006a2802002104200328025c210202400240201b450d00200221052018450d020c010b2003200341e4006a2802003602c005200320043602bc05200320023602b8054100210502402004450d00200210190b2018450d010b200341f4026a280200210720032802ec02210202400240200341f0026a2802002208450d00200821062002210f0340200f28028009210f2006417f6a22060d000b0340200220022f01064102746a4180096a28020021022008417f6a22080d000c020b0b2002210f0b200341b8056a411c6a20022f0106360200200341d0056a4100360200200341cc056a2002360200200320073602d805200341003602c805200342003703c0052003200f3602bc05200341003602b805200341b8056a10ad0220034188036a280200450d00200341e8026a411c6a280200101920140d010c020b2014450d010b201510190b410121084100210f0b4101210620012d0000220241054b0d010b02400240024020020e06040404000201040b2006450d03200141086a280200450d03200141046a28020010190c030b2008450d02200141286a280200450d02200141246a28020010190c020b200f450d012001412c6a280200450d01200141286a28020010190c010b200141286a280200450d00200141246a28020010190b2000200436020420002005360200200341b0066a24000b0a0041a4c2c3001029000b950501067f230041206b2202240020024100360218200242013703102000200241106a105d200041046a200241106a105d200041086a200241106a105d200228021421032002280218210402400240024002400240024002400240024002400240024002400240024020002d00184101470d0020032004470d01200441016a22032004490d0c20044101742205200320032005491b22054100480d0c2004450d03200228021020042005101a2203450d040c090b20032004470d01200441016a22032004490d0b20044101742205200320032005491b22054100480d0b2004450d04200228021020042005101a2203450d050c060b200228021021030c080b200228021021030c050b2005101b22030d050b20054101101c000b2005101b22030d010b20054101101c000b20022005360214200220033602100b200241186a200441016a360200200320046a41003a00000c020b20022005360214200220033602100b200241186a200441016a360200200320046a41013a00000b200028020c21062002200041146a28020022003602002002200241106a105d02400240024020022802142205200241186a28020022036b20004f0d00200320006a22042003490d0320054101742207200420042007491b22074100480d032005450d01200228021020052007101a2204450d020c040b200228021021040c040b2007101b22040d020b20074101101c000b101d000b2002200736021420022004360210200721050b200420036a200620001095031a2001280204210620012802002101200241106a41086a220742003703002002420037031020012006200241106a1001200241086a200729030037030020022002290310370300200241102004200320006a100302402005450d00200410190b200241206a24000b130020004101360204200041bcc2c3003602000b13002000410f3602042000418cdbc1003602000b13002000410136020420004188c3c3003602000bd806010a7f200128020421032001280200210441002105410121064100210720012802082208210902400240024002400240024002400340024020072005470d002005410174220a200541016a220b200b200a491b220a4100480d05024002402005450d0020062005200a101a22060d010c040b200a101b2206450d030b200a21050b200620076a200941807f72200941ff00712009410776220a1b3a0000200741016a2107200a2109200a0d000b200520076b20084f0d02200720086a22092007490d032005410174220a20092009200a491b22094100480d03024002402005450d00200620052009101a2206450d010c030b2009101b22060d020b20094101101c000b200a4101101c000b200921050b200620076a200420081095031a02402003450d00200410190b200128020c210c02400240024002400240200520086b20076b200141146a28020022094f0d00200820076a220a20096a2203200a490d052005410174220a20032003200a491b220a4100480d052005450d0120062005200a101a2206450d020c030b200820096a20076a21030c030b200a101b22060d010b200a4101101c000b200a21050b200620086a20076a200c20091095031a200241086a210a200241046a210820032109034002400240024002402008280200200a2802002207470d00200741016a220b2007490d0520074101742204200b200b2004491b22044100480d052007450d01200228020020072004101a220b0d020c060b2002280200210b0c020b2004101b220b450d040b2002200b36020020082004360200200a28020021070b200a200741016a360200200b20076a200941807f72200941ff0071200941077622071b3a00002007210920070d000b024002400240200241046a2802002209200241086a28020022076b20034f0d00200720036a220a2007490d0320094101742207200a200a2007491b22074100480d032009450d01200228020020092007101a2209450d020c050b200228020021090c050b2007101b22090d030b20074101101c000b101d000b20044101101c000b20022009360200200241046a2007360200200241086a28020021070b200241086a200720036a360200200920076a200620031095031a02402005450d00200610190b2000411a3a00000240200141106a280200450d00200c10190b0b9e05010c7f230041c080016b22022400200241086a200110d90141012103024020022802084101470d002000200229020c370204200041013602002000410c6a200241086a410c6a290200370200200241c080016a24000f0b200228020c2104200241086a4100418080011094031a41002105410021060240024002400240024002402004450d00200141086a2107200141046a21084100210941002105410121034100210a03402008280200220b200728020022066b2004200a6b220c41808001200c41808001491b220c490d022006200c6a220d2006490d03200b200d490d04200241086a200128020020066a200c1095031a2007200d3602000240024002400240200520096b200c4f0d002009200c6a22062009490d092005410174220d20062006200d491b220d4100480d092005450d0120032005200d101a22030d020c0a0b200c20096a21060c020b200d101b2203450d080b200d21050b200320096a200241086a200c1095031a200621092004200c200a6a220a4b0d000b0b2000200336020420004100360200200041146a2006360200200041106a41003602002000410c6a2006360200200041086a2005360200200241c080016a24000f0b200241013a008f8001200241b480016a4101360200200241013602bc8001200242013702a48001200241c4d6c3003602a0800120022002418f80016a3602b880012002200241b880016a3602b080012002419080016a200241a080016a1024200241ab80016a2002419880016a2802003600002002200229039080013700a38001200041053a000420004101360200200020022900a080013700052000410c6a200241a780016a29000037000002402005450d00200310190b200241c080016a24000f0b2006200d1027000b200d200b1028000b101d000b200d4101101c000be007010a7f230041c0006b22022400024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204470d00200241013a000f2002413c6a4101360200200241013602242002420137022c200241c4d6c30036022820022002410f6a3602202002200241206a360238200241106a200241286a1024200241326a200241186a2802003601002002200229031037012a20022002412e6a29010037010620022002290128370300410521050c010b200441016a21062004417f460d0b20032006490d0c2001280200220720046a2d00002108410c21052001410c6a2006360200410021064100210902402008450d004101210920084101470d010b410120036b210a200441026a21042001410c6a210b4100210503402006411f4b0d02200a20046a4102460d032004450d0a20032004490d0b200720046a417f6a2d00002108200b2004360200200841ff00712006411f71742005722105200441016a2104200641076a21062008418001710d000b024020064120490d00410d210620086741686a41ff01714104490d040b2009450d042004417f6a2104410021062001410c6a210b4100210a03402006411f4b0d0720032004460d082004417f460d0e2003200441016a2201490d0f200720046a2d00002108200b2001360200200841ff00712006411f7174200a72210a200641076a2106200121042008418001710d000b024020064120490d00410d210420086741686a41ff01714104490d090b410121040c050b200020083a0005200020053a000420002002290300370106200041013602002000410c6a2002290106370100200241c0006a24000f0b410f21060c010b200241013a00102002413c6a4101360200200241013602242002420137022c200241c4d6c3003602282002200241106a3602202002200241206a3602382002200241286a1024410521060b2000200636020420004101360200200041086a2002290200370200200041106a200241086a280200360200200241c0006a24000f0b410021040b20002005360204200041003602002000410c6a200a360200200041086a2004360200200241c0006a24000f0b410f21040c010b200241013a00102002413c6a4101360200200241013602242002420137022c200241c4d6c3003602282002200241106a3602202002200241206a3602382002200241286a1024410521040b2000200436020420004101360200200041086a2002290200370200200041106a200241086a280200360200200241c0006a24000f0b417f20041027000b200420031028000b417f20061027000b200620031028000b417f200441016a1027000b200441016a20031028000b3702017f017e230041106b22032400200320021045200329030021042000200341086a29030037030820002004370300200341106a24000bb90401027f230041f0006b22052400200541106a41186a200241186a290000370300200541106a41106a200241106a290000370300200541106a41086a200241086a29000037030020052002290000370310024002400240024002402004417f4c0d00024002402004450d002004101b22020d0120044101101c000b410121020b2002200320041095032102200541c0006a41186a200541106a41186a290300370300200541c0006a41106a200541106a41106a290300370300200541c0006a41086a200541106a41086a29030037030020052005290310370340200520043602682005200436026420052002360260200541306a200541c0006a200541e0006a10e8020240024002400240200528023022022005280238220441d889c200410041001000417f460d00200541003602482005200436024420052002360240200541086a200541c0006a10682005280208450d03200528020c2204417f4c0d042004450d01200410df012203450d05200541c8006a2206200628020022062004410020052802402005280244200320042006100022062006417f461b2206200620044b1b22066a36020020062004470d020c060b2000410036020020052802340d060c070b410121032005280240200528024441014100200541c8006a28020010001a41002004460d040b2004450d00200310190b41fcf9c00041331030000b102b000b20044101101c000b2000200436020420002003360200200041086a20043602002005280234450d010b200210190b200541f0006a24000b9c0701087f230041c0006b22032400200341206a41186a200141186a290000370300200341206a41106a200141106a290000370300200341206a41086a200141086a2900003703002003200129000037032002400240024002400240024002404108101b2204450d00200442e3deb9d3b38eddb73a3700004120101b2201450d0120012003290320370000200141186a2205200341206a41186a290300370000200141106a2206200341206a41106a290300370000200141086a2207200341206a41086a290300370000200441084128101a2204450d0220042001290000370008200441206a2005290000370000200441186a2006290000370000200441106a2007290000370000200110192002280204210620022802002105200228020821012003410036022820034201370320200320013602002003200341206a105d02400240024020032802242207200328022822026b20014f0d00200220016a22082002490d0620074101742209200820082009491b22094100480d062007450d01200328022020072009101a2208450d020c070b2003280220220820026a200520011095031a2006450d080c070b2009101b22080d050b20094101101c000b41084101101c000b41204101101c000b41284101101c000b101d000b200320093602242003200836022020092107200820026a200520011095031a2006450d010b200510190b200341206a41086a220542003703002003420037032020044128200341206a1001200341086a22092005290300370300200320032903203703000240024002404110101b2206450d0020062003290300370000200641086a200929030037000020041019200341206a41186a22044200370300200341206a41106a220a420037030020054200370300200342003703202008200220016a200341206a1005200341186a22022004290300370300200341106a200a29030037030020092005290300370300200320032903203703004120101b2201450d0120012003290300370000200141186a2002290300370000200141106a200341106a290300370000200141086a200341086a29030037000002402007450d00200810190b200641104130101a2204450d0220042001290000370010200441286a200141186a290000370000200441206a200141106a290000370000200441186a200141086a29000037000020011019200042b0808080800637020420002004360200200341c0006a24000f0b41104101101c000b41204101101c000b41304101101c000bd61105057f017e127f027e047f230041f0026b2202240020012802082103200128020021040240024020012802042205450d002005210620042101034020012802800921012006417f6a22060d000b0340200420042f01064102746a4180096a28020021042005417f6a22050d000c020b0b200421010b2002411c6a20042f0106360200200241186a4100360200200241146a20043602002002200336022020024100360210200242003703082002200136020420024100360200200241e8006a200210ae0202400240024020022903880122074202510d00200241ad016a210820024198016a210920024190016a210a200241a0016a210b200241a4016a210c200241a8016a210d200241ac016a210e200241e8006a41206a210f200241e8006a411c6a2110200241e8006a41146a2111200241bc026a21120340200241c8006a41186a2206200241e8006a41186a2213290300370300200241c8006a41106a2214200241e8006a41106a2215290300370300200241c8006a41086a2216200241e8006a41086a2203290300370300200241286a41086a2217200841086a290000370300200241286a41106a2218200841106a290000370300200241286a41186a2219200841186a29000037030020022002290368370348200220082900003703282009290300211a200a290300211b200b2802002104200c2802002101200d280200211c200e2d00002105200241d0016a41186a221d2006290300370300200241d0016a41106a221e2014290300370300200241d0016a41086a221f2016290300370300200220022903483703d001200241f0016a41186a22062019290300370300200241f0016a41106a22142018290300370300200241f0016a41086a22162017290300370300200220022903283703f001024002400240024002400240024002400240024020074201520d00200241d0016a201b201a1059450d002001450d012001210620042105034020052802900221052006417f6a22060d000b0340200420042f01064102746a4190026a28020021042001417f6a22010d000c030b0b024002400240200541ff01714102460d00200241b0026a41186a22172006290300370300200241b0026a41106a22062014290300370300200241b0026a41086a22142016290300370300200220022903f0013703b00220054101710d014113101b2205450d052005410f6a41002800f8df41360000200541086a41002900f1df41370000200541002900e9df41370000200541134133101a2205450d06200520022903d0013700132005412b6a201d290300370000200541236a201e2903003700002005411b6a201f290300370000200241e0026a41086a22064200370300200242003703e00220054133200241e0026a100120032006290300370300200220022903e002370368200241e8006a41101002200510190b2001450d010c080b201320172903003703002015200629030037030020032014290300370300200220022903b0023703684113101b2205450d052005410f6a41002800f8df41360000200541086a41002900f1df41370000200541002900e9df41370000200541134133101a2205450d06200520022903d0013700132005412b6a201d290300370000200541236a201e2903003700002005411b6a201f290300370000200241e0026a41086a22064200370300200242003703e00220054133200241e0026a1001200241d0026a41086a2006290300370300200220022903e0023703d002200241d0026a4110200241e8006a412010032005101920010d070b200421050c070b200421050b200f201c360200201020042f0106360200201341003602002011200436020020154100360200200342003703002002200536026c20024100360268200241e8006a1084010c060b41134101101c000b41334101101c000b41134101101c000b41334101101c000b2001210620042105034020052802900221052006417f6a22060d000b0340200420042f01064102746a4190026a28020021042001417f6a22010d000b0b20042f01062101200f201c36020020102001360200201341003602002011200436020020154100360200200342003703002002200536026c20024100360268200241b0026a200241e8006a10ac02024020022802b002450d00034020024190026a41086a2213200241b0026a41086a2201280200360200200220022903b0023703900220122802002105200241b0026a41106a22062802002115200241b0026a41146a2802002104200241a0026a41086a2203201328020036020020022002290390023703a0020240024002400240024002402005450d00200241b0026a41186a201d2903003703002006201e2903003703002001201f290300370300200220022903d0013703b002200241e0026a41086a2003280200360200200220022903a0023703e002200241d0026a200241b0026a200241e0026a10e802200241d0026a41086a280200211420022802d002211320014100360200200242013703b002200220043602e002200241e0026a200241b0026a105d20022802b4022203200128020022066b20044f0d01200620046a22012006490d0b20034101742216200120012016491b22164100480d0b2003450d0220022802b00220032016101a22010d030c0c0b200241b0026a41186a201d2903003703002006201e2903003703002001201f290300370300200220022903d0013703b002200241e0026a41086a2003280200360200200220022903a0023703e002200241d0026a200241b0026a200241e0026a10e80220022802d0022204200241d0026a41086a280200100220022802d402450d04200410190c040b20022802b00221010c020b2016101b2201450d090b200220163602b402200220013602b002201621030b200120066a200520041095031a201320142001200620046a100302402003450d00200110190b024020022802d402450d00201310190b2015450d00200510190b200241b0026a200241e8006a10ac0220022802b0020d000b0b200241e8006a1084010b200241e8006a200210ae02200f29030022074202520d000b0b200210ad02200241f0026a24000f0b101d000b20164101101c000be30301047f230041d0006b22032400024002404113101b2204450d002004410f6a41002800f8df41360000200441086a41002900f1df41370000200441002900e9df41370000200441134133101a2204450d01200420022900003700132004412b6a200241186a290000370000200441236a200241106a2900003700002004411b6a200241086a290000370000200341306a41086a220242003703002003420037033020044133200341306a1001200341206a41086a200229030037030020032003290330370320024002400240200341206a411041d889c200410041001000417f460d00200341306a41186a4200370300200341306a41106a4200370300200341386a420037030020034200370330200341206a4110200341306a4120410010002202417f460d022002411f4d0d02200341186a2202200341306a41186a290300370300200341106a2205200341306a41106a290300370300200341086a2206200341306a41086a29030037030020032003290330370300200041013a000020002003290300370001200041096a2006290300370000200041116a2005290300370000200041196a20022903003700000c010b200041003a00000b20041019200341d0006a24000f0b41fcf9c00041331030000b41134101101c000b41334101101c000bc80202097f027e230041106b220324000240200128020022044100480d00200441ffffffff07460d002001200441016a2205360200200141046a2104200141086a28020021060240024003402004280200220841086a210920082f0106220741057421044100210a0240024003402004450d01200220094120109703220b450d02200441606a2104200a41016a210a200941206a2109200b417f4a0d000b200a417f6a21070b2006450d022006417f6a2106200820074102746a4180096a21040c010b0b200841e8026a200a41c8006c6a2204450d002004280200450d00200441106a290300210c200441086a290300210d0c010b200320012802102002200141146a280200280214110200200341086a290300210c200128020021052003290300210d0b20012005417f6a3602002000200c3703082000200d370300200341106a24000f0b107b000b13002000410436020420004190c8c3003602000b130020004108360204200041d8ebc1003602000b13002000410b360204200041b8ccc3003602000bc60101017f024002400240024002404104101b2202450d002002410036000020024104410c101a2202450d01200242013700042002410c4118101a2202450d022002420137000c200241184130101a2202450d03200242013700242002420137001c200242013700142002413041e000101a2202450d042002428080848080023700342002420137002c200042e0808080c007370204200020023602000f0b41044101101c000b410c4101101c000b41184101101c000b41304101101c000b41e0004101101c000b3401017f02404108101b2202450d0020004288808080800137020420002002360200200242c0843d3700000f0b41084101101c000b3301017f02404104101b2202450d0020004284808080c00037020420002002360200200241e4003600000f0b41044101101c000b3301017f02404108101b2202450d0020004288808080800137020420002002360200200242af013700000f0b41084101101c000b3301017f02404108101b2202450d002000428880808080013702042000200236020020024287013700000f0b41084101101c000b3901017f02404110101b2202450d002002420037000820024215370000200042908080808002370204200020023602000f0b41104101101c000ba10d08047f057e017f017e037f057e017f057e230041f0006b22012400200141286a41086a22024200370300200142003703284196f2c1004118200141286a1001200141086a41086a2002290300370300200120012903283703084100210341102104024002400240200141086a411041d889c200410041001000417f460d002001421037021c2001200141086a360218200141286a200141186a10c80220012903284201520d02200141386a2903002105200141c0006a2903002106200141c8006a2903002107200141d0006a2903002108200141d8006a2903002109200141e0006a2802002103200141e4006a280200210a200141e8006a28020021042001290330210b2001200141ec006a280200220c360264200120043602602001200a36025c2001200336025820012009370350200120083703482001200737034020012006370338200120053703302001200b3703280c010b4201210941808004210a420121084201210742012106420121054201210b0b200141286a41086a220242003703002001420037032841e6fbc000411b200141286a1001200141086a41086a220d200229030037030020012001290328370308024002400240024002400240200141086a411041d889c200410041001000417f460d002001420037033020014200370328200141086a4110200141286a411041001000220e417f460d02200e410f4d0d02200141306a290300210f200129032821100c010b420021104200210f0b2002420037030020014200370328418ff3c1004111200141286a1001200d200229030037030020012001290328370308024002400240200141086a411041d889c200410041001000417f460d0020014100360228200141086a4110200141286a41044100100041016a41044d0d022001280228210d0c010b41e400210d0b42002111200141286a41086a220242003703002001420037032841a0f3c1004114200141286a1001200141086a41086a20022903003703002001200129032837030802400240200141086a411041d889c200410041001000417f460d002001420037033020014200370328200141086a4110200141286a4110410010002202417f460d042002410f4d0d04200141306a2903002111200129032821120c010b421521120b42002113200141286a41086a220242003703002001420037032841fffac0004114200141286a1001200141086a41086a220e20022903003703002001200129032837030802400240200141086a411041d889c200410041001000417f460d002001420037033020014200370328200141086a4110200141286a4110410010002214417f460d052014410f4d0d05200141306a2903002115200129032821160c010b42002116420021150b20024200370300200142003703284193fbc0004114200141286a1001200e20022903003703002001200129032837030802400240200141086a411041d889c200410041001000417f460d002001420037033020014200370328200141086a4110200141286a4110410010002202417f460d062002410f4d0d06200141306a2903002117200129032821130c010b420021170b200141286a41086a220242003703002001420037032841b4f3c1004114200141286a1001200141086a41086a2002290300370300200120012903283703080240024002400240200141086a411041d889c200410041001000417f460d0020014200370328200141086a4110200141286a41084100100041016a41084d0d02200129032821180c010b42870121180b200141286a41086a220242003703002001420037032841c8f3c1004116200141286a1001200141086a41086a20022903003703002001200129032837030802400240200141086a411041d889c200410041001000417f460d0020014200370328200141086a4110200141286a41084100100041016a41084d0d03200129032821190c010b42af0121190b200020103703402000201337037020002016370360200020123703502000200d360290012000200c36023c200020043602382000200a3602342000200336023020002009370328200020083703202000200737031820002006370310200020053703082000200b37030020002019370388012000201837038001200041c8006a200f370300200041f8006a2017370300200041e8006a2015370300200041d8006a2011370300200141f0006a24000f0b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000b41fcf9c00041331030000bdb39030e7f017e017f230041c0006b220324002002280208220441586a2105200241106a2802002206412c6c210702400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024003402007450d01200741546a2107200541286a21082005412c6a2209210520082d00004104470d000b2006412c6c2107200441586a210503402007450d02200741546a2107200541286a21082005412c6a220a210520082d0000410b470d000b2006412c6c2107200441586a210503402007450d03200741546a2107200541286a21082005412c6a2204210520082d00004102470d000b200341106a200910d202200328021420014d0d03200328021020014102746a2207450d03200341086a200410d202200328020c200728020022074d0d04200328020820074104746a2207450d04200a41086a28020020014d0d05200a2802002109200341186a41086a420037030020034280808080c00037031820072d000d2108200341306a41026a220a2003412d6a41026a2d00003a0000200320032f002d3b01304110101b2207450d3f200341206a220b4101360200200341186a410c6a220528020021062003200736021c200720064104746a220741003a000c2007410036020820072008410447220c3602042007200c360200200720032f01303b000d2007410f6a200a2d00003a00002005200528020041016a3602004100210802402009200141186c6a22072802142205450d002007410c6a2106200741146a210a200341306a410472210d4100210841002107034002402003280218220920084d0d00200341306a200341186a410010fd0220032802304101460d0920082003280218220920032802342d000c1b2108200a28020021050b200720054f0d3e02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402006280200220120074104746a2d0000220541ab014b0d00024020050eac01141e0707071e13120c181915110e0d0b17160f1004040404040404040404040404040505050505050505050a1a06060606080000000000000000000008000000000000000000000000000000000000000000000303030101010101010101010101010101010303030101010101010101010101010101010303030303030301010101010101030303030303030101010101010102020202020202020202020202020202020202020202020202140b200341306a200341186a410210fe0220032802300d2a2003280218220541016a22092005490d2b20032009360218200741016a2207200a2802002205490d1f0c200b200341306a200341186a410210fe0220032802300d272003280218220541016a22092005490d2820032009360218200741016a2207200a2802002205490d1e0c1f0b200341306a200341186a410110fe0220032802300d2a2003280218220541016a22092005490d2b20032009360218200741016a2207200a2802002205490d1d0c1e0b200341306a200341186a410110fe0220032802300d2b2003280218220541016a22092005490d2c20032009360218200741016a2207200a2802002205490d1c0c1d0b200341306a200341186a410110fe0220032802300d2c2003280218220541016a22092005490d2d20032009360218200741016a2207200a2802002205490d1b0c1c0b200341306a200341186a410210fe022003280230450d180c2f0b200941016a22052009490d2f20032005360218200741016a2207200a2802002205490d190c1a0b200120074104746a2d0001210e200341306a41026a2003412d6a41026a2d00003a0000200320032f002d3b0130200341246a2802002201200341206a280200470d01200141016a220f2001490d5b20014101742210200f200f2010491b2210ad4204862211422088a70d5b2011a722124100480d5b2001450d13200328021c20014104742012101a220f0d140c5c0b200341306a200341186a410110fe0220032802300d2e2003280218220541016a22092005490d3020032009360218200741016a2207200a2802002205490d170c180b200328021c210f0c130b200941016a22052009490d3d20032005360218200741016a2207200a2802002205490d150c160b200941016a22052009490d3720032005360218200741016a2207200a2802002205490d140c150b200341306a200341186a200120074104746a41046a28020010fd0220032802304101460d2f200341306a200341186a2003280234280204220510fe0220032802300d41200341306a200341186a410110fe0220032802300d4a2003280218220920056a22052009490d4b20032005360218200741016a2207200a2802002205490d130c140b200341306a200341186a410210fe0220032802300d34200341306a200341186a410110fe0220032802300d3e2003280218220541016a22092005490d4820032009360218200741016a2207200a2802002205490d120c130b200341306a200341186a410110fe022003280230450d0f0c300b200941016a22052009490d3720032005360218200741016a2207200a2802002205490d100c110b200341306a200341186a410110fe022003280230450d0d0c2f0b2003200410d2022003280204200120074104746a41046a28020022054d0d2b2003280200220920054104746a2201450d2b200341306a200341186a200920054104746a28020810fe0220032802300d3b2003280218220520012d000d4104476a22092005490d4320032009360218200741016a2207200a2802002205490d0e0c0f0b200341306a200341186a200120074104746a41046a28020010fd0220032802304101460d32200341306a200341186a200328023428020410fe0220032802300d38200341246a2802002205417f6a220920054f0d41200920054b0d41200328021c20094104746a41013a000c200741016a2207200a2802002205490d0d0c0e0b200341246a22052802002209450d2420052009417f6a2209360200200328021c20094104746a22052d000c4102460d2420052802002109200320052802082205360218200520096a22092005490d3f20032009360218200741016a2207200a2802002205490d0c0c0d0b200341246a2802002205417f6a220920054f0d31200920054b0d31200328021c20094104746a41013a000c200741016a2207200a2802002205490d0b0c0c0b200341306a200120074104746a41046a280200200210f90220032802304101460d25200341306a200341186a2003280234220528020810fe0220032802300d392003280218220920052d000d4104476a22052009490d3c20032005360218200741016a2207200a2802002205490d0a0c0b0b200341306a200341186a410110fe0220032802300d2d2003280218220541016a22092005490d3920032009360218200741016a2207200a2802002205490d090c0a0b200341306a200341186a410110fe022003280230450d060c290b200341306a200341186a200120074104746a2209410c6a28020010fd0220032802304101460d2120032802342802042101200941086a2802004102742105200941046a280200210903402005450d07200341306a200341186a200928020010fd0220032802304101460d1b2005417c6a2105200941046a210920032802342802042001460d000c1c0b0b200341306a200341186a200c10fe0220032802300d24200341246a2802002205417f6a220920054f0d30200920054b0d30200328021c20094104746a41013a000c200741016a2207200a2802002205490d060c070b200341306a200341186a410110fe0220032802300d2e2003280218220541016a22092005490d3620032009360218200741016a2207200a2802002205490d050c060b2012101b220f450d480b200341206a20103602002003200f36021c200341246a28020021010b200f20014104746a220141003a000c2001200936020820012005410347200e41044722057136020420012005360200200120032f01303b000d2001410f6a200341326a2d00003a0000200341246a2205200528020041016a3602000b200741016a2207200a2802002205490d010c020b200341306a200341186a200110fe0220032802300d39200341246a2802002205417f6a220920054f0d3a200920054b0d3a200328021c20094104746a41013a000c200741016a2207200a2802002205490d000b0b2000410036020020002008360204200b280200450d5c200328021c1019200341c0006a24000f0b4113101b2207450d382007410f6a41002800aefd41360000200741086a41002900a7fd413700002007410029009ffd41370000200041086a4293808080b0023702002000200736020420004101360200200341c0006a24000f0b410f101b2207450d38200741076a41002900b9fd41370000200741002900b2fd41370000200041086a428f808080f0013702002000200736020420004101360200200341c0006a24000f0b410f101b2207450d38200741076a41002900c8fd41370000200741002900c1fd41370000200041086a428f808080f0013702002000200736020420004101360200200341c0006a24000f0b4125101b2207450d392007411d6a41002900edfd41370000200741186a41002900e8fd41370000200741106a41002900e0fd41370000200741086a41002900d8fd41370000200741002900d0fd41370000200041086a42a5808080d0043702002000200736020420004101360200200341c0006a24000f0b4125101b2207450d392007411d6a41002900edfd41370000200741186a41002900e8fd41370000200741106a41002900e0fd41370000200741086a41002900d8fd41370000200741002900d0fd41370000200041086a42a5808080d0043702002000200736020420004101360200200341c0006a24000f0b4127101b2207450d3a2007411f6a4100290094fe41370000200741186a410029008dfe41370000200741106a4100290085fe41370000200741086a41002900fdfd41370000200741002900f5fd41370000200041086a42a7808080f0043702002000200736020420004101360200200341c0006a24000f0b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a280200450d550c540b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d530c540b410e101b2207450d3a200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d520c530b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d510c520b410e101b2207450d39200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d500c510b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4f0c500b410e101b2207450d38200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4e0c4f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4d0c4e0b410e101b2207450d37200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4c0c4d0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d4b0c4c0b410e101b2207450d36200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d4a0c4b0b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d490c4a0b4127101b2207450d352007411f6a41002900e0fe41370000200741186a41002900d9fe41370000200741106a41002900d1fe41370000200741086a41002900c9fe41370000200741002900c1fe41370000200041086a42a7808080f0043702002000200736020420004101360200200341206a2802000d480c490b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d470c480b410e101b2207450d34200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d460c470b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d450c460b4117101b2207450d332007410f6a41002900abfe41370000200741086a41002900a4fe413700002007410029009cfe41370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d440c450b410e101b2207450d33200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d430c440b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d420c430b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d410c420b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d400c410b410e101b2207450d30200741066a41002900eefe41370000200741002900e8fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d3f0c400b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3e0c3f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3d0c3e0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3c0c3d0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3b0c3c0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d3a0c3b0b410e101b2207450d2b200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d390c3a0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d380c390b200041013602002000200d2902003702042000410c6a200d41086a280200360200200341206a2802000d370c380b4117101b2207450d292007410f6a41002900abfe41370000200741086a41002900a4fe413700002007410029009cfe41370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d360c370b410e101b2207450d29200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d350c360b410e101b2207450d29200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d340c350b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d330c340b4117101b2207450d282007410f6a41002900abfe41370000200741086a41002900a4fe413700002007410029009cfe41370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d320c330b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d310c320b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d300c310b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2f0c300b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2e0c2f0b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d2d0c2e0b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2c0c2d0b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2b0c2c0b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d2a0c2b0b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d290c2a0b4117101b2207450d232007410f6a41002900abfe41370000200741086a41002900a4fe413700002007410029009cfe41370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d280c290b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d270c280b410e101b2207450d23200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d260c270b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d250c260b410e101b2207450d22200741066a41002900b9fe41370000200741002900b3fe41370000200041086a428e808080e0013702002000200736020420004101360200200341206a2802000d240c250b20002003290330370204200041013602002000410c6a200341386a280200360200200341206a2802000d230c240b4117101b2207450d212007410f6a41002900abfe41370000200741086a41002900a4fe413700002007410029009cfe41370000200041086a4297808080f0023702002000200736020420004101360200200341206a2802000d220c230b41134101101c000b410f4101101c000b410f4101101c000b41a4d6c30020072005104a000b41254101101c000b41254101101c000b41104104101c000b41274101101c000b101d000b20124104101c000b410e4101101c000b410e4101101c000b410e4101101c000b410e4101101c000b410e4101101c000b41274101101c000b410e4101101c000b41174101101c000b410e4101101c000b410e4101101c000b410e4101101c000b41174101101c000b410e4101101c000b410e4101101c000b41174101101c000b410e4101101c000b410e4101101c000b410e4101101c000b410e4101101c000b41174101101c000b410e4101101c000b410e4101101c000b410e4101101c000b41174101101c000b200328021c10190b200341c0006a24000b19002000200141186a280200360204200020012802103602000b0c00200028020020011089020bc907020b7f017e230041e0006b22032400200320013602202002280208220441586a2105200241106a2802002206412c6c21020240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004102470d000b200341186a200810d20220032802182107200328021c21020c010b410021070b2002410020071b21092006412c6c2102200441586a2105200741d889c20020071b210a0240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004104470d000b200341106a200810d2022003280210210b2003280214210c0c010b4100210b0b2006412c6c2102200441586a2105200b41d889c200200b1b210d02400240024002400240024002400240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d012006412c6c2102200441586a210503402002450d06200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200341086a200810d202200328020c220b41286c210520032802082204210703402005450d05200541586a2105200741186a2108200741286a2202210720082d00000d000b2001450d022004200b41286c6a210803402001417f6a2101034020082002460d06200241186a2105200241286a2207210220052d00000d000b2007210220010d000b200741586a21020c030b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a2202450d00200320022802002202360224200920024d0d060c050b200341cc006a41013602002003410236022c2003420237023c200341bcd5c3003602382003200341206a3602282003200341286a360248200341d0006a200341386a10242003290254210e200328025021020c060b200241586a21020b20032002411c6a2802002202360224200920024b0d020c030b41d4f9c10041dd001030000b4192f9c10041c2001030000b200a20024104746a2202450d002000410036020020002002360204200341e0006a24000f0b200341dc006a4102360200200341cc006a4102360200200341023602542003420337023c200341ccd5c3003602382003200341206a3602582003200341246a3602502003200341d0006a360248200341286a200341386a1024200329022c210e200328022821020b2000200236020420004101360200200041086a200e370200200341e0006a24000bf50303047f017e017f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d00200020014105746a220441386a2802002105200441346a2802002106200141016a2101200441c4006a2802004102460d030c010b0240024020002802002201450d0020003301044220862003ad842107410121040c010b2003ad210741002104410021010b200010192007a72103024002402007422088a7220620012f01064f0d00200121050c010b03400240024020012802002205450d00200441016a210420013301044220862003ad8421070c010b2003ad2107410021050b200110192007a72103200521012007422088a7220620052f01064f0d000b0b200520064102746a4198036a2802002100200520064105746a220141c4006a2802002108200141386a2802002105200141346a2802002106024020044101460d00410120046b210103402000280294032100200141016a22010d000b0b4100210120084102460d020b2002417f6a210202402005450d00200610190b20020d000b0b0240200041a0c0c100460d0020002802002101200010192001450d0020012802002105200110192005450d00024020052802002201450d000340200510192001210520012802002200210120000d000b0b200510190b0b910302067f017e230041106b2202240002400240024002400240024002400240200041046a2802002203200028020822046b20012802042205200128020022066b41047622074f0d00200420076a22062004490d0320034101742204200620062004491b2206ad4204862208422088a70d032008a722044100480d032003450d01200028020020034104742004101a2203450d020c040b2000280200210320062005460d040c050b2004101b22030d020b20044108101c000b101d000b20002003360200200041046a2006360200200041086a280200210420012802002206200141046a280200470d010b410021060c010b2001200641106a3602000b2002200610fc02024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a2903003703000240024020012802002203200141046a280200460d002001200341106a3602000c010b410021030b200441016a2104200641106a21062002200310fc0220022d000041ac01470d000b0b200041086a2004360200200241106a24000bc80903037f017e017f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001450d0020012d00002202417e6a2203412e4b0d01024020030e2f001f233030152019301e0b30300e0d1d271a0c161c242212112829061b0a091025172605140721080403182b2a130f000b20012d00012104410221020c2f0b200041ac013a00000f0b0c2b0b20012d00012104412b21020c2c0b200141046a280200210620013502082105412a21020c2a0b200141046a280200210620013502082105412521020c290b200141046a280200210620013502082105411d21020c280b200141046a280200210620013502082105412721020c270b200141046a280200210620013502082105412921020c260b200141046a280200210620013502082105412021020c250b200141046a280200210620013502082105411f21020c240b200141046a280200210620012d00012104410c21020c240b200141046a280200210620013502082105411421020c220b200141046a2802002106411021020c210b200141046a2802002106410f21020c200b20012903082105413021020c1e0b200141046a280200210620013502082105412121020c1e0b200141046a280200210620013502082105411a21020c1d0b200141046a280200210620013502082105411921020c1c0b200141046a2802002106412f21020c1b0b200141046a280200210620013502082105412621020c1a0b200141046a2802002106410721020c190b200141046a280200210620013502082105411521020c180b200141046a280200210620013502082105412321020c170b20012d00012104412c21020c170b20012802082204ad2205421e88a70d122005420286a72202417f4c0d124104210602402002450d002002101b2206450d140b02402004450d00200141046a28020021022004410274210320062104034020042002280200360200200441046a2104200241046a21022003417c6a22030d000b0b2001410c6a3502004220862005842105410921020c150b200141046a2802002106411321020c140b200141046a280200210620013502082105411e21020c130b200141046a280200210620013502082105411621020c120b200141046a2802002106411121020c110b200141046a2802002106410b21020c100b20012d00012104410321020c100b200141046a2802002106410821020c0e0b200141046a280200210620013502082105412821020c0d0b200141046a280200210620013502082105411821020c0c0b20012d00012104410421020c0c0b200141046a280200210620013502082105411721020c0a0b200141046a280200210620013502082105412221020c090b200141046a280200210620013502082105412421020c080b200141046a2802002106411221020c070b200141046a280200210620013502082105411b21020c060b200141046a280200210620013502082105411c21020c050b20012903082105412e21020c030b200141046a2802002106412d21020c030b102b000b20024104101c000b0b0b200020043a0001200020023a0000200041086a2005370300200041046a20063602000ba00201027f02400240024002402001410c6a2802002203417f6a220420034d0d004116101b2201450d01200020013602042001410e6a41002900ab8042370000200141086a41002900a580423700002001410029009d8042370000200041086a4296808080e002370200200041013602000f0b0240200420026b220220044d0d00411b101b2201450d0220002001360204200141176a41002800ca8042360000200141106a41002900c38042370000200141086a41002900bb8042370000200141002900b38042370000200041086a429b808080b003370200200041013602000f0b200320024d0d022000200141046a28020020024104746a360204200041003602000f0b41164101101c000b411b4101101c000b41b4d6c30020022003104a000bf60201037f230041106b22032400024002402002450d0020032001410010fd0220032802004101470d01200020034104722202290200370200200041086a200241086a280200360200200341106a24000f0b20004100360200200341106a24000f0b02400240024002402001280200220420032802042205280208470d0020052d000c450d0120004100360200200341106a24000f0b0240200420026b220220044d0d00410f101b2202450d022000428f808080f00137020420002002360200200241076a410029009580423700002002410029008e8042370000200341106a24000f0b2000410036020020012002360200200341106a24000f0b4125101b2202450d01200042a5808080d004370204200020023602002002411d6a41002900868042370000200241186a41002900818042370000200241106a41002900f9ff41370000200241086a41002900f1ff41370000200241002900e9ff41370000200341106a24000f0b410f4101101c000b41254101101c000b931001157f024020002802082201450d00200028020022022001412c6c6a2103034020022204412c6a21020240024002400240024002400240024002400240024002400240024002400240024002400240024020042d00002200410d4b0d00024020000e0e000203040506070809140a0b0c0d000b200441086a280200450d13200441046a280200101920022003470d140c150b0240200441086a280200450d00200441046a28020010190b0240200441146a2802002200450d00200441186a280200450d00200010190b200441246a280200450d12200441206a280200101920022003470d130c140b0240200441086a280200450d00200441046a28020010190b200441146a280200450d11200441106a280200101920022003470d120c130b200441046a210502402004410c6a2802002201450d00200528020021002001410474210103400240200041046a280200450d00200028020010190b200041106a2100200141706a22010d000b0b200441086a280200450d102005280200101920022003470d110c120b200441046a210502402004410c6a2802002201450d0020052802002100200141286c210103400240200041046a280200450d00200028020010190b0240200041106a280200450d002000410c6a28020010190b200041286a2100200141586a22010d000b0b200441086a280200450d0f2005280200101920022003470d100c110b200441086a280200450d0e200441046a280200101920022003470d0f0c100b200441086a280200450d0d200441046a280200101920022003470d0e0c0f0b200441086a280200450d0c200441046a280200101920022003470d0d0c0e0b200441046a21062004410c6a2802002200450d0a2006280200220720004104746a2108410021000c050b200441046a210502402004410c6a2802002201450d0020052802002100200141146c210103400240200041046a280200450d00200028020010190b200041146a21002001416c6a22010d000b0b200441086a280200450d0a2005280200101920022003470d0b0c0c0b200441046a21092004410c6a2802002200450d072009280200220a2000411c6c6a210b410121000c030b200441046a210c2004410c6a2802002200450d05200c280200220d200041186c6a210e410221000c020b200441046a210f2004410c6a2802002200450d03200f28020022102000411c6c6a2111410321000c010b024002400240200441046a2d000022004102460d0020004101460d0120000d022004410c6a280200450d09200441086a280200101920022003470d0a0c0b0b2004410c6a2112200441146a2802002200450d032012280200221320004104746a2114410421000c020b2004410c6a21150240200441146a2802002201450d00201528020021002001410c6c21010340024020002802002205450d00200041046a280200450d00200510190b2000410c6a2100200141746a22010d000b0b200441106a280200450d072015280200101920022003470d080c090b2004410c6a280200450d06200441086a28020010190c060b0340024002400240024002400240024002400240024020000e050001020304040b024020072802082201450d0020072802002100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010190b200041106a2100200141706a22010d000b0b200741106a21000240200741046a280200450d00200728020010190b2000210720002008470d040c0e0b0240200a410c6a2802002201450d00200a2802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010190b200041106a2100200141706a22010d000b0b0240200a41086a280200450d00200a41046a28020010190b200a411c6a21000240200a41146a280200450d00200a28021010190b2000210a2000200b470d040c0c0b0240200d41046a280200450d00200d28020010190b0240200d41146a2802002201450d00200d28020c2100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010190b200041106a2100200141706a22010d000b0b200d41186a21000240200d41106a280200450d00200d410c6a28020010190b2000210d2000200e470d040c0a0b02402010410c6a2802002201450d0020102802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010190b200041106a2100200141706a22010d000b0b0240201041086a280200450d00201041046a28020010190b2010411c6a21000240201041146a280200450d00201028021010190b2000211020002011470d040c080b2013221541106a2113024020152802042200450d0002402015410c6a2802002201450d002001410c6c21010340024020002802002205450d00200041046a280200450d00200510190b2000410c6a2100200141746a22010d000b0b201541086a280200450d00201541046a28020010190b20132014470d040c060b410021000c040b410121000c030b410221000c020b410321000c010b410421000c000b0b200441106a280200450d042012280200101920022003470d050c060b200441086a280200450d03200f280200101920022003470d040c050b200441086a280200450d02200c280200101920022003470d030c040b200441086a280200450d012009280200101920022003470d020c030b200441086a280200450d002006280200101920022003470d010c020b20022003470d000b0b0be80701037f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001413f4b0d00200241046a280200200241086a2802002203470d01200341016a22042003490d1120034101742205200420042005491b22054100480d112003450d05200228020020032005101a2204450d060c170b2001418080014f0d01200241046a2802002204200241086a28020022036b41024f0d02200341026a22052003490d1020044101742203200520052003491b22034100480d102004450d08200228020020042003101a2204450d090c140b200228020021040c160b20014180808080044f0d01200241046a2802002204200241086a28020022036b41044f0d04200341046a22052003490d0e20044101742203200520052003491b22034100480d0e2004450d08200228020020042003101a22040d090c0f0b200228020021040c120b200241046a280200200241086a2802002203470d03200341016a22042003490d0c20034101742205200420042005491b22054100480d0c2003450d09200228020020032005101a22040d0a0c0e0b2005101b22040d110b20054101101c000b200228020021040c050b200228020021040c070b2003101b22040d0b0b20034101101c000b2003101b2204450d060b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a2001410274410272360000200141037422010d0b0c0c0b2005101b2204450d040b20022004360200200241046a2005360200200241086a28020021030b200241086a2205200341016a360200200420036a41033a00000240024002400240200241046a2802002204200528020022036b41044f0d00200341046a22052003490d0420044101742203200520052003491b22034100480d042004450d01200228020020042003101a22040d020c070b200228020021040c020b2003101b2204450d050b20022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a200136000020014103742201450d090c080b101d000b20034101101c000b20054101101c000b20034101101c000b20022004360200200241046a2003360200200241086a28020021030b200241086a200341026a360200200420036a20014102744101723b0000200141037422010d020c030b20022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20014102743a000020014103742201450d010b200020016a210103402000280200200041046a2802002002109802200041086a22002001470d000b0b0bd50101027f200028020421020240024020002802004101470d002000410c6a280200220020011097022000450d01200041186c2103200241146a21000340200041706a280200200041746a28020020011098022000417c6a28020020002802002001109802200041186a2100200341686a22030d000c020b0b200041086a280200220020011097022000450d00200041186c2103200241146a21000340200041706a280200200041746a28020020011098022000417c6a28020020002802002001109802200041186a2100200341686a22030d000b0b0b2700200028020c200041106a2802001004200041146a3502001014200041186a350200101400000b0600200010150b0600200010160b2801017f0240200210152203450d002003200020022001200120024b1b1095031a200010160b20030b1c01017f0240200010152201450d002001410020001094031a0b20010b9709010a7f230041c0006b22032400200341246a2001360200200341346a200241146a2802002204360200200341033a00382003412c6a2002280210220520044103746a3602002003428080808080043703082003200036022041002106200341003602182003410036021020032005360230200320053602280240024002400240024002400240024020022802082207450d0020022802002108200228020422092002410c6a2802002205200520094b1b220a450d01200020082802002008280204200128020c1100000d02200841086a2105200341386a2100200341346a2101200341306a210b4101210603402000200741206a2d00003a00002003200741086a28020036020c20032007410c6a280200360208410021020240024002400240200741186a28020022044101460d00024020044103460d0020044102470d02200341086a41206a2204280200220c200341086a41246a280200460d002004200c41086a360200200c2802044122470d04200c28020028020021040c030b0c030b2007411c6a280200220c200128020022044f0d0a200b280200200c4103746a220c2802044122470d02200c28020028020021040c010b2007411c6a28020021040b410121020b200341086a410c6a2004360200200341086a41086a2002360200410021020240024002400240200741106a28020022044101460d00024020044103460d0020044102470d02200341086a41206a2204280200220c200341086a41246a280200460d002004200c41086a360200200c2802044122470d04200c28020028020021040c030b0c030b200741146a280200220c200128020022044f0d0b200b280200200c4103746a220c2802044122470d02200c28020028020021040c010b200741146a28020021040b410121020b200341086a41146a2004360200200341086a41106a20023602000240024020072802004101470d00200741046a2802002202200128020022044f0d07200b28020020024103746a21020c010b200341086a41206a22042802002202200341086a41246a280200460d072004200241086a3602000b2002280200200341086a200241046a2802001104000d032006200a4f0d02200541046a210220052802002104200541086a2105200741246a2107200641016a2106200341086a41186a28020020042002280200200341086a411c6a28020028020c110000450d000c030b0b20022802002108200228020422092004200420094b1b220a450d00200020082802002008280204200128020c1100000d01200841086a2107200341206a2100200341246a21014101210603402005280200200341086a200541046a2802001104000d022006200a4f0d01200741046a210220072802002104200541086a2105200741086a2107200641016a2106200028020020042002280200200128020028020c110000450d000c020b0b200920064d0d01200341206a280200200820064103746a22072802002007280204200341246a28020028020c110000450d010b200341c0006a240041010f0b200341c0006a240041000f0b419cdbc30020022004104a000b41acdac3001029000b418cdbc300200c2004104a000b418cdbc300200c2004104a000b7701017f230041c0006b220024002000413336020c200041c386c200360208200041346a4123360200200041246a41023602002000410336022c20004202370214200041d4d8c3003602102000200041386a3602302000200041086a3602282000200041286a360220200041106a41e4d8c30010f201000b1c002001280218418ba5c20041052001411c6a28020028020c1100000b02000bba0101037f024002400240024002400240200028020022002802042203200028020822046b20024f0d00200420026a22052004490d0320034101742204200520052004491b22044100480d032003450d01200028020020032004101a2203450d020c040b200028020021030c040b2004101b22030d020b20044101101c000b101d000b20002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a200120021095031a41000bba0401047f230041106b22022400200028020021000240024002400240024002400240024002400240024020014180014f0d00200028020822032000280204470d09200341016a22042003490d0520034101742205200420042005491b22044100480d052003450d01200028020020032004101a2203450d020c080b2002410036020c0240024020014180104f0d0020022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b0240200141ffff034b0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b024020002802042204200028020822036b20014f0d00200320016a22052003490d0520044101742203200520052003491b22034100480d052004450d03200028020020042003101a2204450d040c060b200028020021040c060b2004101b22030d060b20044101101c000b2003101b22040d020b20034101101c000b101d000b20002004360200200041046a2003360200200041086a28020021030b200041086a200320016a360200200420036a2002410c6a20011095031a0c020b20002003360200200041046a2004360200200041086a28020021030b200028020020036a20013a0000200041086a2200200028020041016a3602000b200241106a240041000b6401017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41bcd8c300200241086a1087032101200241206a240020010b0d0042d4f18ccec2c4aeaed4000bfb09010c7f230041106b2203240020002802102104024002400240024002400240024002400240200028020822054101470d0020040d010c020b2004450d070b02402002450d00200120026a2106200041146a280200417f732107410021082001210420012109024002400340200441016a210a0240024020042c0000220b4100480d00200b41ff0171210b200a2104200741016a22070d010c030b024002400240200a2006460d00200a2d0000413f71210c200441026a2204210a200b411f71210d200b41ff0171220b41e001490d010c020b4100210c20062104200b411f71210d200b41ff0171220b41e0014f0d010b200c200d41067472210b200a2104200741016a22070d010c030b02400240024020042006460d00200441016a220a210e20042d0000413f71200c41067472210c200b41f001490d010c020b2006210e4100200c41067472210c200b41f0014f0d010b200c200d410c7472210b200a2104200741016a22070d010c030b02400240200e2006460d00200e41016a2104200e2d0000413f71210b0c010b4100210b200a21040b200c410674200d411274418080f0007172200b72220b418080c400460d03200741016a2207450d020b200820096b20046a21082004210920062004470d000c020b0b200b418080c400460d00024002402008450d0020082002460d0041002104200820024f0d01200120086a2c00004140480d010b200121040b2008200220041b21022004200120041b21010b2005450d020c010b410021022005450d010b4100210a02402002450d002002210b200121040340200a20042d000041c00171418001466a210a200441016a2104200b417f6a220b0d000b0b2002200a6b2000410c6a28020022074f0d014100210a02402002450d004100210a2002210b200121040340200a20042d000041c00171418001466a210a200441016a2104200b417f6a220b0d000b0b200a20026b20076a210b410020002d0030220420044103461b4103712204450d0220044102460d03410021070c040b2000280218200120022000411c6a28020028020c1100002104200341106a240020040f0b2000280218200120022000411c6a28020028020c1100002104200341106a240020040f0b200b21074100210b0c010b200b41016a4101762107200b410176210b0b2003410036020c024002402000280204220441ff004b0d00200320043a000c4101210a0c010b0240200441ff0f4b0d0020032004413f71418001723a000d20032004410676411f7141c001723a000c4102210a0c010b0240200441ffff034b0d0020032004413f71418001723a000e20032004410676413f71418001723a000d20032004410c76410f7141e001723a000c4103210a0c010b20032004413f71418001723a000f2003200441127641f001723a000c20032004410676413f71418001723a000e20032004410c76413f71418001723a000d4104210a0b417f21040240024002400340200441016a2204200b4f0d01200041186a2802002003410c6a200a2000411c6a28020028020c110000450d000c020b0b200041186a220b280200200120022000411c6a220028020028020c110000450d010b200341106a240041010f0b417f210402400340200441016a220420074f0d01200b2802002003410c6a200a200028020028020c110000450d000b200341106a240041010f0b200341106a240041000f0b2000280218200120022000411c6a28020028020c1100002104200341106a240020040b7c01017f230041306b22022400200241146a41243602002002412436020c200220003602082002200041046a3602102001411c6a2802002100200128021821012002412c6a41023602002002420237021c200241fcdac3003602182002200241086a36022820012000200241186a1087032101200241306a240020010bf80201097f230041106b22022400410121030240200128021841272001411c6a22042802002802101104000d00200220002802001085022002410c6a2d00002105200241086a28020021062002280200210320022802042207418080c400472108200141186a21090340024002400240024002400240024020034101460d0041dc00210020034102460d0120034103470d05200541ff01712103410421052003417f6a220a41044b0d05410321030240200a0e050003040507000b4100210541fd0021000c060b410021032007210020080d050c040b410121030c040b20072006410274411c7176410f712200413072200041d7006a2000410a491b21004102410120061b21052006417f6a410020061b21060c030b4102210541fb0021000c020b4103210341f5002100410321050c010b200141186a28020041272001411c6a28020028021011040021030c020b200928020020002004280200280210110400450d000b200241106a240041010f0b200241106a240020030bbe0201037f23004180016b220224000240024002400240200128020022034110710d0020034120710d0120002001108902210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441d7006a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141b68cc2004102200220006a4180016a410020006b108302210020024180016a240020000f0b20002802002103410021000340200220006a41ff006a2003410f712204413072200441376a2004410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d012001410141b68cc2004102200220006a4180016a410020006b108302210020024180016a240020000f0b20034180011027000b20034180011027000b0900200020011089020b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f02400240200120004f0d002002450d012001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000c020b0b2002450d00200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000b0b20000b4401037f024002402002450d00410021030340200020036a2d00002204200120036a2d00002205470d02200341016a22032002490d000b41000f0b41000f0b200420056b0b3e01017f230041106b22052400200520012002200320044100109c03200529030021012000200541086a29030037030820002001370300200541106a24000b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080bb70502037f057e230041306b2206240002400240024002400240024002400240024002400240024002400240024020024200510d002003500d012004500d03200479a7200279a76b2207413f4b0d0241ff0020076b2108200741016a21070c0c0b200450450d012005450d0520034200510d0d20054200370308200520012003823703000c060b2004500d0c20014200510d032004427f7c2209200483500d07200479a7200279a76b2207413e4d0d090b2005450d012005200137030020052002370308420021010c070b2003427f7c2209200383500d044100200379a741c1006a200279a76b22076b21080c080b420021010c050b02402005450d0020054200370300200520022004823703080b200220048021010c040b20034200510d070b200120038021010c020b02402005450d0020054200370308200520092001833703000b20034201510d04200641206a2001200220037aa7109b03200641286a2903002102200629032021010c040b02402005450d0020052001370300200520092002833703080b200220047a423f838821010b420021020c020b41ff0020076b2108200741016a21070b200620012002200841ff0071109a03200641106a20012002200741ff0071109b03200641086a2903002102200641106a41086a290300210a20062903002101200629031021094200210b0340200a4201862009423f8884220c200c427f8520047c20094201862002423f88842209427f85220c20037c200c54ad7c423f87220c2004837d2009200c200383220d54ad7d210a2009200d7d2109420020024201862001423f8884842102200b2001420186842101200c420183220c210b2007417f6a22070d000b02402005450d00200520093703002005200a3703080b20024201862001423f88842102200c20014201868421010b2000200137030020002002370308200641306a24000f0b00000b0ba5e8030200418080c0000b90a502746f6f206d616e7920696e737472756374696f6e73547269656420746f20736872696e6b20746f2061206c617267657220636170616369747953797374656d2045787472696e736963436f756e7453797374656d20416c6c45787472696e736963734c656e626164206f726967696e3a20657870656374656420746f206265206120726f6f74206f726967696e626164206f726967696e3a20657870656374656420746f2062652061207369676e6564206f726967696e626164206f726967696e3a20657870656374656420746f20626520616e20696e686572656e74206f726967696e3a617574683a53797374656d2045787472696e7369634461746153797374656d2044696765737453797374656d2052616e646f6d5365656453797374656d204e756d62657253797374656d2045787472696e73696373526f6f7441757261204c61737454696d657374616d70436f6e73656e737573204f726967696e616c417574686f72697469657353797374656d204576656e747353797374656d20426c6f636b4861736853797374656d204163636f756e744e6f6e63654175726120736c6f74206475726174696f6e2063616e6e6f74206265207a65726f2e2f55736572732f612f7372632f737562737472617465322f73726d6c2f617572612f7372632f6c69622e72734f6e6c79206f6e6520626c6f636b206d617920626520617574686f7265642070657220736c6f742e3a65787472696e7369635f696e6465782f55736572732f612f7372632f737562737472617465322f73726d6c2f636f6e73656e7375732f7372632f6c69622e7273000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f55736572732f612f7372632f737562737472617465322f73726d6c2f617572612f7372632f6c69622e727374696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c6f66666c726570304e6f20606f66666c696e655f7265706f72746020666f756e6420696e2074686520696e686572656e7420646174612173657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a09090971656453797374656d20506172656e7448617368426c6f636b206e756d626572206d6179206e65766572206265207a65726f2f55736572732f612f7372632f737562737472617465322f73726d6c2f73797374656d2f7372632f6c69622e727353797374656d4163636f756e744e6f6e6365543a3a496e64657845787472696e736963436f756e74416c6c45787472696e736963734c656e426c6f636b4861736845787472696e7369634461746152616e646f6d536565644e756d626572506172656e744861736845787472696e73696373526f6f74446967657374543a3a4469676573744576656e74735665633c4576656e745265636f72643c543a3a4576656e743e3e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e6e6f74655f6f66666c696e6572656d61726b7365745f686561705f70616765737365745f636f64657365745f73746f726167652053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573753634204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b204e6f7465207468652070726576696f757320626c6f636b27732076616c696461746f72206d6973736564207468656972206f70706f7274756e69747920746f2070726f706f7365206120626c6f636b2e6f66666c696e653c543a3a496e686572656e744f66666c696e655265706f727420617320496e686572656e744f66666c696e655265706f72743e3a3a496e686572656e74436f6e73656e7375734f726967696e616c417574686f7269746965735665633c543a3a53657373696f6e4b65793e3a6865617070616765733a636f6465647572696e6720657865637574696f6e2f55736572732f612f7372632f737562737472617465322f73726d6c2f636f6e74726163742f7372632f7761736d2f72756e74696d652e72730000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e7273707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090960656d7074795f6f75747075745f627566602069732074616b656e206f6e6c7920686572653b0a09090909606578745f72657475726e602074726170733b0a090909096052756e74696d65602063616e206f6e6c792062652075736564206f6e6c7920666f72206f6e6520657865637574696f6e3b0a09090909716564436f756e63696c20416374697665436f756e63696c566f746572526561706564426164526561706572536c617368656454616c6c795374617274656454616c6c7946696e616c6973656420412074616c6c792028666f7220617070726f76616c20766f746573206f6620636f756e63696c2073656174287329292068617320656e646564202877697468206f6e65206f72206d6f7265206e6577206d656d62657273292e20412074616c6c792028666f7220617070726f76616c20766f746573206f6620636f756e63696c2073656174287329292068617320737461727465642e20736c6173686564207265617065722072656170656420766f7465722c20726561706572436f756e63696c20566f74696e67506572696f64436f756e63696c20446573697265645365617473436f756e63696c204e65787446696e616c697365436f756e63696c205465726d4475726174696f6e436f756e63696c2050726573656e746174696f6e4475726174696f6e436f756e63696c20566f74657273436f756e63696c20536e617073686f7465645374616b6573436f756e63696c204361727279436f756e74436f756e63696c204c6561646572626f617264436f756e63696c205265676973746572496e666f4f66436f756e63696c2043616e64696461746573436f756e63696c2043616e646964617465436f756e74436f756e63696c20566f7465436f756e74436f756e63696c2043616e646964616379426f6e6466696e616c6973652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e00002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f7365745f617070726f76616c73726561705f696e6163746976655f766f746572726574726163745f766f7465727375626d69745f63616e64696461637970726573656e745f77696e6e65727365745f646573697265645f736561747372656d6f76655f6d656d6265727365745f70726573656e746174696f6e5f6475726174696f6e7365745f7465726d5f6475726174696f6e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e74206120766f7465206265696e672070726573656e74656420666f722c2077696c6c20696e766f6b65206066696e616c6973655f766f7465602e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e746c79206120766f7465206265696e672070726573656e74656420666f722c2077696c6c636f756e742052656d6f7665206120706172746963756c6172206d656d6265722e20412074616c6c792077696c6c2068617070656e20696e7374616e746c7920286966206e6f7420616c726561647920696e20612070726573656e746174696f6e20706572696f642920746f2066696c6c2074686520736561742069662072656d6f76616c206d65616e732074686174207468652064657369726564206d656d6265727320617265206e6f74206d65742e20546869732069732065666665637469766520696d6d6564696174656c792e20536574207468652064657369726564206d656d62657220636f756e743b206966206c6f776572207468616e207468652063757272656e7420636f756e742c207468656e2073656174732077696c6c206e6f7420626520757020656c656374696f6e207768656e2074686579206578706972652e204966206d6f72652c207468656e2061206e657720766f74652077696c6c2062652073746172746564206966206f6e65206973206e6f7420616c726561647920696e2070726f67726573732e20436c61696d207468617420607369676e656460206973206f6e65206f662074686520746f702053656c663a3a63617272795f636f756e742829202b2063757272656e745f766f746528292e312063616e646964617465732e204f6e6c7920776f726b73206966207468652060626c6f636b5f6e756d626572203e3d2063757272656e745f766f746528292e306020616e6420603c2063757272656e745f766f746528292e30202b2070726573656e746174696f6e5f6475726174696f6e2829606020607369676e6564602073686f756c642068617665206174206c6561737463616e646964617465746f74616c436f6d706163743c566f7465496e6465783e205375626d6974206f6e6573656c6620666f722063616e6469646163792e204163636f756e74206d757374206861766520656e6f756768207472616e736665727261626c652066756e647320696e20697420746f207061792074686520626f6e642e736c6f742052656d6f7665206120766f7465722e20416c6c20766f746573206172652063616e63656c6c656420616e642074686520766f746572206465706f7369742069732072657475726e65642e2052656d6f7665206120766f7465722e20466f72206974206e6f7420746f206265206120626f6e642d636f6e73756d696e67206e6f2d6f702c20616c6c20617070726f7665642063616e64696461746520696e6469636573206d757374206e6f772062652065697468657220756e72656769737465726564206f72207265676973746572656420746f20612063616e646964617465207468617420726567697374657265642074686520736c6f742061667465722074686520766f7465722067617665207468656972206c61737420617070726f76616c207365742e204d61792062652063616c6c656420627920616e796f6e652e2052657475726e732074686520766f746572206465706f73697420746f20607369676e6564602e7265706f727465725f696e64657877686f5f696e646578617373756d65645f766f74655f696e646578205365742063616e64696461746520617070726f76616c732e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e766f7465735665633c626f6f6c3e436f756e63696c43616e646964616379426f6e64566f74696e67426f6e6450726573656e74536c617368506572566f7465724361727279436f756e7450726573656e746174696f6e4475726174696f6e496e6163746976654772616365506572696f64566f7465496e6465785465726d4475726174696f6e446573697265645365617473416374697665436f756e63696c5665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d626572293e566f7465436f756e74417070726f76616c734f665265676973746572496e666f4f6628566f7465496e6465782c20753332294c6173744163746976654f66566f7465727343616e6469646174657343616e646964617465436f756e744e65787446696e616c69736528543a3a426c6f636b4e756d6265722c207533322c205665633c543a3a4163636f756e7449643e29536e617073686f7465645374616b65735665633c42616c616e63654f663c543e3e4c6561646572626f6172645665633c2842616c616e63654f663c543e2c20543a3a4163636f756e744964293e2047657420746865206c6561646572626f6172642069662077653b726520696e207468652070726573656e746174696f6e2070686173652e20546865207374616b6573206173207468657920776572652061742074686520706f696e7420746861742074686520766f746520656e6465642e20546865206163636f756e747320686f6c64696e672074686520736561747320746861742077696c6c206265636f6d652066726565206f6e20746865206e6578742074616c6c792e205468652070726573656e742063616e646964617465206c6973742e205468652070726573656e7420766f746572206c6973742e20546865206c61737420636c656172656420766f746520696e6465782074686174207468697320766f74657220776173206c617374206163746976652061742e2054686520766f746520696e64657820616e64206c69737420736c6f742074686174207468652063616e646964617465206077686f60207761732072656769737465726564206f7220604e6f6e6560206966207468657920617265206e6f742063757272656e746c7920726567697374657265642e2041206c697374206f6620766f74657320666f72206561636820766f7465722c2072657370656374696e6720746865206c61737420636c656172656420766f746520696e6465782074686174207468697320766f74657220776173206c617374206163746976652061742e2054686520746f74616c206e756d626572206f6620766f746573207468617420686176652068617070656e6564206f722061726520696e2070726f67726573732e205468652063757272656e7420636f756e63696c2e205768656e2074686572652773206120766f746520676f696e67206f6e2c20746869732073686f756c64207374696c6c206265207573656420666f7220657865637574697665206d6174746572732e2054686520626c6f636b206e756d62657220287365636f6e6420656c656d656e7420696e20746865207475706c65292069732074686520626c6f636b207468617420746865697220706f736974696f6e2069732061637469766520756e74696c202863616c63756c61746564206279207468652073756d206f662074686520626c6f636b206e756d626572207768656e2074686520636f756e63696c206d656d6265722077617320656c656374656420616e64207468656972207465726d206475726174696f6e292e204e756d626572206f66206163636f756e747320746861742073686f756c642062652073697474696e67206f6e2074686520636f756e63696c2e20486f77206c6f6e67206561636820706f736974696f6e2069732061637469766520666f722e20486f77206d616e7920766f746520696e6465786573206e65656420746f20676f20627920616674657220612074617267657420766f7465722773206c61737420766f7465206265666f726520746865792063616e2062652072656170656420696620746865697220617070726f76616c7320617265206d6f6f742e20486f77206c6f6e6720746f2067697665206561636820746f702063616e64696461746520746f2070726573656e74207468656d73656c7665732061667465722074686520766f746520656e64732e20486f77206d616e792072756e6e6572732d75702073686f756c64206861766520746865697220617070726f76616c73207065727369737420756e74696c20746865206e65787420766f74652e205468652070756e6973686d656e742c2070657220766f7465722c20696620796f752070726f7669646520616e20696e76616c69642070726573656e746174696f6e2e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f2062652061626c6520746f207375626d697420766f7465732e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f207375626d6974206f6e6527732063616e6469646163792e2f55736572732f612f7372632f737562737472617465322f73726d6c2f636f756e63696c2f7372632f73656174732e72736e6f20617070726f76616c206368616e67657320647572696e672070726573656e746174696f6e20706572696f64696e636f727265637420766f746520696e646578616d6f756e74206f662063616e6469646174657320746f207265636569766520617070726f76616c20766f7465732073686f756c64206265206e6f6e2d7a65726f616d6f756e74206f662063616e64696461746520617070726f76616c20766f7465732063616e6e6f742065786365656420616d6f756e74206f662063616e64696461746573436f756e63696c204c6173744163746976654f66436f756e63696c20566f74696e67426f6e64436f756e63696c20417070726f76616c734f6663616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f647265706f72746572206d757374206265206120766f746572766f746520696e646578206e6f742063757272656e7463616e6e6f74207265617020647572696e6720677261636520706572696f6474617267657420666f7220696e616374697669747920636c65616e7570206d75737420626520616374697665626164207265706f7274657220696e646578436f756e63696c20496e6163746976654772616365506572696f646261642074617267657420696e64657863616e6e6f742072657472616374207768656e2070726573656e74696e6763616e6e6f742072657472616374206e6f6e2d766f74657272657472616374696f6e20696e64657820696e76616c696472657472616374696f6e20696e646578206d69736d617463686475706c69636174652063616e646964617465207375626d697373696f6e696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e64737374616b65206465706f736974656420746f2070726573656e742077696e6e657220616e6420626520616464656420746f206c6561646572626f6172642073686f756c64206265206e6f6e2d7a65726f63616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64696e646578206e6f742063757272656e746c6561646572626f617264206d757374206578697374207768696c652070726573656e742070686173652061637469766570726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647363616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c656374656470726573656e7465642063616e646964617465206d7573742062652063757272656e74436f756e63696c2050726573656e74536c617368506572566f7465726475706c69636174652070726573656e746174696f6e696e636f727265637420746f74616c5374616b696e6720426f6e646167655374616b696e67204e6f6d696e61746f7273466f725265776172644f66666c696e655761726e696e674f66666c696e65536c617368204f6e652076616c696461746f722028616e64207468656972206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e204f6e652076616c696461746f722028616e64207468656972206e6f6d696e61746f72732920686173206265656e20676976656e2061206f66666c696e652d7761726e696e67202874686579277265207374696c6c2077697468696e207468656972206772616365292e205468652061636372756564206e756d626572206f6620736c6173686573206973207265636f726465642c20746f6f2e20416c6c2076616c696461746f72732068617665206265656e2072657761726465642062792074686520676976656e2062616c616e63652e7374616b65756e7374616b656e6f6d696e617465756e6e6f6d696e61746572656769737465725f707265666572656e6365737365745f73657373696f6e735f7065725f6572617365745f626f6e64696e675f6475726174696f6e7365745f76616c696461746f725f636f756e74666f7263655f6e65775f6572617365745f6f66666c696e655f736c6173685f67726163657365745f696e76756c6e657261626c657320536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e76616c696461746f72732053657420746865206f66666c696e6520736c61736820677261636520706572696f642e20466f72636520746865726520746f2062652061206e6577206572612e205468697320616c736f20666f726365732061206e65772073657373696f6e20696d6d6564696174656c792061667465722e20606170706c795f72657761726473602073686f756c64206265207472756520666f722076616c696461746f727320746f20676574207468652073657373696f6e207265776172642e2054686520696465616c206e756d626572206f662076616c696461746f72732e20546865206c656e677468206f662074686520626f6e64696e67206475726174696f6e20696e20657261732e2053657420746865206e756d626572206f662073657373696f6e7320696e20616e206572612e205365742074686520676976656e206163636f756e74277320707265666572656e636520666f7220736c617368696e67206265686176696f75722073686f756c64207468657920626520612076616c696461746f722e20416e206572726f7220286e6f2d6f7029206966206053656c663a3a696e74656e74696f6e7328295b696e74656e74696f6e735f696e6465785d20213d206f726967696e602e696e74656e74696f6e735f696e646578707265667356616c696461746f7250726566733c42616c616e63654f663c543e3e2057696c6c2070616e69632069662063616c6c6564207768656e20736f757263652069736e27742063757272656e746c79206e6f6d696e6174696e67207461726765742e2055706461746573204e6f6d696e6174696e672c204e6f6d696e61746f7273466f7220616e64204e6f6d696e6174696f6e42616c616e63652e7461726765745f696e6465787461726765742052657472616374207468652064657369726520746f207374616b6520666f7220746865207472616e736163746f722e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e204465636c617265207468652064657369726520746f207374616b6520666f7220746865207472616e736163746f722e5374616b696e675374616b696e6720496e76756c657261626c65735374616b696e6720536c617368436f756e745374616b696e67204f66666c696e65536c61736847726163655374616b696e6720526563656e746c794f66666c696e6576206973206e6f6e2d656d7074793b207165645374616b696e672043757272656e744f66666c696e65536c6173685374616b696e6720496e74656e74696f6e735374616b696e67204d696e696d756d56616c696461746f72436f756e745374616b696e672056616c696461746f72507265666572656e636573706f73206465726976656420636f72726563746c792066726f6d2053656c663a3a696e74656e74696f6e7328293b206170706c795f756e7374616b652063616e206f6e6c79206661696c20696620706f732077726f6e673b2053656c663a3a696e74656e74696f6e73282920646f65736e2774206368616e67653b207165645374616b696e6720466f7263696e674e65774572615374616b696e6720426f6e64696e674475726174696f6e496e76616c696420696e6465785374616b696e672043757272656e744e6f6d696e61746f7273466f720000000000000000000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e727356616c696461746f72436f756e744d696e696d756d56616c696461746f72436f756e7453657373696f6e7350657245726153657373696f6e52657761726450657262696c6c4f66666c696e65536c6173684772616365426f6e64696e674475726174696f6e496e76756c657261626c657343757272656e7445726156616c696461746f72507265666572656e636573496e74656e74696f6e734e6f6d696e6174696e674e6f6d696e61746f7273466f7243757272656e744e6f6d696e61746f7273466f7243757272656e7453657373696f6e52657761726443757272656e744f66666c696e65536c6173684e65787453657373696f6e735065724572614c6173744572614c656e6774684368616e67655374616b6552616e6765506169724f663c42616c616e63654f663c543e3e536c617368436f756e74466f7263696e674e65774572612829526563656e746c794f66666c696e655665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d6265722c20753332293e204d6f737420726563656e742060524543454e545f4f46464c494e455f434f554e546020696e7374616e6365732e202877686f206974207761732c207768656e20697420776173207265706f727465642c20686f77206d616e7920696e7374616e63657320746865792077657265206f66666c696e6520666f72292e2057652061726520666f7263696e672061206e6577206572612e20546865206e756d626572206f662074696d6573206120676976656e2076616c696461746f7220686173206265656e207265706f72746564206f66666c696e652e205468697320676574732064656372656d656e746564206279206f6e652065616368206572612074686174207061737365732e2054686520626c6f636b20617420776869636820746865206077686f6027732066756e6473206265636f6d6520656e746972656c79206c69717569642e20546865206869676865737420616e64206c6f77657374207374616b65642076616c696461746f7220736c61736861626c652062616c616e6365732e205468652073657373696f6e20696e6465782061742077686963682074686520657261206c656e677468206c617374206368616e6765642e20546865206e6578742076616c7565206f662073657373696f6e7320706572206572612e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e742e20416c6c206e6f6d696e61746f72202d3e206e6f6d696e65652072656c6174696f6e73686970732e20416c6c20746865206163636f756e7473207769746820612064657369726520746f207374616b652e20507265666572656e636573207468617420612076616c696461746f72206861732e205468652063757272656e742065726120696e6465782e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c65206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c69736520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e20546865206c656e677468206f662074686520626f6e64696e67206475726174696f6e20696e20626c6f636b732e204e756d626572206f6620696e7374616e636573206f66206f66666c696e65207265706f727473206265666f726520736c617368696e6720626567696e7320666f722076616c696461746f72732e20536c6173682c207065722076616c696461746f7220746861742069732074616b656e20666f72207468652066697273742074696d6520746865792061726520666f756e6420746f206265206f66666c696e652e204d6178696d756d207265776172642c207065722076616c696461746f722c20746861742069732070726f7669646564207065722061636365707461626c652073657373696f6e2e20546865206c656e677468206f662061207374616b696e672065726120696e2073657373696f6e732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e2f55736572732f612f7372632f737562737472617465322f73726d6c2f7374616b696e672f7372632f6c69622e72735374616b696e672043757272656e7453657373696f6e5265776172645374616b696e67205374616b6552616e67655374616b696e67204c6173744572614c656e6774684368616e67655374616b696e672053657373696f6e735065724572615374616b696e672043757272656e744572615374616b696e67204e65787453657373696f6e735065724572615374616b696e672056616c696461746f72436f756e745374616b696e67204f66666c696e65536c6173685374616b696e672053657373696f6e526577617264000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e72730000000000000000617474656d707420746f20646976696465206279207a65726f43616e6e6f74207374616b6520696620616c7265616479206e6f6d696e6174696e672e43616e6e6f74207374616b6520696620616c7265616479207374616b65642e43616e6e6f74206e6f6d696e61746520696620616c7265616479206e6f6d696e6174696e672e43616e6e6f74206e6f6d696e61746520696620616c7265616479207374616b65642e5374616b696e67204e6f6d696e6174696e674163636f756e74206d757374206265206e6f6d696e6174696e67496e76616c69642074617267657420696e64657863616e6e6f7420756e7374616b65207768656e2074686572652061726520746f6f20666577207374616b6564207061727469636970616e7473436f756e63696c566f74696e6720436f756e63696c566f74654f6654616c6c7943616e63656c6174696f6e54616c6c795265666572656e64756d204120766f74696e672074616c6c79206861732068617070656e656420666f722061207265666572656e64756d20766f74652e204c61737420746872656520617265207965732c206e6f2c206162737461696e20636f756e74732e204120766f74696e672074616c6c79206861732068617070656e656420666f722061207265666572656e64756d2063616e63656c6c6174696f6e20766f74652e2f55736572732f612f7372632f737562737472617465322f73726d6c2f636f756e63696c2f7372632f766f74696e672e7273436f756e63696c566f74696e672050726f706f73616c73436f756e63696c566f74696e672050726f706f73616c4f66436f756e63696c566f74696e67205665746f656450726f706f73616c436f756e63696c566f74696e6720456e61637444656c6179506572696f6447757275206d656469746174696f6e7665746f7365745f636f6f6c6f66665f706572696f647365745f766f74696e675f706572696f64626c6f636b7370726f706f73616c5f68617368436f756e63696c566f74696e67436f6f6c6f6666506572696f64456e61637444656c6179506572696f645665633c28543a3a426c6f636b4e756d6265722c20543a3a48617368293e543a3a50726f706f73616c50726f706f73616c566f74657273436f756e63696c566f74654f6628543a3a486173682c20543a3a4163636f756e744964295665746f656450726f706f73616c28543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e29204e756d626572206f6620626c6f636b7320627920776869636820746f2064656c617920656e6163746d656e74206f66207375636365737366756c2c206e6f6e2d756e616e696d6f75732d636f756e63696c2d696e7374696761746564207265666572656e64756d2070726f706f73616c732e00002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e7273436f756e63696c566f74696e6720566f74696e67506572696f6470726f706f73657220776f756c64206e6f74206265206f6e20636f756e63696c70726f706f73616c206973207665746f6564436f756e63696c566f74696e672050726f706f73616c566f746572736f6e6c7920636f756e63696c6c6f7273206d617920766f7465206f6e20636f756e63696c2070726f706f73616c736120636f756e63696c6c6f72206d6179206e6f74207665746f20612070726f706f73616c2074776963656f6e6c7920636f756e63696c6c6f7273206d6179207665746f20636f756e63696c2070726f706f73616c7370726f706f73616c206d75737420657869737420746f206265207665746f6564436f756e63696c566f74696e6720436f6f6c6f6666506572696f64547265617375727920506f7454726561737572792050726f706f73616c7353756469644b65794368616e67656420546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e2f55736572732f612f7372632f737562737472617465322f73726d6c2f7375646f2f7372632f6c69622e72735370656e64696e67417761726465644275726e74526f6c6c6f766572205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e52657475726e207479706573206c656e6774682073686f756c642062652030206f7220315472656173757279205370656e64506572696f64547265617375727920417070726f76616c735472656173757279204275726e0000000000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e72735375646f4b657970726f706f73655f7370656e647365745f706f74636f6e66696775726572656a6563745f70726f706f73616c617070726f76655f70726f706f73616c20417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f6964202852652d29636f6e6669677572652074686973206d6f64756c652e70726f706f73616c5f626f6e64436f6d706163743c5065726d696c6c3e70726f706f73616c5f626f6e645f6d696e696d756d7370656e645f706572696f646275726e20536574207468652062616c616e6365206f662066756e647320617661696c61626c6520746f207370656e642e6e65775f706f742050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e62656e6566696369617279547265617375727950726f706f73616c426f6e645065726d696c6c50726f706f73616c426f6e644d696e696d756d5370656e64506572696f644275726e506f7450726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e417070726f76616c735665633c50726f706f73616c496e6465783e2050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e20546f74616c2066756e647320617661696c61626c6520746f2074686973206d6f64756c6520666f72207370656e64696e672e2050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e2050726f706f7274696f6e206f662066756e647320746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c61636520612070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f65736e27742e2f55736572732f612f7372632f737562737472617465322f73726d6c2f74726561737572792f7372632f6c69622e72735375646f204b65796f6e6c79207468652063757272656e74207375646f206b65792063616e207375646f6f6e6c79207468652063757272656e74207375646f206b65792063616e206368616e676520746865207375646f206b657954726561737572792050726f706f73616c426f6e644d696e696d756d54726561737572792050726f706f73616c426f6e6450726f706f73657227732062616c616e636520746f6f206c6f7754726561737572792050726f706f73616c436f756e744e6f2070726f706f73616c206174207468617420696e6465780000000000000000000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962616c6c6f632f7665632e727353657373696f6e20466f7263696e674e657753657373696f6e73746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c6964207479706562656e6566696369617279206163636f756e74206d757374207072652d65786973746e6f7420656e6f75676820667265652066756e64736163636f756e742068617320746f6f206665772066756e647342616c616e636573204372656174696f6e46656542616c616e636573205472616e7366657246656542616c616e63657320546f74616c49737375616e636553657373696f6e2043757272656e74496e64657853657373696f6e2053657373696f6e4c656e67746842616c616e636573204578697374656e7469616c4465706f73697453657373696f6e2056616c696461746f727342616c616e636573204672656542616c616e636542616c616e63657320526573657276656442616c616e636500617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e72734e657753657373696f6e204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e426c6f636b4e756d6265724e65774163636f756e745265617065644163636f756e74205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e20416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e2f55736572732f612f7372632f737562737472617465322f73726d6c2f73657373696f6e2f7372632f6c69622e72732f55736572732f612f7372632f737562737472617465322f73726d6c2f62616c616e6365732f7372632f6c69622e72736f766572666c6f77206d756c7469706c79696e6720676173206c696d69742062792070726963656e6f7420656e6f7567682066756e647320666f72207472616e73616374696f6e2066656553657373696f6e204c6173744c656e6774684368616e676553657373696f6e2043757272656e74537461727453657373696f6e204e65787453657373696f6e4c656e67746853657373696f6e204e6578744b6579466f72000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f7365745f6b65797365745f6c656e677468666f7263655f6e65775f73657373696f6e20466f726365732061206e65772073657373696f6e2e6170706c795f72657761726473205365742061206e65772073657373696f6e206c656e6774682e20576f6e2774206b69636b20696e20756e74696c20746865206e6578742073657373696f6e206368616e6765202861742063757272656e74206c656e677468292e6e65772053657473207468652073657373696f6e206b6579206f6620605f76616c696461746f726020746f20605f6b6579602e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e6b6579543a3a53657373696f6e4b657953657373696f6e56616c696461746f727353657373696f6e4c656e67746843757272656e74496e64657843757272656e745374617274466f7263696e674e657753657373696f6e4c6173744c656e6774684368616e67654e6578744b6579466f724e65787453657373696f6e4c656e67746820546865206e6578742073657373696f6e206c656e6774682e20546865206e657874206b657920666f72206120676976656e2076616c696461746f722e20426c6f636b206174207768696368207468652073657373696f6e206c656e677468206c617374206368616e6765642e204e65772073657373696f6e206973206265696e6720666f72636564206973207468697320656e747279206578697374733b20696e20776869636820636173652c2074686520626f6f6c65616e2076616c7565206973207768657468657220746865206e65772073657373696f6e2073686f756c6420626520636f6e736964657265642061206e6f726d616c20726f746174696f6e202872657761726461626c6529206f7220657863657074696f6e616c2028736c61736861626c65292e2054696d657374616d70207768656e2063757272656e742073657373696f6e20737461727465642e2043757272656e7420696e646578206f66207468652073657373696f6e2e2043757272656e74206c656e677468206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e7472616e736665727365745f62616c616e636520536574207468652062616c616e636573206f66206120676976656e206163636f756e742e77686f667265657265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572207374616b65722e42616c616e636573546f74616c49737375616e63654578697374656e7469616c4465706f7369745472616e736665724665654372656174696f6e46656556657374696e6756657374696e675363686564756c653c543a3a42616c616e63653e4672656542616c616e6365526573657276656442616c616e63652054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e20285468697320697320646966666572656e7420616e642077686f6c6c7920756e72656c6174656420746f207468652060426f6e64616765602073797374656d207573656420696e20746865207374616b696e67206d6f64756c652e29205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420697320616c6f6e65207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865726d6f72652c20604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e75702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e204174206c6561737420617320626967206173205265636c61696d5265626174652e205468652066656520726571756972656420746f206d616b652061207472616e736665722e20546865206d696e696d756d20616d6f756e7420616c6c6f77656420746f206b65657020616e206163636f756e74206f70656e2e2054686520746f74616c20616d6f756e74206f66207374616b65206f6e207468652073797374656d2e002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e00000000000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e727342616c616e6365732056657374696e6776657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c7565676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c756554696d657374616d702044696455706461746554696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f55736572732f612f7372632f737562737472617465322f73726d6c2f74696d657374616d702f7372632f6c69622e727363616e6e6f74207472616e7366657220696c6c69717569642066756e647354696d657374616d70204e6f7754696d657374616d7020426c6f636b506572696f6444656d6f637261637920566f74696e67506572696f6444656d6f637261637920566f74654f6644656d6f637261637920426f6e64616765496e646963657320456e756d53657444656d6f6372616379205265666572656e64756d496e666f4f6654696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b54696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c426c6f636b506572696f643e206265747765656e2073657175656e7469616c20626c6f636b73000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f6f70732f61726974682e72735461626c6564537461727465645061737365644e6f7450617373656443616e63656c6c65645265666572656e64756d496e646578566f74655468726573686f6c6450726f70496e6465785665633c4163636f756e7449643e2f55736572732f612f7372632f737562737472617465322f73726d6c2f696e64696365732f7372632f6c69622e72734e65774163636f756e74496e6465782041206e6577206163636f756e7420696e646578207761732061737369676e65642e2054686973206576656e74206973206e6f7420747269676765726564207768656e20616e206578697374696e6720696e64657820697320726561737369676e656420746f20616e6f7468657220604163636f756e744964602e4163636f756e74496e64657854696d657374616d7020746f6f2066617220696e2066757475726520746f206163636570744765747320616e64206465636f6465732074696d657374616d7020696e686572656e742064617461496e6469636573204e657874456e756d53657444656d6f6372616379204c61756e6368506572696f6444656d6f6372616379205075626c696350726f707344656d6f6372616379204465706f7369744f6644656d6f6372616379205075626c696344656c617944656d6f6372616379204e65787454616c6c7944656d6f6372616379205265666572656e64756d436f756e7444656d6f6372616379204469737061746368517565756544656d6f637261637920566f74657273466f7243616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d00000000000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000000000000617474656d707420746f2063616c63756c617465207468652072656d61696e646572207769746820612064697669736f72206f66207a65726f496e64696365734e657874456e756d536574543a3a4163636f756e74496e646578456e756d5365745665633c543a3a4163636f756e7449643e2054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e7365636f6e6473746172745f7265666572656e64756d63616e63656c5f7265666572656e64756d63616e63656c5f7175657565642043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e7768656e436f6d706163743c543a3a426c6f636b4e756d6265723e77686963682052656d6f76652061207265666572656e64756d2e7265665f696e646578436f6d706163743c5265666572656e64756d496e6465783e2053746172742061207265666572656e64756d2e426f783c543a3a50726f706f73616c3e64656c6179543a3a426c6f636b4e756d62657220566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e566f7465436f6d706163743c50726f70496e6465783e2050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e436f6d706163743c42616c616e63654f663c543e3e44656d6f63726163795075626c696350726f70436f756e745075626c696350726f70735665633c2850726f70496e6465782c20543a3a50726f706f73616c2c20543a3a4163636f756e744964293e4465706f7369744f662842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e294c61756e6368506572696f644d696e696d756d4465706f73697442616c616e63654f663c543e5075626c696344656c61794d61784c6f636b506572696f64734c6f636b506572696f6473566f74696e67506572696f645265666572656e64756d436f756e744e65787454616c6c795265666572656e64756d496e666f4f66285265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a50726f706f73616c3e29446973706174636851756575655665633c4f7074696f6e3c28543a3a50726f706f73616c2c205265666572656e64756d496e646578293e3e426f6e64616765566f74657273466f72566f74654f66285265666572656e64756d496e6465782c20543a3a4163636f756e74496429204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e2054686520626c6f636b20617420776869636820746865206077686f6027732066756e6473206265636f6d65206c69717569642e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206e657874207265666572656e64756d20696e64657820746861742073686f756c642062652074616c6c6965642e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e64756d73207374617274656420736f206661722e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20546865206d6178696d756d206e756d626572206f66206164646974696f6e616c206c6f636b20706572696f6473206120766f746572206d6179206f6666657220746f20737472656e677468656e20746865697220766f74652e204d756c7469706c6573206f6620605075626c696344656c6179602e205468652064656c6179206265666f726520656e6163746d656e7420666f7220616c6c207075626c6963207265666572656e64612e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e73657420536574207468652063757272656e742074696d652e2045787472696e736963207769746820746869732063616c6c2073686f756c6420626520706c616365642061742074686520737065636966696320706f736974696f6e20696e20746865206561636820626c6f636b2028737065636966696564206279207468652054726169743a3a54494d455354414d505f5345545f504f534954494f4e29207479706963616c6c7920617420746865207374617274206f6620746865206561636820626c6f636b2e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e74207370656369666965642062792060626c6f636b5f706572696f64602e6e6f77436f6d706163743c543a3a4d6f6d656e743e54696d657374616d704e6f77543a3a4d6f6d656e74426c6f636b506572696f6444696455706461746520446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f20546865206d696e696d756d2028616e6420616476697365642920706572696f64206265747765656e20626c6f636b732e2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e2f55736572732f612f7372632f737562737472617465322f73726d6c2f64656d6f63726163792f7372632f6c69622e727344656d6f6372616379204d696e696d756d4465706f73697476616c756520746f6f206c6f7770726f706f73657227732062616c616e636520746f6f206c6f7744656d6f6372616379205075626c696350726f70436f756e7463616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f7744656d6f6372616379204d61784c6f636b506572696f6473766f74652068617320746f6f206772656174206120737472656e677468766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e7472616e736163746f72206d75737420686176652062616c616e636520746f207369676e616c20617070726f76616c2e2f55736572732f612f7372632f737562737472617465322f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f20657865637574655f626c6f636b696e697469616c6973655f626c6f636b6170706c795f65787472696e736963696e686572656e745f65787472696e73696373636865636b5f696e686572656e747376616c69646174655f7472616e73616374696f6e6772616e6470615f70656e64696e675f6368616e67652f55736572732f612f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d636f6465632d332e302e302f7372632f636f6465632e7273626164206f726967696e3a20657870656374656420746f2062652061207468726573686f6c64206e756d626572206f6620636f756e63696c206d656d6265727350726f706f736564566f746564417070726f766564446973617070726f76656445786563757465642041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e206173207533327320726573706563746976656c79292e2041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20753332292e50726f706f73616c496e6465782f55736572732f612f7372632f737562737472617465322f73726d6c2f636f756e63696c2f7372632f6d6f74696f6e732e72730000000000000000000000000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656450726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b2071656400000000000000000000000000000000000000000070726f706f7365766f746570726f706f73616c543a3a48617368696e646578436f6d706163743c50726f706f73616c496e6465783e617070726f76657468726573686f6c64436f6d706163743c7533323e426f783c3c542061732054726169743e3a3a50726f706f73616c3e436f756e63696c4d6f74696f6e7350726f706f73616c735665633c543a3a486173683e50726f706f73616c4f663c542061732054726169743e3a3a50726f706f73616c566f74696e672850726f706f73616c496e6465782c207533322c205665633c543a3a4163636f756e7449643e2c205665633c543a3a4163636f756e7449643e2950726f706f73616c436f756e742050726f706f73616c7320736f206661722e20566f74657320666f72206120676976656e2070726f706f73616c3a202872657175697265645f7965735f766f7465732c207965735f766f746572732c206e6f5f766f74657273292e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e205468652028686173686573206f662920746865206163746976652070726f706f73616c732e436f756e63696c4d6f74696f6e732050726f706f73616c4f666475706c69636174652070726f706f73616c73206e6f7420616c6c6f77656470726f706f736572206e6f74206f6e20636f756e63696c436f756e63696c4d6f74696f6e732050726f706f73616c436f756e74436f756e63696c4d6f74696f6e732050726f706f73616c73436f756e63696c4d6f74696f6e7320566f74696e67766f746572206e6f74206f6e20636f756e63696c70726f706f73616c206d7573742065786973746d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f72656400000000000000000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e727374686520766563746f7220697320616c7761797320636c65617265643b2069742773207772697474656e206f6e6c79206f6e63652f55736572732f612f7372632f737562737472617465322f73726d6c2f636f6e74726163742f7372632f657865632e727346656573205472616e73616374696f6e4261736546656546656573205472616e73616374696f6e42797465466565466565732043757272656e745472616e73616374696f6e4665654469676573744974656d206e6f7420657175616c73797374656d6175726174696d657374616d70636f6e73656e737573696e646963657362616c616e63657373657373696f6e7374616b696e6764656d6f6372616379636f756e63696c636f756e63696c5f766f74696e67636f756e63696c5f6d6f74696f6e736772616e6470617472656173757279636f6e74726163747375646f6665657343686172676564204665652063686172676564202865787472696e7369635f696e6465782c206665655f616d6f756e7429416d6f756e745472616e73616374696f6e4261736546656541737365744f663c543e5472616e73616374696f6e4279746546656543757272656e745472616e73616374696f6e46656520546865206065787472696e7369635f696e646578203d3e20616363756d756c617465645f6665657360206d61702c20636f6e7461696e696e67207265636f72647320746f20747261636b20746865206f766572616c6c2063686172676564206665657320666f722065616368207472616e73616374696f6e2e20416c6c207265636f7264732073686f756c642062652072656d6f7665642061742066696e616c6973652073746167652e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e466565737375627374726174652d6e6f646500df6acb689907609b0100000037e397fc7c91f5e40100000040fe3ad401f8959a02000000d2bc9897eed08f1501000000ed99c5acb25eedf501000000dd718d5cc53262d40100000072656163686564206d6178696d756d2064657074682c2063616e6e6f74206372656174656e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e746961746520666565636f6e747261637420616c7265616479206578697374736e6f7420656e6f7567682067617320746f20706179207472616e736665722066656562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c2066656563616e2774206465636f6465207761736d20636f6465657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e61747572654f6e20656e74727920746f207468652066756e6374696f6e20606d6f64756c65602063616e277420626520604e6f6e65603b207165646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163656d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e76616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e7420747970654d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c65646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6563616c6c2066756e6374696f6e2069736e2774206578706f727465646465706c6f792066756e6374696f6e2069736e2774206578706f727465646578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e66756e6374696f6e206861732061206e6f6e2d6578697374656e742074797065627974657320666565206f766572666c6f776e6f2065787472696e73696320696e64657820666f756e6466656520676f74206f766572666c6f77206166746572206368617267656e6f7420616c6c6f77656420746f206661696c20696e2072756e74696d655468657265206973206f6e6c79206f6e6520666174616c206572726f723b20716564496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473214e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f72216465706c6f793a6772616e6470613a617574683a6c656e4e6577417574686f726974696573204e657720617574686f726974792073657420686173206265656e206170706c6965642e5665633c2853657373696f6e4b65792c20753634293e2f55736572732f612f7372632f737562737472617465322f73726d6c2f6772616e6470612f7372632f6c69622e72736d656d6f727976616c69646174696f6e206572726f72657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a0909090909097165642f55736572732f612f7372632f737562737472617465322f73726d6c2f636f6e74726163742f7372632f7761736d2f6d6f642e72734772616e64706146696e616c6974792050656e64696e674368616e67657265706f72745f6d69736265686176696f72205265706f727420736f6d65206d69736265686176696f75722e5f7265706f72744772616e64706146696e616c69747950656e64696e674368616e676553746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265722c20543a3a53657373696f6e4b65793e436f6e7472616374204761735370656e74436f6e7472616374204761735072696365436f6e747261637420426c6f636b4761734c696d6974616c726561647920626f72726f776564616c7265616479206d757461626c7920626f72726f7765645472616e73666572496e7374616e746961746564436f646553746f7265645363686564756c65557064617465644469737061746368656420412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e4163636f756e744964626f6f6c20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e75333220436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e4861736820436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d60202d3e2060746f60207769746820676976656e206076616c7565602061732070617274206f66206120606d6573736167652d63616c6c60206f722060637265617465602e42616c616e6365436f6e747261637420436f6465486173684f6653746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e2f55736572732f612f7372632f737562737472617465322f73726d6c2f6578656375746976652f7372632f6c69622e7273446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e45787472696e736963732073686f756c64206e6f742065786365656420626c6f636b206c696d6974416c6c2065787472696e736963732073686f756c642062652070726f7065726c79207369676e6564416c6c2065787472696e736963732073686f756c6420686176652073656e6465722061626c6520746f207061792074686569722066656573416c6c2065787472696e736963732073686f756c6420686176652074686520636f7272656374206e6f6e6365626c6f636b2073697a65206c696d697420697320726561636865645472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e696e76616c6964206163636f756e7420696e646578626164207369676e617475726520696e2065787472696e736963436f6e747261637420436f646553746f72616765636f6465206973206e6f7420666f756e64436f6e7472616374205072697374696e65436f64657072697374696e6520636f6465206973206e6f7420666f756e647570646174655f7363686564756c657075745f636f646563616c6c637265617465204372656174652061206e657720636f6e74726163742c206f7074696f6e616c6c79207472616e73666572696e6720736f6d652062616c616e636520746f207468652063726561746564206163636f756e742e204372656174696f6e20697320657865637574656420617320666f6c6c6f77733a202d207468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20746865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792063726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e79206d6573736167652072656365697665642062792074686973206163636f756e742e656e646f776d656e74436f6d706163743c543a3a42616c616e63653e6761735f6c696d6974436f6d706163743c543a3a4761733e636f64655f68617368436f6465486173683c543e646174615665633c75383e204d616b6520612063616c6c20746f206120737065636966696564206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e646573743c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f7572636576616c75652053746f72657320636f646520696e207468652073746f726167652e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e636f6465205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c653c543a3a4761733e436f6e7472616374436f6e7472616374466565543a3a42616c616e636543616c6c42617365466565543a3a4761734372656174654261736546656547617350726963654d61784465707468426c6f636b4761734c696d69744761735370656e7443757272656e745363686564756c65436f6465486173684f66543a3a4163636f756e7449645072697374696e65436f6465436f646553746f726167657761736d3a3a5072656661625761736d4d6f64756c652041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f722074686520657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e20546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f63726561746520737461636b2e20546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520666565206368617267656420666f72206120637265617465206f66206120636f6e74726163742e2054686520666565206368617267656420666f7220612063616c6c20696e746f206120636f6e74726163742e205468652066656520726571756972656420746f20637265617465206120636f6e74726163742e204174206c6561737420617320626967206173207374616b696e672773205265636c61696d5265626174652e2f55736572732f612f7372632f737562737472617465322f73726d6c2f636f6e74726163742f7372632f6c69622e7273436f6e74726163742043757272656e745363686564756c657468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f64656e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e2063757272656e74436f6e7472616374204d61784465707468436f6e747261637420436f6e7472616374466565436f6e74726163742043616c6c42617365466565436f6e747261637420437265617465426173654665655f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e6578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f6372656174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d5f736565646578745f6e6f776578745f64697370617463685f63616c6c6578745f696e7075745f73697a656578745f696e7075745f636f70796578745f736372617463685f73697a656578745f736372617463685f636f707966756e635f737461636b5f636f7374732069736e27742079657420636f6d70757465643b0a0909090944696420796f752063616c6c2060636f6d707574655f737461636b5f636f737473603f656e7667617300002f55736572732f612f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e312f7372632f6761732e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647343616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a202f55736572732f612f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e312f7372632f737461636b5f6865696768742f6d6f642e727366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a090909097165645369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e656446756e6374696f6e20617420696e64657820206973206e6f7420646566696e65647372632f6c6962616c6c6f632f7665632e7273617373657274696f6e206661696c65643a20656e64203c3d206c656e617373657274696f6e206661696c65643a20696e646578203c3d206c656e6066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e644e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e46756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64737461636b206d757374206265206e6f6e2d656d707479737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e64000000000000000000002f55736572732f612f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e312f7372632f737461636b5f6865696768742f6d61785f6865696768742e7273747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e647300002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f736c6963652f6d6f642e7273547261696c696e6744617461556e6578706563746564456f66496e76616c696444617461492f4f204572726f723a20696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f55736572732f612f7372632f737562737472617465322f636f72652f73722d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e727361757261736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214175726120696e686572656e742064617461206e6f7420666f756e6474696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e4578706c69636974207265706f7274696e67206e6f7420616c6c6f77656445787472696e7369635375636365737345787472696e7369634661696c656420416e2065787472696e736963206661696c65642e20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e48617368206e6f7420657175616c000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f55736572732f612f7372632f737562737472617465322f636f72652f73722d7072696d6974697665732f7372632f67656e657269632f6572612e7273617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a2052756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e676361706163697479206f766572666c6f777372632f6c6962616c6c6f632f7261775f7665632e72736120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f727372632f6c6962636f72652f726573756c742e727300000000002f72757374632f386165373330613434326363386166366134383761313337616539626137386638396564626261362f7372632f6c6962636f72652f666d742f6d6f642e7273010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303040404040400000000000000000000000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e6465782069732030303031303230333034303530363037303830393130313131323133313431353136313731383139323032313232323332343235323632373238323933303331333233333334333533363337333833393430343134323433343434353436343734383439353035313532353335343535353635373538353936303631363236333634363536363637363836393730373137323733373437353736373737383739383038313832383338343835383638373838383939303931393239333934393539363937393839397372632f6c6962636f72652f736c6963652f6d6f642e7273696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e67746820736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d7372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f66206000000000000000000000000000007372632f6c6962636f72652f666d742f6d6f642e72732e2e00010305050606030706080809110a1c0b190c140d120e160f0410031212130916011705180219031a071c021d011f1620032b062c022d0b2e01300331023202a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f1838586898b8c98a0a4a6a8a9acbabebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f74759697c9ff2f5f262e2fa7afb7bfc7cfd7df9a409798308f1fffceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100856070207150d500443032d03010411060f0c3a041d250d064c206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082a0682ff1118082f112d032010210f808c048297190b158894052f053b07020e180980af31740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880ba3d35040a06380846080c06740b1e035a0459098083181c0a1609460a808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b0210011104120513111402150217021a021c051d0824016a036b02bc02d102d40cd509d602d702da01e005e802ee20f004f9040c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1c848509379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a2225c5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d03f71727b5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a80a64e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b5f2148080a80a65e22450b0a060d1338080a362c041080c03c64530c0181004808531d398107460a1d03474937030e080a0639070a8136198107839a66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b65450b2f101140021e97f20e82f3a50d811f51818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b87d580d7294b050a0402831144814b3c06010455051b3402810e2c04640c560a0d035c043d391d0d2c040907020e06809a83d50b0d030a06740c59270c0438080a0628081e520c046703290d0a06030d30600e85927372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21b003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000d0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c813000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d000000000000001e1f20000000000021002200232425000000002600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027280000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000002b2c00002d0000000000000000000000000000000000000000000000000000000000002e2f300000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000000000320033000000000000000000000000000000000000000000000000000034350000353535360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff06fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db07000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75657372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f662060426f72726f774572726f72426f72726f774d75744572726f723a204572726f72004190a5c2000b80c30115001000240000002c8310001700000040020000090000009d01100022000000bf0110002c000000b500000003000000eb01100028000000bf0110002c000000bb00000003000000c7801000280000002302100031000000b8000000010000006002100019000000800210002c000000ef0000001e000000950310001e000000b30310002e0000004e0100000300000000000000e70310000c0000000100000000000000517610000c00000000000000f30310000800000000000000d8841000749610000000000000000000d884100000000000000000000100000000000000fb0310000e0000000000000000000000196f10000300000000000000000000000000000000000000d8841000b09810000000000000000000d88410000000000000000000000000000000000009041000100000000000000000000000196f10000300000000000000000000000000000000000000d8841000b09810000000000000000000d88410000000000000000000000000000000000019041000090000000100000000000000525210000e00000000000000c36010000700000000000000d88410008c9610000000000000000000d884100000000000000000000100000000000000220410000d0000000100000000000000196f100003000000000000007e7410000700000000000000d8841000649610000000000000000000d8841000000000000000000001000000000000002f0410000a0000000000000000000000c36010000700000000000000000000000000000000000000d88410008c9610000000000000000000d88410000000000000000000010000000000000039041000060000000000000000000000525210000e00000000000000000000000000000000000000d884100074961000000000000000000084961000010000000000000001000000000000003f0410000a0000000000000000000000c36010000700000000000000000000000000000000000000d88410008c9610000000000000000000d884100000000000000000000100000000000000490410000e0000000000000000000000c36010000700000000000000000000000000000000000000d88410008c9610000000000000000000d884100000000000000000000100000000000000570410000600000000000000000000005d0410000900000000000000000000000000000000000000d88410009c9610000000000000000000d884100000000000000000000100000000000000660410000600000000000000000000006c0410001a00000000000000000000000000000000000000d8841000ac9610000000000000000000d88410000000000000000000010000002500000000000000010000002600000025000000000000000100000027000000860410004200000025000000000000000100000028000000250000000000000001000000260000002500000000000000010000002600000000000000596d1000120000000000000068e1100001000000000000000000000080e11000010000000000000000000000c80410000c00000000000000c4971000010000000000000000000000dc971000010000000000000000000000d40410000600000000000000e4971000010000000000000000000000fc971000010000000000000000000000da0410000e00000000000000049810000100000000000000000000001c981000010000000000000000000000e80410000800000000000000249810000100000000000000000000003c981000010000000000000000000000f00410000b00000000000000449810000100000000000000000000005c981000010000000000000000000000f40510000700000000000000fb0510003d000000a305100051000000000000009c05100007000000000000007e74100007000000810510001b000000000000007905100005000000000000007e051000030000003a0510003f000000000000008941100003000000000000007e741000070000002805100012000000000000001605100005000000000000001b0510000d000000fb0410001b0000000000000041061000130000000000000000000000540610001200000000000000000000000000000000000000d8841000b09810000000000000000000d884100000000000000000000000000025000000000000000100000029000000c780100028000000ef8010003d0000003701000009000000de791000230000002302100031000000b800000001000000c78010002800000085061000390000005c00000008000000c006100019000000e006100048000000bb0100002d00000000000000ae0910000b00000000000000e0e21000020000000000000000000000d0991000010000000000000000000000b90910001000000000000000d0bf1000010000000000000000000000d8991000010000000000000000000000c90910000c0000000000000008e31000010000000000000000000000e0991000010000000000000000000000d50910000e00000000000000e8991000020000000000000000000000f89910000100000000000000890a1000150000007a0a10000f0000003d0a10003d000000524e10000e000000524e10000e000000e30910005a000000b00c100039000000600c100048000000100200002d000000f00b100048000000e70900000a000000400c100019000000600c100048000000bb0100002d000000f00b100048000000ed0900000e00000000000000e90c10000d00000000000000dc9b10000200000000000000000000000c9c1000020000000000000000000000f60c100013000000000000001c9c10000400000000000000000000007c9c1000050000000000000000000000090d10000d00000000000000a49c1000010000000000000000000000bc9c1000010000000000000000000000160d10001000000000000000c49c1000010000000000000000000000dc9c1000030000000000000000000000260d10000e00000000000000f49c10000300000000000000000000003c9d1000030000000000000000000000340d10001100000000000000549d10000100000000000000000000006c9d1000030000000000000000000000450d10000d00000000000000849d10000100000000000000000000009c9d1000030000000000000000000000520d10001900000000000000b49d1000010000000000000000000000cc9d10000200000000000000000000006b0d10001100000000000000b49d1000010000000000000000000000dc9d10000200000000000000000000002c1310000500000000000000311310000900000000000000ca6010000500000000000000bc10100012000000c4121000580000001c13100010000000000000009b1210000e00000000000000f56010000c00000000000000564410000300000000000000d37410002300000000000000a91210000900000000000000f56010000c00000000000000b21210001200000000000000bc101000120000007f11100058000000d71110005c0000003312100028000000d8841000000000005b1210004000000000000000ca6010000500000000000000f56010000c000000341110004b00000000000000301110000400000000000000f56010000c000000ce1010001e000000d884100000000000ec1010004400000000000000ae1010000900000000000000d37410002300000000000000b710100005000000000000001a5310001500000000000000ca6010000500000000000000bc10100012000000ce0f1000590000002710100069000000901010001e000000000000003e0e10000500000000000000f56010000c0000000e0f100059000000670f10005a000000c10f10000d00000000000000564410000300000000000000d374100023000000430e10005c0000009f0e100050000000ef0e10001f000000000000003e0e10000500000000000000d751100017000000e80d100056000000d00d1000180000007c0d100054000000d00d10001800000000000000411310000d0000000000000000000000c15310000c00000000000000000000000000000000000000d8841000dca310000000000000000000eca31000010000000000000001000000000000004e1310000a0000000000000000000000c15310000c00000000000000000000000000000000000000d8841000f4a31000000000000000000004a410000100000000000000010000000000000058131000140000000000000000000000c15310000c00000000000000000000000000000000000000d88410000ca4100000000000000000001ca41000010000000000000001000000000000006c1310000a0000000000000000000000196f10000300000000000000000000000000000000000000d884100024a41000000000000000000034a410000100000000000000010000000000000076131000140000000000000000000000525210000e00000000000000000000000000000000000000d884100064a4100000000000000000003ca41000010000000000000001000000000000008a1310001300000000000000000000009d1310000900000000000000000000000000000000000000d884100044a41000000000000000000054a4100002000000000000000100000000000000f15310000c0000000000000000000000525210000e00000000000000000000000000000000000000d884100064a4100000000000000000002cd3100001000000000000000100000000000000a61310000c0000000000000000000000525210000e00000000000000000000000000000000000000d884100074a41000000000000000000084a4100001000000000000000100000000000000b21310000c0000000000000000000000196f10000300000000000000000000000000000000000000d884100004a5100000000000000000008ca4100001000000000000000100000000000000be1310000d0000000000000000000000cb1310002300000000000000000000000000000000000000d88410002ca51000000000000000000094a4100004000000000000000100000000000000ee1310000900000000000000000000009d1310000900000000000000000000000000000000000000d884100004a510000000000000000000b4a4100001000000000000000100000000000000f71310000b0000000100000000000000517610000c00000000000000311310000900000000000000d88410002ca510000000000000000000bca4100002000000000000000100000000000000021410000e0000000100000000000000517610000c00000000000000101410001000000000000000d8841000dca410000000000000000000cca4100002000000000000000000000000000000201410000c0000000100000000000000517610000c000000000000009d1310000900000000000000d8841000dca410000000000000000000eca41000010000000000000000000000000000002c141000060000000000000000000000315110001100000000000000000000000000000000000000d88410002ca510000000000000000000f4a4100001000000000000000100000000000000321410000a0000000000000000000000315110001100000000000000000000000000000000000000d88410002ca510000000000000000000fca41000010000000000000001000000000000003c1410000e0000000000000000000000196f10000300000000000000000000000000000000000000d884100004a510000000000000000000d8841000000000000000000001000000000000004a1410000c0000000000000000000000561410002800000000000000000000000000000000000000d884100014a51000000000000000000024a51000010000000000000000000000000000007e1410001000000000000000000000008e1410001100000000000000000000000000000000000000d88410002ca5100000000000000000003ca51000010000000000000001000000000000009f1410000b0000000000000000000000aa1410002100000000000000000000000000000000000000d884100044a51000000000000000000054a510000100000000000000000000002500000000000000010000002a000000441a1000410000002500000000000000010000002b000000021a1000420000002500000000000000010000002c000000bf191000430000002500000000000000010000002d000000721910004d000000231910004f0000002500000000000000010000002e000000a7181000680000000f191000140000002500000000000000010000002f000000250000000000000001000000300000008118100026000000471810003a0000001a1710005b000000751710005c000000d11710005c0000002d1810001a000000d9161000410000006e1610005b000000c916100010000000f91510005f000000581610001600000025000000000000000100000029000000b915100040000000a115100018000000851510001c00000025000000000000000100000031000000250000000000000001000000320000003d1510004800000025000000000000000100000026000000031510003a00000025000000000000000100000032000000cb14100038000000c780100028000000851a1000310000005a00000001000000de79100023000000851a1000310000005a00000001000000000000001a1f1000060000000000000060b8100001000000000000000000000010a61000010000000000000000000000201f10000e0000000000000018a6100002000000000000000000000028a610000200000000000000000000002e1f10000c00000000000000b8bf100002000000000000000000000038a6100001000000000000001f20100038000000dc6e100009000000196f100003000000851f100055000000da1f1000450000003a1f10004b00000000000000572010000500000000000000d884100000000000000000000000000024a810000300000000000000000000005c20100007000000000000003ca8100001000000000000000000000054a810000300000000000000000000006320100008000000000000006ca81000010000000000000000000000d88410000000000000000000000000006b2010000a0000000000000084a810000100000000000000000000009ca81000020000000000000000000000752010001400000000000000aca81000020000000000000000000000dca81000030000000000000000000000892010001400000000000000fcc01000010000000000000000000000f4a810000100000000000000000000009d2010001400000000000000fcc01000010000000000000000000000fca81000010000000000000000000000b1201000130000000000000004a910000100000000000000000000001ca91000010000000000000000000000c42010000d000000000000001cc1100001000000000000000000000024a91000020000000000000000000000d1201000170000000000000004a9100001000000000000000000000034a91000010000000000000000000000e820100011000000000000003ca9100001000000000000000000000054a9100001000000000000002724100030000000d884100000000000f02310003700000000000000002310001000000000000000f56010000c000000c023100030000000d884100000000000f02310003700000000000000ba2310000600000000000000d37410002300000000000000ae2310000c00000000000000f56010000c0000003123100044000000752310003900000000000000002310001000000000000000f56010000c00000000000000102310000500000000000000152310001c0000006422100056000000d884100000000000ba221000460000003e22100026000000122210002c00000000000000894110000300000000000000f56010000c000000f2211000200000005a2110004f000000a9211000490000003621100024000000000000002c2110000a000000000000003151100011000000f9201000330000001026100048000000ed0900000e00000000000000582610000e0000000000000000000000196f10000300000000000000000000000000000000000000d884100058b11000000000000000000040b010000100000000000000010000000000000066261000150000000000000000000000196f10000300000000000000000000000000000000000000d884100048b01000000000000000000058b01000010000000000000001000000000000007b2610000e0000000000000000000000525210000e00000000000000000000000000000000000000d8841000a0b01000000000000000000060b0100001000000000000000100000000000000892610000d0000000000000000000000962610000700000000000000000000000000000000000000d884100068b01000000000000000000078b01000010000000000000001000000000000002e1f10000c0000000000000000000000962610000700000000000000000000000000000000000000d884100080b01000000000000000000090b01000010000000000000001000000000000009d261000110000000000000000000000196f10000300000000000000000000000000000000000000d884100058b11000000000000000000098b0100001000000000000000100000000000000ae2610000f0000000000000000000000525210000e00000000000000000000000000000000000000d8841000a0b010000000000000000000b0b0100001000000000000000100000000000000bd2610000c0000000000000000000000315110001100000000000000000000000000000000000000d884100088b110000000000000000000b8b0100002000000000000000100000000000000c92610000a0000000000000000000000525210000e00000000000000000000000000000000000000d884100040b110000000000000000000c8b0100001000000000000000100000000000000d3261000140000000100000000000000517610000c00000000000000152310001c00000000000000d8841000d0b010000000000000000000e0b0100001000000000000000100000000000000e72610000a0000000000000000000000315110001100000000000000000000000000000000000000d884100088b110000000000000000000e8b0100001000000000000000100000000000000f12610000a0000000100000000000000517610000c00000000000000517610000c00000000000000d884100070b110000000000000000000f0b0100001000000000000000000000000000000fb2610000d0000000100000000000000517610000c00000000000000315110001100000000000000d884100088b110000000000000000000f8b010000100000000000000010000000000000008271000140000000100000000000000517610000c00000000000000315110001100000000000000d884100088b11000000000000000000000b11000010000000000000001000000000000001c271000140000000000000000000000c15310000c00000000000000000000000000000000000000d884100008b11000000000000000000078b010000100000000000000010000000000000030271000130000000000000000000000c15310000c00000000000000000000000000000000000000d884100008b11000000000000000000090b010000100000000000000010000000000000043271000120000000000000000000000525210000e00000000000000000000000000000000000000d884100070b11000000000000000000018b110000100000000000000000000000000000055271000130000000000000000000000525210000e00000000000000000000000000000000000000d884100040b11000000000000000000020b1100001000000000000000100000000000000682710000a0000000000000000000000722710001400000000000000000000000000000000000000d884100028b11000000000000000000038b11000010000000000000001000000000000008a541000070000000100000000000000517610000c00000000000000525210000e00000000000000d884100040b11000000000000000000050b1100001000000000000000100000000000000862710000a0000000100000000000000517610000c00000000000000196f10000300000000000000d884100058b11000000000000000000068b1100001000000000000000100000000000000902710000d00000000000000000000009d2710000200000000000000000000000000000000000000d884100070b11000000000000000000080b11000010000000000000000000000000000009f2710000f0000000000000000000000ae2710002800000000000000000000000000000000000000d884100088b11000000000000000000098b110000100000000000000010000000a2d10002a00000025000000000000000100000033000000ba2c100050000000912c10002900000025000000000000000100000034000000492c10004800000025000000000000000100000035000000f52b100054000000a72b10004e0000002500000000000000010000002f000000792b10002e000000a52a1000690000000e2b10006b0000008e2a100017000000250000000000000001000000360000006c2a100022000000432a1000290000001b2a100028000000f629100025000000b5291000410000002500000000000000010000002b00000091291000240000005929100038000000250000000000000001000000370000001d2910003c00000025000000000000000100000027000000e02810003d000000250000000000000001000000310000006c2810007400000025000000000000000100000029000000522810001a00000025000000000000000100000026000000d62710007c000000c780100028000000342d10002f0000005300000001000000c02e100019000000702e100048000000bb0100002d000000302e100039000000702e100048000000100200002d0000001026100048000000e70900000a000000de79100023000000342d10002f000000530000000100000000000000f72f1000100000000000000068b2100004000000000000000000000088b21000020000000000000000000000073010000f0000000000000068b2100004000000000000000000000098b2100002000000000000004a6f100004000000196f100003000000196f100003000000196f1000030000007130100040000000493010002800000016301000330000004930100028000000c780100028000000b130100032000000210000000100000000000000b0601000070000000000000010b91000010000000000000000000000d8841000000000000000000000000000b760100004000000000000009cb31000020000000000000000000000d88410000000000000000000000000005b3110000400000000000000ccb31000010000000000000000000000d88410000000000000000000000000005f3110001200000000000000e4b31000010000000000000000000000d8841000000000000000000000000000713110001100000000000000e4b31000010000000000000000000000d8841000000000000000000000000000bb6010000800000000000000c36010000700000000000000e56010000700000000000000e56e10000400000000000000883110000d00000000000000c36010000700000000000000823110000600000000000000d75110001700000000000000a23110000d0000000000000000000000525210000e00000000000000000000000000000000000000d88410005cb610000000000000000000d884100000000000000000000100000000000000f15310000c0000000000000000000000525210000e00000000000000000000000000000000000000d88410006cb610000000000000000000d884100000000000000000000100000000000000af311000100000000000000000000000525210000e00000000000000000000000000000000000000d88410007cb6100000000000000000008cb61000010000000000000001000000000000002a611000090000000000000000000000bf3110001e00000000000000000000000000000000000000d884100094b610000000000000000000d8841000000000000000000001000000000000003f6110000a0000000100000000000000c36010000700000000000000dd3110000b00000000000000d8841000a4b610000000000000000000d884100000000000000000000000000000000000e83110000e0000000100000000000000c36010000700000000000000315110001100000000000000d884100094b610000000000000000000d884100000000000000000000100000000000000f63110000d0000000100000000000000033210001700000000000000e56e10000400000000000000d8841000a4b610000000000000000000d8841000000000000000000000000000000000001a3210000e0000000100000000000000c36010000700000000000000283210002300000000000000d8841000b4b610000000000000000000d88410000000000000000000000000002500000000000000010000002f00000025000000000000000100000038000000250000000000000001000000270000004b32100073000000250000000000000001000000260000002500000000000000010000002900000025000000000000000100000032000000c032100048000000e70900000a000000de79100023000000b1301000320000002100000001000000000000004c341000050000000000000044b710000100000000000000000000004cb71000010000000000000000000000513410000a00000000000000d0bf100001000000000000000000000054b710000100000000000000e56e10000400000097341000180000005b3410003c000000c780100028000000af3410002c000000230000000100000000000000335e1000080000000000000050b8100001000000000000000000000058b81000010000000000000000000000db341000080000000000000060b8100001000000000000000000000068b81000010000000000000000000000e3341000070000000000000070b8100003000000000000000000000088b81000010000000000000000000000ea341000050000000000000060b8100001000000000000000000000090b81000010000000000000000000000ef341000080000000000000060b8100001000000000000000000000098b810000100000000000000da5f10000d000000c03510000e000000e26f100007000000863510003a000000da5f10000d000000e26f100007000000dc6e10000900000066351000200000004335100023000000f73410004c00000030361000390000007036100048000000100200002d00000000000000d6641000040000000000000010b91000010000000000000000000000d8841000000000000000000000000000e9401000070000000000000028b91000010000000000000000000000d8841000000000000000000000000000bb60100008000000000000003d5210001000000000000000894110000300000000000000d37410002300000000000000bc361000030000000000000000000000517610000c00000000000000000000000000000000000000d88410008cb910000000000000000000d88410000000000000000000010000002500000000000000010000002800000000000000bf3610000d0000000000000078ba1000020000000000000000000000a8ba1000030000000000000000000000cc3610000700000000000000c0ba1000010000000000000000000000d8ba1000010000000000000000000000d33610000900000000000000e0ba100004000000000000000000000040bb1000010000000000000000000000dc3610000f0000000000000048bb100001000000000000000000000060bb1000010000000000000000000000eb361000100000000000000048bb100001000000000000000000000068bb1000020000000000000000000000f674100005000000000000001a5310001500000000000000063910000b00000000000000d374100023000000593810004b000000a43810004d000000f138100015000000000000005238100007000000000000001a53100015000000253810002d00000000000000e33710000d00000000000000f037100010000000000000000038100015000000000000001a5310001500000000000000153810000c00000000000000d75110001700000000000000213810000400000000000000f037100010000000c73710001c00000000000000bc3710000b00000000000000cf601000160000007d3710003f000000fb36100057000000523710002b00000000000000193910000c0000000000000000000000253910000700000000000000000000000000000000000000d884100028be10000000000000000000d8bd1000020000000000000001000000000000002c391000130000000000000000000000c15310000c00000000000000000000000000000000000000d884100010be10000000000000000000e8bd1000010000000000000001000000000000003f3910000b0000000000000000000000525210000e00000000000000000000000000000000000000d8841000f0bd1000000000000000000000be1000010000000000000001000000000000004a391000040000000000000000000000253910000700000000000000000000000000000000000000d884100028be1000000000000000000008be1000010000000000000001000000000000004e391000030000000000000000000000c15310000c00000000000000000000000000000000000000d884100010be1000000000000000000020be1000010000000000000001000000000000009f6110000d0000000000000000000000da5f10000d00000000000000000000000000000000000000d884100028be1000000000000000000038be1000010000000000000001000000000000002a611000090000000100000000000000da5f10000d00000000000000513910002400000000000000d884100040be1000000000000000000050be100001000000000000000000000000000000753910000900000000000000000000007e3910001200000000000000000000000000000000000000d884100058be1000000000000000000068be1000010000000000000001000000013b100054000000553b100037000000af3a100052000000250000000000000001000000390000008d3a100022000000493a1000440000002500000000000000010000002b000000163a10003300000025000000000000000100000031000000ed3910002900000025000000000000000100000029000000ce3910001f00000025000000000000000100000026000000903910003e000000c7801000280000008c3b1000300000003700000001000000de79100023000000af3410002c0000002300000001000000de791000230000008c3b1000300000003700000001000000a03c1000430000006e0a000025000000a03c100043000000740a00002c000000403e100019000000603e100048000000bb0100002d00000000000000a83e10000a000000000000001cbf100001000000000000000000000024bf10000200000000000000293f10000b000000b23e100055000000073f10002200000000000000343f10000a00000000000000b8bf1000020000000000000000000000c8bf10000100000000000000000000003e3f10000d00000000000000d0bf1000010000000000000000000000d8bf10000100000000000000000000003a6e10000800000000000000e0bf100004000000000000000000000000c010000100000000000000dc6e100009000000e26f1000070000008e3f10001b000000dc6e100009000000773f100017000000dc6e100009000000dc6e100009000000e26f100007000000e26f1000070000004b3f10002c000000c780100028000000a93f10002f0000003b00000001000000c780100028000000d83f100030000000a800000001000000b040100039000000603e100048000000100200002d00000000000000e94010000700000000000000d4c01000010000000000000000000000ecc01000020000000000000000000000f04010000a00000000000000fcc0100001000000000000000000000014c11000010000000000000000000000fa40100011000000000000001cc1100001000000000000000000000034c11000010000000000000000000000ed4110000300000000000000f04110000d0000008c41100058000000e44110000900000000000000894110000300000000000000d7511000170000002e4110005b00000000000000214110000d00000000000000e56e1000040000000b4110001600000000000000044210000a0000000000000000000000315110001100000000000000000000000000000000000000d88410009cc310000000000000000000acc31000010000000000000001000000000000000e4210000d0000000000000000000000525210000e00000000000000000000000000000000000000d8841000b4c310000000000000000000c4c31000010000000000000001000000000000001b4210000c0000000000000000000000525210000e00000000000000000000000000000000000000d8841000d4c310000000000000000000ccc3100001000000000000000100000000000000274210000c0000000000000000000000ec5a10000900000000000000000000000000000000000000d8841000d4c310000000000000000000e4c310000100000000000000010000000000000033421000110000000000000000000000e56e10000400000000000000000000000000000000000000d884100028c710000000000000000000ecc310000200000000000000000000000000000044421000100000000000000000000000525210000e00000000000000000000000000000000000000d884100028c710000000000000000000fcc3100001000000000000000000000000000000544210000a0000000100000000000000517610000c00000000000000f04110000d00000000000000d884100028c71000000000000000000004c41000010000000000000000000000000000005e421000110000000000000000000000525210000e00000000000000000000000000000000000000d884100028c7100000000000000000000cc4100001000000000000000000000025000000000000000100000026000000ff4310001f0000002500000000000000010000002f000000e04310001f000000c24310001e000000250000000000000001000000270000009a43100028000000dc4210005e0000003a43100060000000ac4210003000000088421000240000006f42100019000000000000001e44100008000000000000006cc410000200000000000000000000009cc41000010000000000000000000000264410000b00000000000000a4c41000030000000000000000000000ecc41000010000000000000000000000cf7410000400000000000000d37410002300000000000000f674100005000000000000003b74100013000000654410003500000000000000564410000300000000000000d374100023000000000000005944100004000000000000003b74100013000000000000005d44100008000000000000003b74100013000000314410002500000000000000a24410000d0000000000000000000000eb7510000a00000000000000000000000000000000000000d884100098c71000000000000000000008c7100001000000000000000100000000000000af441000120000000000000000000000eb7510000a00000000000000000000000000000000000000d884100098c71000000000000000000010c7100001000000000000000100000000000000c14410000b0000000000000000000000eb7510000a00000000000000000000000000000000000000d884100098c71000000000000000000018c7100001000000000000000100000000000000cc4410000b0000000000000000000000eb7510000a00000000000000000000000000000000000000d884100098c71000000000000000000020c7100001000000000000000100000000000000d7441000070000000100000000000000517610000c00000000000000de4410001b00000000000000d884100028c71000000000000000000038c7100001000000000000000000000000000000f94410000b0000000100000000000000517610000c00000000000000eb7510000a00000000000000d884100098c71000000000000000000040c710000b000000000000000100000000000000044510000f0000000100000000000000517610000c00000000000000eb7510000a00000000000000d884100098c710000000000000000000a8c710000c0000000000000001000000c64a100029000000924a1000340000006d4a100025000000244a10004900000025000000000000000100000029000000ee49100036000000ba47100027000000d884100000000000e147100053000000344810005a0000008e48100055000000e34810004f00000032491000500000008249100015000000d884100000000000974910005700000075471000450000002500000000000000010000002b000000134510005d0000007045100027000000d884100000000000974510005b000000f24510005c0000004e4610004a000000d884100000000000984610005d000000f54610002d000000d88410000000000022471000530000007547100045000000604b100048000000b001000023000000604b100048000000b101000023000000394b10001c000000d285100018000000e40300000d000000f04a100049000000870200001d000000f04a1000490000009d0000003a000000f04a100049000000a400000030000000de79100023000000a93f10002f0000003b00000001000000de79100023000000d83f100030000000a800000001000000194c10002b000000444c100031000000b400000004000000154d100030000000444c100031000000a800000004000000454d10004c000000444c100031000000a900000004000000a04d100019000000c04d100048000000bb0100002d00000000000000335e1000080000000000000034ca1000020000000000000000000000d8841000000000000000000000000000084e1000060000000000000044ca1000030000000000000000000000d88410000000000000000000000000000e4e100007000000000000005cca1000020000000000000000000000d8841000000000000000000000000000154e100006000000000000006cca1000010000000000000000000000d88410000000000000000000000000001b4e100009000000000000006cca1000010000000000000000000000d8841000000000000000000000000000244e100009000000000000006cca1000010000000000000000000000d8841000000000000000000000000000535e1000080000000000000074ca1000020000000000000000000000d88410000000000000000000494e100009000000e26f100007000000494e100009000000e26f100007000000524e10000e0000002d4e10000f0000003c4e10000d0000002d4e10000f0000002d4e10000f000000e56e100004000000c780100028000000604e10002f0000004800000001000000000000008f4e10000f00000000000000c8ca1000020000000000000000000000d8ca10000400000000000000dc6e100009000000194f10000c0000009e4e100022000000d884100000000000c04e100041000000014f100018000000c780100028000000444c1000310000009c00000001000000de79100023000000604e10002f0000004800000001000000de79100023000000444c1000310000009c00000001000000d050100039000000c04d100048000000100200002d0000008050100048000000ed0900000e00000000000000105110000b00000000000000000000001b5110000f00000000000000000000000000000000000000d88410003cd31000000000000000000000cc1000010000000000000001000000000000002a5110000700000001000000000000001b5110000f00000000000000315110001100000000000000d88410008cd31000000000000000000008cc1000010000000000000001000000585110001f000000425110001600000000000000b0601000070000000000000018cd100002000000000000000000000048cd100001000000000000000000000077511000060000000000000050cd100001000000000000000000000048cd1000010000000000000000000000b7601000040000000000000068cd100002000000000000000000000098cd10000200000000000000000000007d5110001000000000000000a8cd1000030000000000000000000000f0cd10000100000000000000000000008d5110001100000000000000f8cd100001000000000000000000000010ce10000100000000000000000000009e5110000d0000000000000018ce100002000000000000000000000048ce1000010000000000000000000000bb60100008000000000000003d5210001000000000000000f674100005000000000000001a53100015000000f25210002800000000000000bb6010000800000000000000e05210001200000000000000085210000900000000000000115210001800000000000000b76010000400000000000000dc52100004000000605210004d000000ad5210002f00000000000000bb60100008000000000000003d5210001000000000000000ec60100009000000000000003c4e10000d000000000000004d5210000500000000000000525210000e0000002952100014000000000000000852100009000000000000001152100018000000f35110001500000000000000d35110000400000000000000d75110001700000000000000ee5110000500000000000000f56010000c000000ab5110002800000000000000385310000f0000000000000000000000494e10000900000000000000000000000000000000000000d88410003cd310000000000000000000c4d2100001000000000000000100000000000000475310000b0000000000000000000000525310002b00000000000000000000000000000000000000d88410008cd310000000000000000000ccd21000010000000000000001000000000000007d531000090000000100000000000000494e10000900000000000000865310002100000000000000d8841000d4d210000000000000000000e4d2100001000000000000000000000000000000a75310000c0000000000000000000000525210000e00000000000000000000000000000000000000d88410001cd310000000000000000000ecd2100001000000000000000100000000000000b35310000e0000000000000000000000c15310000c00000000000000000000000000000000000000d8841000f4d21000000000000000000004d3100001000000000000000100000000000000cd5310000b0000000000000000000000525210000e00000000000000000000000000000000000000d884100024d5100000000000000000000cd3100001000000000000000100000000000000d85310000e0000000000000000000000e65310000b00000000000000000000000000000000000000d884100054d51000000000000000000014d3100001000000000000000100000000000000f15310000c0000000000000000000000525210000e00000000000000000000000000000000000000d88410001cd3100000000000000000002cd3100001000000000000000100000000000000fd5310000f00000000000000000000002d4e10000f00000000000000000000000000000000000000d88410003cd31000000000000000000034d31000010000000000000001000000000000000c5410000900000000000000000000002d4e10000f00000000000000000000000000000000000000d88410003cd3100000000000000000004cd3100001000000000000000100000000000000155410001000000001000000000000002d4e10000f00000000000000255410002d00000000000000d884100054d31000000000000000000064d3100001000000000000000000000000000000525410000d0000000100000000000000525210000e000000000000005f5410002b00000000000000d88410006cd3100000000000000000007cd31000010000000000000001000000000000008a541000070000000100000000000000517610000c00000000000000525210000e00000000000000d884100024d51000000000000000000084d3100001000000000000000100000000000000915410000900000001000000000000002d4e10000f00000000000000315110001100000000000000d88410008cd3100000000000000000009cd31000010000000000000001000000000000009a541000060000000100000000000000a05410001f00000000000000dc5210000400000000000000d884100054d510000000000000000000a4d31000030000000000000001000000d85810003d000000b8581000200000002500000000000000010000003200000097581000210000005e581000390000002500000000000000010000002b000000115810004d000000dc5710003500000066571000760000002500000000000000010000002f000000385710002e000000ea5610004e00000025000000000000000100000031000000b856100032000000250000000000000001000000290000008b5610002d000000250000000000000001000000260000005b56100030000000275610003400000025000000000000000100000026000000fe55100029000000bf541000750000003455100072000000a65510005800000000000000155910000300000000000000e8d3100001000000000000000000000000d41000080000000000000000000000cb5a10000300000000000000ce5a1000120000001859100016000000d8841000000000002e59100055000000835910005b000000de5910005d0000003b5a10002f000000d8841000000000006a5a10006100000000000000e95a1000030000000000000000000000ec5a10000900000000000000000000000000000000000000d884100024d51000000000000000000034d5100001000000000000000100000000000000f55a10000b0000000000000000000000ec5a10000900000000000000000000000000000000000000d88410003cd5100000000000000000004cd5100001000000000000000100000000000000005b1000090000000000000000000000e56e10000400000000000000000000000000000000000000d884100054d51000000000000000000064d5100001000000000000000100000025000000000000000100000027000000675b10002400000025000000000000000100000030000000365b10003100000025000000000000000100000029000000095b10002d000000c7801000280000008b5b1000310000004e00000001000000de791000230000008b5b1000310000004e00000001000000235d10000d000000085d10001b000000d95c10002f000000ef00000001000000305d100010000000405d10000f0000004f5d100013000000625d10000f000000715d100014000000855d10001600000000000000335e10000800000000000000c8d61000040000000000000000000000e8d610000100000000000000000000003b5e10000500000000000000f0d6100005000000000000000000000018d71000020000000000000000000000405e10000800000000000000f8e2100001000000000000000000000028d71000010000000000000000000000485e10000b00000000000000f8e2100001000000000000000000000030d71000010000000000000000000000535e1000080000000000000038d7100002000000000000000000000048d710000100000000000000dc6e100009000000da5f10000d0000004a6f100004000000196f100003000000815f100059000000dc6e1000090000004a6f100004000000e56e100004000000196f100003000000196f100003000000025f100042000000445f10003d000000d15e1000310000009c5e1000350000004a6f100004000000e56e1000040000005b5e100041000000c780100028000000e75f100033000000430000000100000065601000360000009b5d1000580000004e01000005000000286010003d0000009b5d100058000000550100000500000065601000360000009b5d10005800000069010000050000009b5d100058000000700100000500000000000000b0601000070000000000000018d81000020000000000000000000000d8841000000000000000000000000000b7601000040000000000000048d81000030000000000000000000000d8841000000000000000000000000000ec6010000900000000000000f56010000c00000000000000bb6010000800000000000000016110001b00000000000000bb6010000800000000000000c36010000700000000000000ca6010000500000000000000cf6010001600000000000000e56010000700000000000000e56e100004000000000000002a611000090000000000000000000000336110000c00000000000000000000000000000000000000d8841000c0d910000000000000000000d0d91000010000000000000001000000000000003f6110000a0000000100000000000000c36010000700000000000000496110001600000000000000d8841000e0d910000000000000000000d8d91000010000000000000000000000000000005f611000060000000100000000000000c36010000700000000000000656110003a00000000000000d8841000e0d910000000000000000000f0d91000010000000000000000000000000000009f6110000d0000000000000000000000196f10000300000000000000000000000000000000000000d8841000f8d91000000000000000000008da1000010000000000000001000000250000000000000001000000260000003a62100026000000076210003300000025000000000000000100000029000000be6110004900000025000000000000000100000031000000ac61100012000000de79100023000000e75f10003300000043000000010000005063100048000000ed0900000e0000009863100034000000cc6310003100000096000000030000002500000000000000010000003a0000003b0000003c0000003d000000000000005964100006000000000000003e00000000000000000000003f00000000000000000000000200000000000000000000000000000000000000400000000000000000000000000000005f64100004000000000000004100000000000000020000000000000000000000000000000200000000000000000000000000000002000000000000000000000000000000000000006364100009000000000000004200000000000000000000004300000000000000000000000000000044000000000000000000000002000000000000000000000000000000000000006c6410000900000000000000450000000000000000000000460000000000000000000000000000004700000000000000000000000200000000000000000000000000000000000000756410000700000000000000480000000000000000000000490000000000000000000000000000004a0000000000000000000000000000004b0000000000000000000000000000007c64100008000000000000004c00000000000000000000004d0000000000000000000000000000004e0000000000000000000000000000004f0000000000000000000000000000008464100007000000000000005000000000000000000000005100000000000000000000000000000052000000000000000000000000000000530000000000000000000000000000008b6410000700000000000000540000000000000000000000550000000000000000000000000000005600000000000000000000000000000057000000000000000000000000000000926410000900000000000000580000000000000000000000590000000000000000000000000000005a0000000000000000000000000000005b0000000000000000000000000000009b64100007000000000000005c00000000000000000000005d0000000000000000000000000000005e0000000000000000000000000000005f000000000000000000000000000000a26410000e00000000000000600000000000000000000000610000000000000000000000000000006200000000000000000000000000000063000000000000000000000000000000b06410000f00000000000000640000000000000000000000650000000000000000000000000000006600000000000000000000000000000067000000000000000000000000000000bf6410000700000000000000680000000000000000000000690000000000000000000000000000006a0000000000000000000000000000006b000000000000000000000000000000c664100008000000000000006c00000000000000000000006d0000000000000000000000000000006e0000000000000000000000000000006f000000000000000000000000000000ce6410000800000000000000700000000000000000000000710000000000000000000000000000007200000000000000000000000000000073000000000000000000000000000000d66410000400000000000000740000000000000000000000750000000000000000000000000000007600000000000000000000000000000077000000000000000000000000000000da641000040000000000000078000000000000000000000079000000000000000000000002000000000000000000000000000000000000007a000000000000000000000000000000de641000070000000000000060df100002000000000000000000000070df10000100000000000000196f1000030000000f65100006000000e56410002a0000000000000015651000120000000000000000000000276510000a00000000000000000000000000000000000000d88410006ce0100000000000000000005ce010000100000000000000010000000000000031651000120000000000000000000000276510000a00000000000000000000000000000000000000d88410006ce01000000000000000000064e010000100000000000000010000000000000043651000150000000100000000000000196f10000300000000000000276510000a00000000000000d88410006ce0100000000000000000007ce01000040000000000000001000000466610003700000003661000430000002500000000000000010000002b00000058651000450000009d65100035000000d884100000000000d2651000310000007b00000018000000040000007c0000007d0000007e0000007f00000000000000fe6b10000e00000000000000e4e01000010000000000000000000000ece010000100000000000000306c1000160000000c6c100024000000c780100028000000466c10002f0000009d00000001000000de79100023000000466c10002f0000009d000000010000008b6c10007c000000076d1000350000007a0000000600000000000000596d1000120000000000000068e1100001000000000000000000000080e11000010000000000000000000000856d100007000000000000007e741000070000006b6d10001a000000000000009b6d10000d0000000000000000000000a86d10003200000000000000000000000000000000000000d8841000d4e110000000000000000000d884100000000000000000000000000025000000000000000100000029000000000000003a6e10000800000000000000c0e21000030000000000000000000000d8e21000010000000000000000000000426e10000c00000000000000e0e21000020000000000000000000000f0e210000100000000000000000000004e6e10000a00000000000000f8e2100001000000000000000000000000e31000010000000000000000000000586e10000f0000000000000008e3100001000000000000000000000010e31000010000000000000000000000676e10000a0000000000000018e3100002000000000000000000000028e310000200000000000000dc6e100009000000dc6e100009000000e26f100007000000856f10005d000000dc6e100009000000dc6e1000090000004e6f1000370000004a6f1000040000001c6f10002e000000196f100003000000e96e100030000000dc6e100009000000e56e100004000000716e10004e000000bf6e10001d000000a17110001c000000247010003100000051000000030000007d7110002400000024701000310000005900000003000000367110002c0000002470100031000000930000004c000000fe701000380000002470100031000000910000002a000000d67010002800000024701000310000009200000032000000ae701000280000002470100031000000940000002c0000007c701000320000002470100031000000c80000000300000055701000270000002470100031000000d000000004000000fc6f1000280000002470100031000000d60000000300000000000000407210000f00000000000000c0e41000010000000000000000000000d8e410000300000000000000000000004f7210000800000000000000f0e4100002000000000000000000000020e5100001000000000000000000000057721000040000000000000028e5100004000000000000000000000088e510000100000000000000000000005b721000060000000000000090e51000040000000000000000000000f0e51000090000000000000000000000c07510000800000000000000c875100010000000507510002d000000d8841000000000007d75100043000000000000004e7410000900000000000000577410000f000000000000004c75100004000000000000007e74100007000000fb7410005100000000000000cf7410000400000000000000d37410002300000000000000f674100005000000000000003b74100013000000000000004e7410000900000000000000577410000f000000000000007a74100004000000000000007e74100007000000857410004a000000000000003274100009000000000000003b74100013000000000000004e7410000900000000000000577410000f000000000000006674100009000000000000006f7410000b000000000000007a74100004000000000000007e741000070000006172100053000000d884100000000000b472100021000000d884100000000000d572100050000000257310002e000000537310005b000000ae73100057000000057410002d00000000000000e07510000b0000000000000000000000eb7510000a00000000000000000000000000000000000000d88410007ce9100000000000000000008ce9100001000000000000000100000000000000f57510000b0000000000000000000000007610000600000000000000000000000000000000000000d884100094e910000000000000000000a4e9100001000000000000000100000000000000067610000d0000000000000000000000007610000600000000000000000000000000000000000000d8841000ace910000000000000000000bce910000100000000000000010000000000000013761000080000000000000000000000eb7510000a00000000000000000000000000000000000000d8841000c4e910000000000000000000d4e91000010000000000000001000000000000001b761000080000000000000000000000196f10000300000000000000000000000000000000000000d8841000dce910000000000000000000ece9100001000000000000000100000000000000237610000d0000000000000000000000007610000600000000000000000000000000000000000000d8841000f4e91000000000000000000004ea10000100000000000000010000000000000030761000080000000000000000000000007610000600000000000000000000000000000000000000d88410000cea100000000000000000001cea100001000000000000000100000000000000387610000f0000000000000000000000c87510001000000000000000000000000000000000000000d884100024ea1000000000000000000034ea100001000000000000000100000000000000477610000a0000000100000000000000517610000c000000000000006f7410000b00000000000000d88410004cea100000000000000000003cea1000010000000000000000000000000000005d7610000c00000001000000000000006f7410000b000000000000007e7410000700000000000000d88410004cea1000000000000000000044ea100001000000000000000000000000000000697610000b00000001000000000000006f7410000b00000000000000747610001600000000000000d88410004cea100000000000000000005cea100001000000000000000000000025000000000000000100000080000000937810005300000025000000000000000100000081000000677810002c000000250000000000000001000000820000003b7810002c0000002500000000000000010000002c0000001d7810001e00000025000000000000000100000083000000eb7710003200000025000000000000000100000084000000af7710003c000000250000000000000001000000270000008f77100020000000250000000000000001000000850000006a77100025000000407710002a000000e776100059000000250000000000000001000000290000008a7610005d000000c780100028000000e6781000300000009600000001000000de79100023000000e6781000300000009600000001000000407b1000550000008800000016000000307c10006200000023010000170000000b7c1000250000005e7d100012000000707d10000f000000317d10000a0000003b7d1000140000004f7d10000f000000927d10001c0000007f7d1000130000007704000009000000ae7d10001e0000007f7d1000130000006e03000009000000817e100012000000937e10000c000000807f100069000000c8000000110000005080100048000000e70900000a000000bc8010000b000000c780100028000000ef8010003d0000008700000009000000c780100028000000ef8010003d000000900000000900000000000000f08110001000000000000000d8841000000000000000000000000000d4eb1000010000000000000000000000008210000f00000000000000d8841000000000000000000000000000dceb1000010000000000000024821000250000000f821000150000006082100019000000808210003d0000005500000022000000bd8210002d000000ea8210000c000000f6821000030000001b831000110000002c83100017000000ea0200000500000090831000460000006301000013000000860000000400000004000000870000008800000089000000d88410000000000089921000020000007683100015000000e503000005000000d884100020000000f8841000120000002500000000000000010000008a000000ea85100006000000f085100022000000d28510001800000069090000050000001286100016000000288610000d000000d2851000180000006f09000005000000538610000b0000005a9210001600000035861000010000003d86100016000000ea07000009000000389210000e00000046921000040000004a9210001000000035861000010000003d86100016000000ee07000005000000f89110002b00000023921000150000005901000015000000538610000b0000005e8610002600000084861000080000008c8610000600000035861000010000003d86100016000000fb07000005000000d884100000000000b686100002000000a0861000160000003f04000011000000a086100016000000330400002800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20f08b10004a000000408e100000020000409010003700000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b0200010202020203020202020402050602020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202070202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202d08b1000200000002700000019000000d08b1000200000002800000020000000d08b1000200000002a00000019000000d08b1000200000002b00000018000000d08b1000200000002c00000020000000d88410000000000023921000150000000e0400000500000000b5fe01046e616d6501acfe019d0300146578745f6765745f73746f726167655f696e746f010c6578745f74776f785f31323802116578745f636c6561725f73746f72616765030f6578745f7365745f73746f72616765040e6578745f7072696e745f75746638050e6578745f626c616b65325f32353606126578745f656432353531395f76657269667907106578745f73746f726167655f726f6f7408186578745f73746f726167655f6368616e6765735f726f6f7409166578745f73616e64626f785f6d656d6f72795f6765740a166578745f73616e64626f785f6d656d6f72795f7365740b1b6578745f73616e64626f785f6d656d6f72795f74656172646f776e0c126578745f6578697374735f73746f726167650d106578745f636c6561725f7072656669780e0d6578745f7072696e745f6865780f166578745f73616e64626f785f6d656d6f72795f6e657710176578745f73616e64626f785f696e7374616e746961746511126578745f73616e64626f785f696e766f6b65121d6578745f73616e64626f785f696e7374616e63655f74656172646f776e13236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74140d6578745f7072696e745f6e756d150a6578745f6d616c6c6f6316086578745f6672656517683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6835383032626362613431643031636466186b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864623365663664303937646130313135190e5f5f727573745f6465616c6c6f631a0e5f5f727573745f7265616c6c6f631b0c5f5f727573745f616c6c6f631c08727573745f6f6f6d1d34616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68643139346663353733636462343236331e7e3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c20543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68346261333764666133306635343336641f6f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6830646261326232323438326233353932206f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6830356538326634356533616231396332216c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6832396332383763346463633239396538226f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a683135356439656338343464373838306423443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68633066346339336637333036626631312425616c6c6f633a3a666d743a3a666f726d61743a3a6833383261633037633166326434353161256f3c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b54797065206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a686461663565336137326665303764363126793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68376232623132316532393561646639322736636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a68363035313233613134373566313662332834636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68633165393164666364386439633131362929636f72653a3a70616e69636b696e673a3a70616e69633a3a68386164356338393439343465376462652a6b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68373837373062616630656639323131342b4b3c616c6c6f633a3a7261775f7665633a3a5261775665633c542c20413e3e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303037336263316262373130653465392c3273725f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a68623661653734316462386334643261352d5d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68623938313664613165323832343138652ea7017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f4445434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a68666530343832386338323064316636652faa017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f454e434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a6830643963316339356434313639613839302e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a68656636346636633237326230646362373186017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a68666131363731313836333937393163393227636f72653a3a7374723a3a66726f6d5f757466383a3a6863376466333836666362633130643339334473726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a53746f726167655665633a3a6974656d3a3a686537386132303730336139373136643034463c753332206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683338306431353132623735333939613735b8013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f6d6f7274616c5f636f6d706163745f65787472696e7369633a3a556e636865636b65644d6f7274616c436f6d7061637445787472696e7369633c416464726573732c20496e6465782c2043616c6c2c205369676e61747572653e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686138313935343166626363643063383736733c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6861343738636235663432393263356264375d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862356662663134333966643762356434384e3c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862323637303335313565373530636635397f3c284b2c204c2c204d2c204e2c204f2c20502c20512c20522c20532c20542c20552c20562c20572c20582c20592c205a292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c6973653c4e756d6265723e3e3a3a6f6e5f66696e616c6973653a3a68643863333337643532313831326535393a4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383938633736396431313834623635333b4a3c5b75383b205f5d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68333731346130373634396634383037393c383c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6465706f7369745f6c6f673a3a68313634616430666435366464356535323d3a3c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6465706f7369745f6576656e743a3a68333932373663333439353465656338383e523c28522c2053292061732073726d6c5f73657373696f6e3a3a4f6e53657373696f6e4368616e67653c543e3e3a3a6f6e5f73657373696f6e5f6368616e67653a3a68383339363138623139393538333238373f493c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a736176655f6f726967696e616c5f617574686f7269746965733a3a6861323266363332363335653431306637404e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6836656662353032363233346164356534413a3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a6465706f7369745f6f663a3a6834336635643238306430643734303763423d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68373766343966656136636362313630344333636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68613764623366303238343235333561392e3333443f3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a72657365727665645f62616c616e63653a3a6832316537323538356534323936393965453b3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a667265655f62616c616e63653a3a6834326162396536316532393330313565463f3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f667265655f62616c616e63653a3a683261353634623231383638323731383747433c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f72657365727665645f62616c616e63653a3a686338653137303230386237616236656148413c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a696e6a6563745f7265666572656e64756d3a3a6834303663323961343039303235303662493f3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a7265666572656e64756d5f696e666f3a3a68326230363763623338333362393365384a36636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68303635373534343366303865386664374b8d013c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c6973653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c6973653a3a68333835653564396162333433653064614ca2013c73726d6c5f64656d6f63726163793a3a566f74657273466f723c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167654d61703c7533322c20616c6c6f633a3a7665633a3a5665633c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3a3a6765743a3a68373365323262393237616532336136394d6a636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653c413e20666f7220266d757420463e3a3a63616c6c5f6f6e63653a3a68373035633338623163383131623736664e403c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a636c6561725f7265666572656e64756d3a3a68326234636139393632356531373734364fe8013c73726d6c5f64656d6f63726163793a3a446973706174636851756575653c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265722c20616c6c6f633a3a7665633a3a5665633c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c283c542061732073726d6c5f64656d6f63726163793a3a54726169743e3a3a50726f706f73616c2c20753332293e3e3e3e3a3a6765743a3a686537373438346562636462303361363550593c6e6f64655f72756e74696d653a3a43616c6c2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6865666331656130356332343138346637513d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6835633465316665623565306561623430524e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6835613463366333623232633238656136534e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6863316364396233396166623131626535543d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6836393232666630313736616433373463554e3c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832616666363230656661613731656237564e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6835353534646630623663383934353936576c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a686137326231646661363834666238313658383c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a70726f706f73616c733a3a683931626330646661613565653233333859483c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a7365745f667265655f62616c616e63655f6372656174696e673a3a68623330323366303261663035376462305a4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68663038333466393166366164326536635b3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68626432306262313136383963623937335c4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68326262396365366138396561333964355d673c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c27612c207533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68306235353366353631663761666538395e4d3c6e6f64655f72756e74696d653a3a4c6f67206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a68623662306463656335346538643736365fc5013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f6d6f7274616c5f636f6d706163745f65787472696e7369633a3a556e636865636b65644d6f7274616c436f6d7061637445787472696e7369633c416464726573732c20496e6465782c2043616c6c2c205369676e61747572653e2061732073725f7072696d6974697665733a3a7472616974733a3a436865636b61626c653c436f6e746578743e3e3a3a636865636b3a3a686136616634366433643863653134313660373c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a626c6f636b5f686173683a3a686564356330623638313731613832373261363c73726d6c5f696e64696365733a3a4d6f64756c653c543e3e3a3a656e756d5f7365743a3a68303536373535303336646364333932376230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a686137646233663032383432353335613963673c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c27612c207536343e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683533613665313936386533336132343964513c6e6f64655f72756e74696d653a3a43616c6c206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68383462356132636236623166613563366530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683939323039356335666239343861343966373c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a696e697469616c6973653a3a6863336234306233663463396139333365673a3c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6163636f756e745f6e6f6e63653a3a6865366231346265353363663030306264685d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862626461313161363935633934333233697b6e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f4576656e743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a6465636f64653a3a68663930646431613432386335303838396a7e6e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f4576656e743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a68626238626631356138326564613634346b403c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a68303234336239363363323165303936366c453c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a6e6f74655f66696e69736865645f65787472696e736963733a3a68376136343831393335306330366239346d453c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a68336132313130666132626635313232346e30636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68303231666133393335626566353464626f353c73726d6c5f73797374656d3a3a4d6f64756c653c543e3e3a3a66696e616c6973653a3a6834346363636263613936326163353231703e3c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a686662303565363865346663393037326171433c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a686139303936636139373932323566343772483c73726d6c5f636f6e73656e7375733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a683564336561343965616466313062653573493c73726d6c5f636f6e73656e7375733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686131616339333964336663656231306574713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68363265646139613733386461623038337582013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a68613137363665343738373638333639307682013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6372656174653a3a683635326463393431383536663366633377543c73726d6c5f636f6e74726163743a3a657865633a3a457865637574696f6e436f6e746578743c27612c20542c20562c204c3e3e3a3a696e7374616e74696174653a3a68333136376231373138383363313736337882013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a68346431396638353166653261653632667983013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a68666339316438313336386132663735627a83013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a68643461353534323762363731663634357b2e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a68653066613535373161303639623838617c84013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a68653166366138616365363837326433387d85013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a68616235376630336531316536646234307e86013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7075745f636f70793a3a68303666303834333662383837343865627f86013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7075745f73697a653a3a6834633663376438363534353466336338800187013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a686534313236363631393135656563386581017f3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6837663231626361646363386463353035820187013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d5f736565643a3a6864363635663264653866666335386664830187013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a68316266386632646431366162343361328401623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683062326262313936386437613634326585012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a68313535376135366264323763343139338601523c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c27612c204b2c20563e3e3a3a696e736572743a3a683662666530643362636566373734363087014b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6834393965646430363530313463363865880188013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f636f70793a3a6838366237363736373936303166333363890188013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a68346639666366616365353635383332618a0189013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a68626531353066336536316537613564358b0132636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68613764623366303238343235333561392e388c017b3c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a68393362346430653463666237653666658d0180013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a68646165653062346637303338303436618e014d3c73726d6c5f636f6e74726163743a3a657865633a3a457865637574696f6e436f6e746578743c27612c20542c20562c204c3e3e3a3a63616c6c3a3a68306336353363636262306137666363358f018d013c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a686466303836376532623230663966666690017f3c73726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e74726163743a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a6864386662666364313431643638326263910180013c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d5265663c27612c20486173682c20417574686f7269747949643e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a683164373061353534353039336431363692014473726d6c5f636f6e74726163743a3a7761736d3a3a72756e74696d653a3a746f5f657865637574696f6e5f726573756c743a3a683363386439653734323939323162383893016c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a683031636362383861333463356637626694013d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683433316165346535633136373237656595014e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686133353432366366656338386539343396013d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68666262613961333632623838376230659701473c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a63616e6469646174655f7265675f696e666f3a3a686634396231323338613439646266353898013d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68396535356163303933323034333530659901433c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a68356336653237353062633163393733339a01483c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a68643163366164343531613031393765629b014d3c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a68383264636434316235396265313761359c01733c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f476574427974655374727563744c6561646572626f6172643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68373166613666333234653762343066629d01713c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f47657442797465537472756374566f7465436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68313561393963396638643462616137659e01743c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f476574427974655374727563745465726d4475726174696f6e3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68393937663737373235663132623438669f017b3c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f47657442797465537472756374496e6163746976654772616365506572696f643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831643237396639613562633564353736a001723c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f476574427974655374727563744361727279436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862343035396261316366623764663039a1017c3c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f4765744279746553747275637450726573656e74536c617368506572566f7465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861323631396239366135313339626161a201753c73726d6c5f636f756e63696c3a3a73656174733a3a5f5f4765744279746553747275637443616e646964616379426f6e643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865316662393266386365623432613738a3014e3c73726d6c5f636f756e63696c3a3a73656174733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832343136333438633038313830616635a401633c73726d6c5f636f756e63696c3a3a73656174733a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6838653264333131336162393837323339a501413c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a72656d6f76655f766f7465723a3a6836306332613364333962356130313130a6016a3c28582c2059292061732073726d6c5f737570706f72743a3a7472616974733a3a456e737572654163636f756e744c69717569643c4163636f756e7449643e3e3a3a656e737572655f6163636f756e745f6c69717569643a3a6834636230633961616361383465666566a701413c73726d6c5f636f756e63696c3a3a73656174733a3a4d6f64756c653c543e3e3a3a617070726f76616c735f6f663a3a6839653538663730306462633534356533a80185013c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173685f72657365727665643a3a6837633231333764623832303232363434a9017c3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173683a3a6863636463653436393130363237343437aa014e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830336135396534623065663239376466ab013c3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6836316637313764336337303863356438ac013c3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6e6f6d696e61746f72735f666f723a3a6862356138656266383339363436366532ad01413c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6835373734323234636438313339613163ae01443c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a63757272656e745f6e6f6d696e61746f72735f666f723a3a6862343631356336333630313362616634af013b3c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a6170706c795f756e7374616b653a3a6836343038373436633936343335306530b001463c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6862343163313137366261343034646334b101743c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744c6173744572614c656e6774684368616e67653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833353561663761386563653931333465b2016b3c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563745374616b6552616e67653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834363065353534366638643462666132b301753c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637456616c696461746f72507265666572656e6365733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862373632656634356266336365663533b401683c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c27612c20753132383e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832346432633065653163666438303432b501703c73726d6c5f7374616b696e673a3a5f5f47657442797465537472756374426f6e64696e674475726174696f6e3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831376566623866316339386164383061b6016d3c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744f66666c696e65536c6173683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863623965396162633562656666313463b7016e3c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637453657373696f6e5265776172643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837396661376532326538363365653166b801763c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834316561316232323266373262353934b901473c73726d6c5f7374616b696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6830623535626165643461343034343135ba016c3c73726d6c5f737570706f72743a3a73746f726167653a3a52756e74696d6553746f726167652061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167653e3a3a6765743a3a6863616363643363643264386630666331bb017d3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7265776172643a3a6830626532636463323061303963396633bc012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6838396133336530376633623066396361bd013c3c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a7365745f76616c696461746f72733a3a6865656562663633346331633337643932be01523c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a66726f6d5f697465723a3a6866663238653963656365383834366439bf01b1013c73726d6c5f7374616b696e673a3a4e6f6d696e6174696e673c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c203c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6765743a3a6863613233643731393838623530663536c001493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6831633533613864363839383132393765c101443c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6838346563346165373435646136396536c201493c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6832353862616365333566636235383562c3014e3c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6865376338663231623738313437363937c401753c73726d6c5f636f756e63696c3a3a766f74696e673a3a5f5f47657442797465537472756374566f74696e67506572696f643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862323331376166363865636533386235c501443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6866313362656437636464636238653433c601483c73726d6c5f636f6e74726163743a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6861323638393735353334393936313132c701493c73726d6c5f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6835343439353832656537663963613762c801443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6866313362656437636464636238653433c901443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6866313362656437636464636238653433ca01473c73726d6c5f696e64696365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832383232363938363962376631383032cb01643c73726d6c5f636f756e63696c3a3a766f74696e673a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6837636463363935396138626433393637cc01433c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a69735f636f756e63696c6c6f723a3a6864653664356264613936383032323864cd013d3c73726d6c5f636f756e63696c3a3a766f74696e673a3a4d6f64756c653c543e3e3a3a7665746f5f6f663a3a6866623838333734613738653136656133ce01733c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837383939656239633138386436313234cf01763c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c204163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6830613261366266363537636133666362d001970173726d6c5f74726561737572793a3a5f494d504c5f4445434f44455f464f525f50726f706f73616c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f74726561737572793a3a50726f706f73616c3c4163636f756e7449642c2042616c616e63653e3e3a3a6465636f64653a3a6863613732326138663265306235353163d101393c73726d6c5f7375646f3a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6831363963626537313837393534666534d2013e3c73726d6c5f7375646f3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6861323330323632393564373261393764d301433c73726d6c5f7375646f3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6831626436323066313738313639626265d401613c73726d6c5f7375646f3a3a5f5f476574427974655374727563744b65793c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838383636373830336539383938643336d5013d3c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6836633337353265323066373238646235d601423c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6830383934333438393830653964636362d701473c73726d6c5f74726561737572793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6833366132633966313239366563373839d8016d3c73726d6c5f74726561737572793a3a5f5f476574427974655374727563745370656e64506572696f643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839333337356635666231303430623066d901743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862323032323538333266653130323239da016a3c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a6832383164363537623238313831316265db016a3c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a6837663935333261373837326465343934dc013d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6862353838313234306262663266653332dd01397061726974795f636f6465633a3a636f6465633a3a4f75747075743a3a707573685f627974653a3a6834316330646132666461306266303130de014e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830623038393030323631393736653264df01135f5f727573745f616c6c6f635f7a65726f6564e0014e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862353039656138383063636365313737e101be013c6e6f64655f72756e74696d653a3a4c6f6720617320636f72653a3a636f6e766572743a3a46726f6d3c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c7072696d69746976655f74797065733a3a483235362c207375627374726174655f7072696d6974697665733a3a617574686f726974795f69643a3a45643235353139417574686f7269747949643e3e3e3a3a66726f6d3a3a6839343362626536316435373830313763e201493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a6832636539616637316133653435313066e301b00173725f7072696d6974697665733a3a67656e657269633a3a626c6f636b3a3a5f494d504c5f4445434f44455f464f525f426c6f636b3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073725f7072696d6974697665733a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c4865616465722c2045787472696e7369633e3e3a3a6465636f64653a3a6835393939366461336332303165376436e4017c3c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c20486173682c204469676573744974656d3e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6831323763353437633739613631643632e5013873726d6c5f636f6e74726163743a3a6761733a3a726566756e645f756e757365645f6761733a3a6834626338313839613937633362323861e6012e73726d6c5f636f6e74726163743a3a6761733a3a6275795f6761733a3a6839623665393138373434663061663461e7013c3c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6866663662633634383431623762306437e801413c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6864613834653561383237386661323739e901463c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6831326335623931326332386532386130ea013d3c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6836333835656437653262376635336165eb01423c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6838383765343333316165326236386632ec01473c73726d6c5f62616c616e6365733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6834303762333866303839616336613935ed0134636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6863323736313832626137393735393637ee013c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6838646364633565656163333438653134ef012e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6839326262643639653162366238316263f001483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836666336653764643536633334653137f101323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837616535326134313431313430626563f2012d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a6830306561303536306664663962383338f3012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6864373166383938653035653236613935f401303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864653061356234393466353865326637f501453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836353166346536383632356566386437f6015e3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832353136303932636265623638663963f7013c3c73726d6c5f696e64696365733a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6866383034346338643861636333383365f801413c73726d6c5f696e64696365733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6863663664383435306563623666383233f901463c73726d6c5f696e64696365733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6866643963366537623662373435333465fa013e3c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6861653430633162376362373137326534fb01433c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6861333164336631633561363531616237fc01483c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6832356163653635343665373464656338fd01703c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374446973706174636851756575653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866396635303734383961326666646136fe013e3c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6864313334396338363738643632393265ff01433c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a68343562373364666536353761646364358002483c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a68393330663138396463653634646337318102303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838613365633164666234343639356361820249636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207536343e3a3a666d743a3a6839636436373561313931336238343533830235636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68343335396238663836343362376231378402303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864613832643064393335373230656437850241636f72653a3a636861723a3a6d6574686f64733a3a3c696d706c20636861723e3a3a6573636170655f64656275673a3a683065306332333737313663623535653786028001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a686434653335323666333439643666356387022e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a68386535336363313765313665643465378802303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865383638313262393639373563323334890249636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a68363763663236396239396434383238318a0234636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f6e7461696e733a3a68643735323839356138613334316662388b02443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663133626564376364646362386534338c02493c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c20563e3e3a3a696e736572743a3a68333832336439343933363230646539398d020c436f72655f76657273696f6e8e0210436f72655f617574686f7269746965738f0212436f72655f657865637574655f626c6f636b90024173725f7072696d6974697665733a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a683261363331353936313031623565643591026c3c73725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362061732073725f7072696d6974697665733a3a7472616974733a3a486173683e3a3a656e756d6572617465645f747269655f726f6f743a3a68356331313236653534316436323361309202753c73726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c20426c6f636b2c20436f6e746578742c205061796d656e742c20416c6c4d6f64756c65733e3e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a68643532313662353037343530383137619302483c492061732073725f7072696d6974697665733a3a7472616974733a3a436865636b457175616c3e3a3a636865636b5f657175616c3a3a68333862643033333065616436333830619402483c636f72653a3a666d743a3a417267756d656e74733c275f3e20617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6831646533376266393932623233333530950215436f72655f696e697469616c6973655f626c6f636b9602114d657461646174615f6d657461646174619702603c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68366130613862663934323034643233359802433c5b75385d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68626639663936613330633635393763649902633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68376631626430626566343033373034369a02633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68376534363137366133376165393831329b02633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68646533313566316236353930376665329c021c426c6f636b4275696c6465725f6170706c795f65787472696e7369639d021b426c6f636b4275696c6465725f66696e616c6973655f626c6f636b9e0220426c6f636b4275696c6465725f696e686572656e745f65787472696e736963739f025d3c7375627374726174655f696e686572656e74733a3a496e686572656e7444617461206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830353034623364636238316566343361a0023873726d6c5f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a6832323431333365363839393539636263a102623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6838373264656461653734313464383232a2021c426c6f636b4275696c6465725f636865636b5f696e686572656e7473a302477375627374726174655f696e686572656e74733a3a436865636b496e686572656e7473526573756c743a3a7075745f6572726f723a3a6838623532396232343738316465323263a402523c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c27612c204b2c20563e3e3a3a696e736572743a3a6865633164343039366237396338383737a50218426c6f636b4275696c6465725f72616e646f6d5f73656564a6022b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ea7028f013c73726d6c5f666565733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a43686172676542797465734665653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368617267655f626173655f62797465735f6665653a3a6832333234643437643338316463373730a802214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e6765a9021e4772616e6470614170695f6772616e6470615f617574686f726974696573aa0215417572614170695f736c6f745f6475726174696f6eab02623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6832356265393535383066326634363261ac02733c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838363135353861663030306135346335ad02623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863333039663066646238343837323263ae02733c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c20563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6862323362323966343936313164306664af02453c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6863363530356531353435393138633166b0024a3c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6836623930383363643962396535643232b1024f3c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6838356163376434623933643165383230b202703c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a5f5f47657442797465537472756374566f74696e673c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836343336373433343966613439383463b3025d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830663466303133386537353266393331b4025e3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832643431633331343737313235303032b502653c73726d6c5f636f756e63696c3a3a6d6f74696f6e733a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6865336532663161326264343632373031b602406e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73797374656d3a3a6833366466326333383939386534313261b70239636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653a3a63616c6c5f6f6e63653a3a6832613332666633643832393134363763b802416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696e64696365733a3a6832326561316462316263633237353432b902426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f62616c616e6365733a3a6834643233633039313264653762303138ba02416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73657373696f6e3a3a6831356431316534646466316261386139bb02416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7374616b696e673a3a6835373736653130613138366661373030bc02436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f64656d6f63726163793a3a6862313839363637376630653335363736bd02416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f756e63696c3a3a6838313432653837386365353363643031be02486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f756e63696c5f766f74696e673a3a6835383830303635653730653465633238bf02496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f756e63696c5f6d6f74696f6e733a3a6831353062343839383735643036656130c002416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6772616e6470613a3a6864303230653937373239383536363739c102426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f74726561737572793a3a6831623838653462363463393230356538c202426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6e74726163743a3a6863323133373038643764343935383932c3023e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7375646f3a3a6832636536623263653636663939646439c4023e3c73726d6c5f666565733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6839646234616462353363346137366431c502433c73726d6c5f666565733a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6839323238366266313763626438386139c6023e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f666565733a3a6865613934666439313861316139363239c702703c73726d6c5f666565733a3a5f5f476574427974655374727563745472616e73616374696f6e426173654665653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863633433353830373166653131333433c802880173726d6c5f636f6e74726163743a3a5f494d504c5f4445434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6e74726163743a3a5363686564756c653c4761733e3e3a3a6465636f64653a3a6838386430343331313234306465666431c9027c3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6831613433376261356238663431393864ca023073726d6c5f636f6e74726163743a3a657865633a3a7472616e736665723a3a6836613562633834353830333834363330cb023873726d6c5f636f6e74726163743a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a6863383164633030313836633030336364cc025e3c73726d6c5f636f6e74726163743a3a7761736d3a3a5761736d566d3c27612c20543e2061732073726d6c5f636f6e74726163743a3a657865633a3a566d3c543e3e3a3a657865637574653a3a6837333933346635623061653438373437cd027a3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6865303831326631393233636434613164ce02543c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e3e3a3a7365745f62616c616e63653a3a6866323530313437623366353539363437cf0230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6864663565306531323433393732363839d0024173726d6c5f636f6e74726163743a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a6835366166653637353466316536363139d1026f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6865373964333863623430326131663563d202467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6836383036656134373130326134616234d30230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6831663339353065343539656264646663d4024b3c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e3e3a3a696e736572743a3a6836613932613339376133643733613537d5023c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6831386630393130373131343532376331d602553c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3e3a3a7265736f6c76655f747970655f7265663a3a6862383638386439633037323635323231d702a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6835393761653539613638623466643835d8023a707761736d5f7574696c733a3a72756c65733a3a496e737472756374696f6e547970653a3a6f703a3a6838383163633738373832643833343862d9022f3c616c6c6f633a3a7665633a3a5665633c543e3e3a3a696e736572743a3a6866323962646433366438663135643464da02523c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3e3a3a707573685f66756e6374696f6e3a3a6832346462643664633333646235313836db023c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a6831633634356537616666633737303238dc026b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6831346665646566636631376561336533dd025d3c73726d6c5f636f6e74726163743a3a43616c6c3c543e2061732073726d6c5f737570706f72743a3a64697370617463683a3a446973706174636861626c653e3a3a64697370617463683a3a6866326137373463396333346633383932de026b3c73726d6c5f636f6e74726163743a3a7761736d3a3a5761736d566d3c27612c20543e2061732073726d6c5f636f6e74726163743a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6837393863353563346638303331666630df023d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6832333964343339303266343430356363e0023c3c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6831353066376533343437653564376337e102413c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6866626666306262363739636563636339e202463c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6836623138343063663461383339366435e302713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6830333134316439646164623964323964e402457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6838353437393638333334346566623332e5027c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6832343965666135346161363234393138e602773c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6837323635336332643130323561323261e702773c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6835363063653666326465623537373837e8024773726d6c5f737570706f72743a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a66756c6c5f6b65793a3a6866393235663636656361636262613565e902723c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6830616234626633343866376564363735ea02743c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64653a3a6833643865613361656664373637326532eb027f3c73726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c27612c20543e2061732073726d6c5f636f6e74726163743a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6836646566333861373064613832326138ec023d3c73726d6c5f636f6e74726163743a3a4d6f64756c653c543e3e3a3a63616c6c5f66756e6374696f6e733a3a6834353436613266613430363937636130ed02423c73726d6c5f636f6e74726163743a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f6e616d653a3a6833333966653661616363633139656663ee02473c73726d6c5f636f6e74726163743a3a4d6f64756c653c543e3e3a3a73746f72655f6d657461646174615f66756e6374696f6e733a3a6865373365353734646633383132393133ef02713c73726d6c5f636f6e74726163743a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837313335393635663366313131643165f0026f3c73726d6c5f636f6e74726163743a3a5f5f47657442797465537472756374426c6f636b4761734c696d69743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861633739643638323432313464393931f1026a3c73726d6c5f636f6e74726163743a3a5f5f476574427974655374727563744d617844657074683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866393039383532323330316561366430f2026f3c73726d6c5f636f6e74726163743a3a5f5f47657442797465537472756374437265617465426173654665653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834363266303365366232623361353266f3026d3c73726d6c5f636f6e74726163743a3a5f5f4765744279746553747275637443616c6c426173654665653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862663064383032376634376133626638f4026d3c73726d6c5f636f6e74726163743a3a5f5f47657442797465537472756374436f6e74726163744665653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835663161326561356264323061383134f502363c73726d6c5f636f6e74726163743a3a436f6e6669673c543e3e3a3a7072656c6f61643a3a6834376335376235386630356166323730f60241707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6839643734366466306564353939386533f702457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6865646264303366613132336337373732f802323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837613935313030396230303834373736f9023f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6862303836343566346536623763643631fa02623c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c20563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833326436396139613265316139323834fb02543c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c20493e3e3a3a737065635f657874656e643a3a6838323666343735373532356137626566fc02383c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26276120543e3e3a3a636c6f6e65643a3a6836626364366632323630333264613532fd0246707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6834376464636436636538396562373362fe024b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6831383638376532636566343132633961ff02463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68623363373039373663383735323963628003423c5b545d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68643837353137333065356230643564318103633c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c204f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6861353865656637663062623131633038820311727573745f626567696e5f756e77696e6483030a5f5f72675f616c6c6f6384030c5f5f72675f6465616c6c6f6385030c5f5f72675f7265616c6c6f638603115f5f72675f616c6c6f635f7a65726f6564870323636f72653a3a666d743a3a77726974653a3a686564313964326132646634613939663588032e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a683737623336633331383763646661363289033e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68623936336336336461633039613564658a0330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68336462376530353366396565363736348b033a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68653234363164626633343735343833318c033b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68326161616264313037336465336261358d033a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68396262313337633765366531323965628e03313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68333430343833333766616231326263658f032c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a683835623930363830366464616562343190034a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68343031653834343139653837633362669103323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835383339336530646635626263323032920349636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a6835343034306432623131306631393333930334636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a68356562356133666665396438316635639403066d656d7365749503066d656d6370799603076d656d6d6f76659703066d656d636d709803095f5f756469767469339903085f5f6d756c7469339a033f636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a727573745f693132385f73686c3a3a68313464616132323232386339303861379b033f636f6d70696c65725f6275696c74696e733a3a696e743a3a73686966743a3a727573745f753132385f7368723a3a68643764323365303831373731333130639c030c5f5f756469766d6f6474693400590970726f64756365727302086c616e677561676501045275737404323031380c70726f6365737365642d62790105727573746325312e33342e302d6e696768746c79202838616537333061343420323031392d30322d303429", + "0x53d1471b684c8a776c80353e5981c960": "0x00407a10f35a00000000000000000000", + "0xd9c94b41dc87728ebf0a966d2e9ad9c0": "0x3200000000000000", + "0xb8f48a8c01f629d6dc877f64892bed49": "0x0000000000000000", + "0x0e4944cfd98d6f4cc374d16f5a4e3f9c": "0x0000000000000000", + "0x040ff70c23416b89ce6afb75ee0d362e": "0x00000000", + "0x24586f4898a5a637b755b658ec163d00": "0x00407a10f35a00000000000000000000", + "0x4664fb5d4e16f894df23cadb3faaa9a6": "0x04000000", + "0x784006f2a1a409c65c0059c57eaed7a6": "0x00e40b54020000000000000000000000", + "0x329586a7b97f2ac15f6c26a02c3c5621": "0x1082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0xdd9b01f8462dc19488279cb351a6d861": "0x20a10700", + "0x52c9048efbfc40fd1e312b7bed451dee": "0x06000000", + "0x472b8f236d06a2ff7f1e9b2e848ef1d5": "0x0080e03779c311000000000000000000", + "0x74d5dca6735bab024bc25136daaab7c0": "0x06", + "0x3a6772616e6470613a617574683a6c656e": "0x04000000", + "0x8366297e853b97a38cca0f62019a717b": "0x00000000000000000000000000000000", + "0x27b3872d47181b4a2dc15f0da43e7026": "0xe803000000000000", + "0xf4039aa8ae697861be900c58239e96f7": "0x0010a5d4e80000000000000000000000", + "0x3a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5", + "0x52b963fbdb3d6e1b03808fc20071f07f": "0x0027060000000000", + "0x7935e46f94f24b82716c0142e2271de9": "0x8070000000000000", + "0x50a63a871aced22e88ee6466fe5aa5d9": "0xf295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd", + "0xe026dd082e3158e72eb7c985fc8bac4f": "0x4038000000000000", + "0x579ab55d37b1220812be3c3df29d4858": "0x0000000000000000", + "0x0b21b3456b23e90d061941ab416f5ea2": "0x00000000000000000000000000000000", + "0x90d5871cf3f4d0a3642cf2043a7d8eda": "0x0010a5d4e80000000000000000000000", + "0x3a6772616e6470613a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf50100000000000000", + "0xb9b861cab4bbce870c811515bd5f33d7": "0x00", + "0x3a617574683a00000000": "0x82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5", + "0xb7b6ec0f25eb1ed8b91d05f697d7a874": "0x0c00000000000000", + "0x3a6772616e6470613a617574683a02000000": "0x063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca50100000000000000", + "0x0e0cdac0d4de97c54f3ae216b003fa81": "0x5802000000000000", + "0xdade128e67a5ed110063f56a01ab6bbf": "0x0000000000000000", + "0x3a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7", + "0x93940e78496482b15b64783020bbdfa0": "0x6400000000000000", + "0xfe7030fd433199728c516e4392091aa5": "0x0080c6a47e8d03000000000000000000", + "0x7c1f36e9b2a83a7f2b42d97ec0f18d9c": "0x04f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd", + "0x6ca8e0c58adf9d1f3105b0888d39bf2d": "0x0010a5d4e80000000000000000000000", + "0x3a6772616e6470613a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c0100000000000000", + "0x637414312dac3b280120bf15b4f66cee": "0x00000000", + "0xd437fe93b0bd0a5d67d30d85d010edc2": "0x40420f00", + "0xcc2719d196dc6b2ef83fd3399f9a8c7b": "0x1082c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf54de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca58101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0xa902f1f0ef97177b8df9f9fd413768e7": "0x00000000", + "0x3a617574683a6c656e": "0x04000000", + "0x6e45a8645fa8f905c49fecfef3d06c67": "0x01000000", + "0x59b17352bea17cb7dec6dde697de7db4": "0x6400000000000000", + "0x799192c17c5cc562d709af11ace92e6a": "0x00040000", + "0xa36baa0f89eff09b2facf282f27a11ba": "0x50c30000", + "0x5278a9149ec1adfa8090a8ad336c881e": "0x0300000000000000", + "0xcf9a75deea0508104cd993c82daf57d3": "0x8096980000000000", + "0x4a8b1a5c7681353a6a320553abbbca49": "0x4038000000000000", + "0x717a2ee9c64ad3424e10e4461ec08296": "0x000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000000010010000000", + "0x24b2518f9a9ee24ab0b62346d83d90b0": "0x11080000", + "0x2dce29f1a768624dc5343063cb77f77d": "0x07000000", + "0x3a617574683a03000000": "0x8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c", + "0x90e2849b965314409e8bc00011f3004f": "0x04000000", + "0xf14d23a9d4492a1efc9194e257b3c3d9": "0x00000000", + "0x62f532424b7b1c52f522857315040f27": "0x00407a10f35a00000000000000000000", + "0x78f4ad73d6b7279f8d06f359e363c829": "0x0000a0dec5adc9353600000000000000", + "0xfc2dc4b8bb0b9ca8f01a73a726f7c7f5": "0x00e1000000000000", + "0xfb4fdd0ab2d85118e220e2e7473cd3b5": "0x0000a0dec5adc9353600000000000000", + "0x34de7fc8c73e4252b9e09a9e3bf602f8": "0x6400000000000000", + "0x3b7d32346a3315a351084927a27d06a7": "0x0010a5d4e80000000000000000000000", + "0x99e2aba8a2b7c8ccba2d740fb86adb0c": "0x00", + "0x3a6772616e6470613a617574683a01000000": "0x4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e70100000000000000", + "0x125dc846383907f5846f72ce53ca0e4b": "0x00ca9a3b000000000000000000000000", + "0x2ec6e5652282d579398fb8fdfa531ef6": "0x0000000000000000", + "0x9651d20f401bfac47731a01d6eba33b4": "0x00000000" + } + } +} diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index b06cc974518a6e27aae2855010d42c588ee616ae..53980de0330a8d1bd0ce65254c80a5201c274313 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,35 +16,52 @@ //! Substrate chain configurations. -use primitives::{AuthorityId, ed25519}; +use primitives::{ed25519::Public as AuthorityId, ed25519, sr25519, Pair, crypto::UncheckedInto}; use node_primitives::AccountId; use node_runtime::{ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig, - SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, - UpgradeKeyConfig, ContractConfig, GrandpaConfig, Permill, Perbill}; + SessionConfig, StakingConfig, StakerStatus, TimestampConfig, BalancesConfig, TreasuryConfig, + SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, FeesConfig, Permill, Perbill}; pub use node_runtime::GenesisConfig; use substrate_service; - -use substrate_keystore::pad_seed; +use hex_literal::{hex, hex_impl}; +use substrate_telemetry::TelemetryEndpoints; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; /// Specialised `ChainSpec`. pub type ChainSpec = substrate_service::ChainSpec; -/// Charred Cherry testnet generator -pub fn charred_cherry_config() -> Result { - ChainSpec::from_embedded(include_bytes!("../res/charred-cherry.json")) +/// Dried Danta testnet generator +pub fn dried_danta_config() -> Result { + ChainSpec::from_embedded(include_bytes!("../res/dried-danta.json")) } fn staging_testnet_config_genesis() -> GenesisConfig { - let initial_authorities = vec![ - hex!["82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5"].into(), - hex!["4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7"].into(), - hex!["063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5"].into(), - hex!["8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c"].into(), - ]; - let endowed_accounts = vec![ - hex!["f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd"].into(), + // stash, controller, session-key + // generated with secret: + // for i in 1 2 3 4 ; do for j in stash controller; do subkey -p danta-$i-$j restore $secret; done; done + // and + // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 -p danta-$i-$j restore $secret; done; done + let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![( + hex!["d807f8bd6b4b02b3db716dd5372960b094ed0e62b5704a07bc990130a642992b"].unchecked_into(), // 5GwxZv7LxSUQn89TLUaLi3oEWhFcabqW3nHcEg2J88gZNhrb + hex!["1a934af462454e512e22b5d9455c0c3c2df479b1c61406b3d990f6bc2eb25e09"].unchecked_into(), // 5CfYrg5cW8UebBdfJpJbKFhZLyk7yHWXUgdxZnSGb2dWKgpt + hex!["831fcce3a9565baf093b52568a8cb9875cb54974d80da8fc4f0cc767128a23e9"].unchecked_into(), // 5F2daQPHK7yv4Yuwyz3cggvvn1R5u1ofGMQ5LK5XvnfebMcX + ),( + hex!["12652f26e427c56268095bb0ec5824471e37722b073a9fa5de61c61c1de94656"].unchecked_into(), // 5CUpn2JmpsWkHQjZgWjN3rqPEUnjjUQZYcMk14nbUgR2Gpab + hex!["5279e73e22971d729276ebad4eb6804d1b9c0c35bd32e8aba4513c674760a461"].unchecked_into(), // 5Dvqzke7Mdp3fP6Ysut7UXPSepPr3Qguys6LNkZGPSwXwAkR + hex!["dbe61640d854bb7bf83cbfaf638a8a4c76c49a919ec3bbdd86799061fc1903e4"].unchecked_into(), // 5H32hCtKf6nXSckviVhUvWb7N14wDCRunRkCM29mxEXwjcUZ + ),( + hex!["a81d738fdeeaed440cfce5635e0820d0d23e89207cf66a62b8c0d2a968e37d32"].unchecked_into(), // 5Fs8ehAjDEnenDwULCPnEr3HVXgepAVfyk9ABW84NfxCYtWD + hex!["443a2c779a5f5dada8ee6921efec9673f67e5ce1bd6012899ff6c1adc437696c"].unchecked_into(), // 5DcAPqR269myKXhZmwbU1x2xLbuTojr85jHNRuDhrFdZ3vwi + hex!["5bc01f56225e8602372fb343dba65a73e20c55bdbb3b8343a8f34df298a616fb"].unchecked_into(), // 5E91HbY2xo2qDJzi3KY8nRXjDNAQE9WtmMaji6YRwT8DAuK1 + ),( + hex!["e269e835e0bc07c497d55bc17c7bb29c85c5615f9e61582ffdeca7e5f5c66578"].unchecked_into(), // 5HBa95U5HDFCV1N5Xyrjti65F71tHRQcPbZBmkxRJ39SpqzM + hex!["3e9829e6fd4fc7501b504fc16f12177c6c7f38aeb3b8344efb9b15ee85118b2c"].unchecked_into(), // 5DUn2afs2QevZ6PrGu8snrt76157oacH6JXUD8JNM18VKMwK + hex!["0fd673ee5e95ed124bcd71463ff924c810573dad91527ab9d2b5af36f66ff84b"].unchecked_into(), // 5CRUHGLA1JYe2v4p479VCHybqjB9uBXjGkJ2npdduVdrTuUM + )]; + // generated with secret: subkey -p danta-root restore $secret + let endowed_accounts: Vec = vec![ + hex!["343df6f04ffae0840f214f6cb0da00b612c7e9347f980e7afafc520582f79136"].unchecked_into(), // 5DFCkiP9vky31C1ZP3LpuQYinLAFwQqq6vda7NXa8ALCpq5D ]; const MILLICENTS: u128 = 1_000_000_000; const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent. @@ -55,28 +72,37 @@ fn staging_testnet_config_genesis() -> GenesisConfig { const HOURS: u64 = MINUTES * 60; const DAYS: u64 = HOURS * 24; + const ENDOWMENT: u128 = 10_000_000 * DOLLARS; + const STASH: u128 = 100 * DOLLARS; + GenesisConfig { consensus: Some(ConsensusConfig { - code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), // TODO change - authorities: initial_authorities.clone(), + code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), // FIXME change once we have #1252 + authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), }), system: None, balances: Some(BalancesConfig { - balances: endowed_accounts.iter().map(|&k| (k, 10_000_000 * DOLLARS)).collect(), - transaction_base_fee: 1 * CENTS, - transaction_byte_fee: 10 * MILLICENTS, + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) + .collect(), existential_deposit: 1 * DOLLARS, transfer_fee: 1 * CENTS, creation_fee: 1 * CENTS, - reclaim_rebate: 1 * CENTS, + vesting: vec![], + }), + indices: Some(IndicesConfig { + ids: endowed_accounts.iter().cloned() + .chain(initial_authorities.iter().map(|x| x.0.clone())) + .collect::>(), }), session: Some(SessionConfig { - validators: initial_authorities.iter().cloned().map(Into::into).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 5 * MINUTES, + keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), staking: Some(StakingConfig { current_era: 0, - intentions: initial_authorities.iter().cloned().map(Into::into).collect(), offline_slash: Perbill::from_billionths(1_000_000), session_reward: Perbill::from_billionths(2_065), current_offline_slash: 0, @@ -86,6 +112,8 @@ fn staging_testnet_config_genesis() -> GenesisConfig { bonding_duration: 60 * MINUTES, offline_slash_grace: 4, minimum_validator_count: 4, + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 10 * MINUTES, // 1 day per public referendum @@ -129,12 +157,16 @@ fn staging_testnet_config_genesis() -> GenesisConfig { block_gas_limit: 10_000_000, current_schedule: Default::default(), }), - upgrade_key: Some(UpgradeKeyConfig { + sudo: Some(SudoConfig { key: endowed_accounts[0].clone(), }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.clone().into_iter().map(|k| (k, 1)).collect(), - }) + authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + }), + fees: Some(FeesConfig { + transaction_base_fee: 1 * CENTS, + transaction_byte_fee: 10 * MILLICENTS, + }), } } @@ -146,59 +178,85 @@ pub fn staging_testnet_config() -> ChainSpec { "staging_testnet", staging_testnet_config_genesis, boot_nodes, - Some(STAGING_TELEMETRY_URL.into()), + Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), None, None, None, ) } -/// Helper function to generate AuthorityID from seed -pub fn get_authority_id_from_seed(seed: &str) -> AuthorityId { - let padded_seed = pad_seed(seed); - // NOTE from ed25519 impl: - // prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - ed25519::Pair::from_seed(&padded_seed).public().0.into() +/// Helper function to generate AccountId from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId { + sr25519::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate AuthorityId from seed +pub fn get_session_key_from_seed(seed: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate stash, controller and session key from seed +pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuthorityId) { + ( + get_account_id_from_seed(&format!("{}//stash", seed)), + get_account_id_from_seed(seed), + get_session_key_from_seed(seed) + ) } /// Helper function to create GenesisConfig for testing pub fn testnet_genesis( - initial_authorities: Vec, - upgrade_key: AccountId, - endowed_accounts: Option>, + initial_authorities: Vec<(AccountId, AccountId, AuthorityId)>, + root_key: AccountId, + endowed_accounts: Option>, ) -> GenesisConfig { - let endowed_accounts = endowed_accounts.unwrap_or_else(|| { + let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { vec![ - get_authority_id_from_seed("Alice"), - get_authority_id_from_seed("Bob"), - get_authority_id_from_seed("Charlie"), - get_authority_id_from_seed("Dave"), - get_authority_id_from_seed("Eve"), - get_authority_id_from_seed("Ferdie"), + get_account_id_from_seed("Alice"), + get_account_id_from_seed("Bob"), + get_account_id_from_seed("Charlie"), + get_account_id_from_seed("Dave"), + get_account_id_from_seed("Eve"), + get_account_id_from_seed("Ferdie"), + get_account_id_from_seed("Alice//stash"), + get_account_id_from_seed("Bob//stash"), + get_account_id_from_seed("Charlie//stash"), + get_account_id_from_seed("Dave//stash"), + get_account_id_from_seed("Eve//stash"), + get_account_id_from_seed("Ferdie//stash"), ] }); + + const STASH: u128 = 1 << 20; + const ENDOWMENT: u128 = 1 << 20; + GenesisConfig { consensus: Some(ConsensusConfig { code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), - authorities: initial_authorities.clone(), + authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), }), system: None, + indices: Some(IndicesConfig { + ids: endowed_accounts.clone(), + }), balances: Some(BalancesConfig { - transaction_base_fee: 1, - transaction_byte_fee: 0, existential_deposit: 500, transfer_fee: 0, creation_fee: 0, - reclaim_rebate: 0, - balances: endowed_accounts.iter().map(|&k| (k.into(), (1 << 60))).collect(), + balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), + vesting: vec![], }), session: Some(SessionConfig { - validators: initial_authorities.iter().cloned().map(Into::into).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 10, + keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), staking: Some(StakingConfig { current_era: 0, - intentions: initial_authorities.iter().cloned().map(Into::into).collect(), minimum_validator_count: 1, validator_count: 2, sessions_per_era: 5, @@ -208,6 +266,8 @@ pub fn testnet_genesis( current_offline_slash: 0, current_session_reward: 0, offline_slash_grace: 0, + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 9, @@ -218,8 +278,8 @@ pub fn testnet_genesis( }), council_seats: Some(CouncilSeatsConfig { active_council: endowed_accounts.iter() - .filter(|a| initial_authorities.iter().find(|&b| a.0 == b.0).is_none()) - .map(|a| (a.clone().into(), 1000000)).collect(), + .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, _)| controller == endowed).is_none()) + .map(|a| (a.clone(), 1000000)).collect(), candidacy_bond: 10, voter_bond: 2, present_slash_per_voter: 1, @@ -227,7 +287,7 @@ pub fn testnet_genesis( presentation_duration: 10, approval_voting_period: 20, term_duration: 1000000, - desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32, + desired_seats: (endowed_accounts.len() / 2 - initial_authorities.len()) as u32, inactive_grace_period: 1, }), council_voting: Some(CouncilVotingConfig { @@ -253,21 +313,25 @@ pub fn testnet_genesis( block_gas_limit: 10_000_000, current_schedule: Default::default(), }), - upgrade_key: Some(UpgradeKeyConfig { - key: upgrade_key, + sudo: Some(SudoConfig { + key: root_key, }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.clone().into_iter().map(|k| (k, 1)).collect(), - }) + authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + }), + fees: Some(FeesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, + }), } } fn development_config_genesis() -> GenesisConfig { testnet_genesis( vec![ - get_authority_id_from_seed("Alice"), + get_authority_keys_from_seed("Alice"), ], - get_authority_id_from_seed("Alice").into(), + get_account_id_from_seed("Alice"), None, ) } @@ -280,10 +344,10 @@ pub fn development_config() -> ChainSpec { fn local_testnet_genesis() -> GenesisConfig { testnet_genesis( vec![ - get_authority_id_from_seed("Alice"), - get_authority_id_from_seed("Bob"), + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), ], - get_authority_id_from_seed("Alice").into(), + get_account_id_from_seed("Alice"), None, ) } @@ -297,7 +361,7 @@ pub fn local_testnet_config() -> ChainSpec { mod tests { use super::*; use service_test; - use service::Factory; + use crate::service::Factory; fn local_testnet_genesis_instant() -> GenesisConfig { let mut genesis = local_testnet_genesis(); @@ -312,6 +376,6 @@ mod tests { #[test] fn test_connectivity() { - service_test::connectivity::(integration_test_config()); + service_test::connectivity::(integration_test_config()); } } diff --git a/node/cli/src/error.rs b/node/cli/src/error.rs index a83466fbe679dd463a4542b53eeb374a62328a2f..dd5448ac8ad6366813387e7694a4f69872117ff7 100644 --- a/node/cli/src/error.rs +++ b/node/cli/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,6 +17,9 @@ //! Initialization errors. use client; +use error_chain::{ + error_chain, error_chain_processing, impl_error_chain_processed +}; error_chain! { foreign_links { diff --git a/node/cli/src/lib.rs b/node/cli/src/lib.rs index 70980b495d79d76c65360515c6a1d7a8266e2c1d..1b103b7bfc1961fc6bbb35f00be0ca613334b82a 100644 --- a/node/cli/src/lib.rs +++ b/node/cli/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,43 +19,16 @@ #![warn(missing_docs)] #![warn(unused_extern_crates)] -extern crate tokio; - -extern crate substrate_cli as cli; -extern crate substrate_primitives as primitives; -extern crate node_runtime; -extern crate exit_future; -#[macro_use] -extern crate hex_literal; -#[cfg(test)] -extern crate substrate_service_test as service_test; -extern crate substrate_transaction_pool as transaction_pool; -#[macro_use] -extern crate substrate_network as network; -extern crate substrate_consensus_aura as consensus; -extern crate substrate_client as client; -extern crate substrate_finality_grandpa as grandpa; -extern crate node_primitives; -#[macro_use] -extern crate substrate_service; -extern crate node_executor; -extern crate substrate_keystore; - -#[macro_use] -extern crate log; -extern crate structopt; - pub use cli::error; pub mod chain_spec; mod service; -mod params; -use tokio::runtime::Runtime; -pub use cli::{VersionInfo, IntoExit}; +use tokio::prelude::Future; +use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; +pub use cli::{VersionInfo, IntoExit, NoCustom}; use substrate_service::{ServiceFactory, Roles as ServiceRoles}; -use params::{Params as NodeParams}; -use structopt::StructOpt; use std::ops::Deref; +use log::info; /// The chain specification option. #[derive(Clone, Debug)] @@ -64,8 +37,8 @@ pub enum ChainSpec { Development, /// Whatever the current runtime is, with simple Alice/Bob auths. LocalTestnet, - /// The Charred Cherry testnet. - CharredCherry, + /// The Dried Danta testnet. + DriedDanta, /// Whatever the current runtime is with the "global testnet" defaults. StagingTestnet, } @@ -74,7 +47,7 @@ pub enum ChainSpec { impl ChainSpec { pub(crate) fn load(self) -> Result { Ok(match self { - ChainSpec::CharredCherry => chain_spec::charred_cherry_config()?, + ChainSpec::DriedDanta => chain_spec::dried_danta_config()?, ChainSpec::Development => chain_spec::development_config(), ChainSpec::LocalTestnet => chain_spec::local_testnet_config(), ChainSpec::StagingTestnet => chain_spec::staging_testnet_config(), @@ -85,7 +58,7 @@ impl ChainSpec { match s { "dev" => Some(ChainSpec::Development), "local" => Some(ChainSpec::LocalTestnet), - "" | "cherry" | "charred-cherry" => Some(ChainSpec::CharredCherry), + "" | "danta" | "dried-danta" => Some(ChainSpec::DriedDanta), "staging" => Some(ChainSpec::StagingTestnet), _ => None, } @@ -105,58 +78,36 @@ pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Resul T: Into + Clone, E: IntoExit, { - let full_version = substrate_service::config::full_version_from_strs( - version.version, - version.commit - ); - - let matches = match NodeParams::clap() - .name(version.executable_name) - .author(version.author) - .about(version.description) - .version(&(full_version + "\n")[..]) - .get_matches_from_safe(args) { - Ok(m) => m, - Err(e) => e.exit(), - }; - - let (spec, mut config) = cli::parse_matches::( - load_spec, version, "substrate-node", &matches - )?; - - if matches.is_present("grandpa_authority_only") { - config.custom.grandpa_authority = true; - config.custom.grandpa_authority_only = true; - // Authority Setup is only called if validator is set as true - config.roles = ServiceRoles::AUTHORITY; - } else if matches.is_present("grandpa_authority") { - config.custom.grandpa_authority = true; - // Authority Setup is only called if validator is set as true - config.roles = ServiceRoles::AUTHORITY; - } - - match cli::execute_default::(spec, exit, &matches, &config)? { - cli::Action::ExecutedInternally => (), - cli::Action::RunService(exit) => { - info!("Substrate Node"); + cli::parse_and_execute::( + load_spec, &version, "substrate-node", args, exit, + |exit, _custom_args, config| { + info!("{}", version.name); info!(" version {}", config.full_version()); - info!(" by Parity Technologies, 2017, 2018"); + info!(" by Parity Technologies, 2017-2019"); info!("Chain specification: {}", config.chain_spec.name()); info!("Node name: {}", config.name); info!("Roles: {:?}", config.roles); - let mut runtime = Runtime::new()?; + let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build() + .map_err(|e| format!("{:?}", e))?; let executor = runtime.executor(); - match config.roles == ServiceRoles::LIGHT { - true => run_until_exit(&mut runtime, service::Factory::new_light(config, executor)?, exit)?, - false => run_until_exit(&mut runtime, service::Factory::new_full(config, executor)?, exit)?, - } + match config.roles { + ServiceRoles::LIGHT => run_until_exit( + runtime, + service::Factory::new_light(config, executor).map_err(|e| format!("{:?}", e))?, + exit + ), + _ => run_until_exit( + runtime, + service::Factory::new_full(config, executor).map_err(|e| format!("{:?}", e))?, + exit + ), + }.map_err(|e| format!("{:?}", e)) } - } - Ok(()) + ).map_err(Into::into).map(|_| ()) } fn run_until_exit( - runtime: &mut Runtime, + mut runtime: Runtime, service: T, e: E, ) -> error::Result<()> @@ -172,5 +123,14 @@ fn run_until_exit( let _ = runtime.block_on(e.into_exit()); exit_send.fire(); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + drop(service); + + // TODO [andre]: timeout this future #1318 + let _ = runtime.shutdown_on_idle().wait(); + Ok(()) } diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 393b2a480ceb79efa478e765972a4dfdb10ebc8a..dd03b25bb93491167f3e3419f797286e0bd2a432 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,19 +19,24 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use std::sync::Arc; -use transaction_pool::{self, txpool::{Pool as TransactionPool}}; +use std::time::Duration; + +use client; +use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; +use grandpa; +use node_executor; +use primitives::{Pair as _Pair, ed25519::Pair}; +use node_primitives::Block; use node_runtime::{GenesisConfig, RuntimeApi}; -use node_primitives::{Block, InherentData}; use substrate_service::{ FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, - FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, TaskExecutor + FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, TaskExecutor, }; -use node_executor; -use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; -use primitives::ed25519::Pair; -use client; -use std::time::Duration; -use grandpa; +use transaction_pool::{self, txpool::{Pool as TransactionPool}}; +use inherents::InherentDataProviders; +use network::construct_simple_protocol; +use substrate_service::construct_service_factory; +use log::info; construct_simple_protocol! { /// Demo protocol attachment for substrate. @@ -40,23 +45,17 @@ construct_simple_protocol! { /// Node specific configuration pub struct NodeConfig { - /// should run as a grandpa authority - pub grandpa_authority: bool, - /// should run as a grandpa authority only, don't validate as usual - pub grandpa_authority_only: bool, /// grandpa connection to import block - - // FIXME: rather than putting this on the config, let's have an actual intermediate setup state - // https://github.com/paritytech/substrate/issues/1134 + // FIXME #1134 rather than putting this on the config, let's have an actual intermediate setup state pub grandpa_import_setup: Option<(Arc>, grandpa::LinkHalfForService)>, + inherent_data_providers: InherentDataProviders, } impl Default for NodeConfig where F: substrate_service::ServiceFactory { fn default() -> NodeConfig { NodeConfig { - grandpa_authority: false, - grandpa_authority_only: false, grandpa_import_setup: None, + inherent_data_providers: InherentDataProviders::new(), } } } @@ -77,89 +76,83 @@ construct_service_factory! { { |config: FactoryFullConfiguration, executor: TaskExecutor| FullComponents::::new(config, executor) }, AuthoritySetup = { - |mut service: Self::FullService, executor: TaskExecutor, key: Option>| { + |mut service: Self::FullService, executor: TaskExecutor, local_key: Option>| { let (block_import, link_half) = service.config.custom.grandpa_import_setup.take() .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - let local_key = if let Some(key) = key { - if !service.config.custom.grandpa_authority_only { - info!("Using authority key {}", key.public()); - let proposer = Arc::new(substrate_service::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }); - - let client = service.client(); - executor.spawn(start_aura( - SlotDuration::get_or_compute(&*client)?, - key.clone(), - client, - block_import.clone(), - proposer, - service.network(), - )); - } - - if service.config.custom.grandpa_authority { - info!("Running Grandpa session as Authority {}", key.public()); - Some(key) - } else { - None - } - } else { - None - }; - - let voter = grandpa::run_grandpa( + if let Some(ref key) = local_key { + info!("Using authority key {}", key.public()); + let proposer = Arc::new(substrate_basic_authorship::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }); + + let client = service.client(); + executor.spawn(start_aura( + SlotDuration::get_or_compute(&*client)?, + key.clone(), + client, + block_import.clone(), + proposer, + service.network(), + service.on_exit(), + service.config.custom.inherent_data_providers.clone(), + )?); + + info!("Running Grandpa session as Authority {}", key.public()); + } + + executor.spawn(grandpa::run_grandpa( grandpa::Config { local_key, - gossip_duration: Duration::new(4, 0), // FIXME: make this available through chainspec? + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::new(4, 0), + justification_period: 4096, name: Some(service.config.name.clone()) }, link_half, grandpa::NetworkBridge::new(service.network()), - )?; - - executor.spawn(voter); + service.config.custom.inherent_data_providers.clone(), + service.on_exit(), + )?); Ok(service) } }, LightService = LightComponents { |config, executor| >::new(config, executor) }, - FullImportQueue = AuraImportQueue< - Self::Block, - grandpa::BlockImportForService, - NothingExtra, - ::consensus::InherentProducingFn, - > + FullImportQueue = AuraImportQueue { |config: &mut FactoryFullConfiguration , client: Arc>| { let slot_duration = SlotDuration::get_or_compute(&*client)?; - let (block_import, link_half) = grandpa::block_import::<_, _, _, RuntimeApi, FullClient>(client.clone(), client)?; + let (block_import, link_half) = + grandpa::block_import::<_, _, _, RuntimeApi, FullClient>( + client.clone(), client.clone() + )?; let block_import = Arc::new(block_import); + let justification_import = block_import.clone(); config.custom.grandpa_import_setup = Some((block_import.clone(), link_half)); - Ok(import_queue( + import_queue( slot_duration, block_import, - NothingExtra, - ::consensus::make_basic_inherent as _, - )) - }}, - LightImportQueue = AuraImportQueue< - Self::Block, - LightClient, - NothingExtra, - ::consensus::InherentProducingFn, - > - { |ref mut config, client: Arc>| - Ok(import_queue( - SlotDuration::get_or_compute(&*client)?, + Some(justification_import), client, NothingExtra, - ::consensus::make_basic_inherent as _, - )) + config.custom.inherent_data_providers.clone(), + ).map_err(Into::into) + }}, + LightImportQueue = AuraImportQueue + { |config: &FactoryFullConfiguration, client: Arc>| { + import_queue( + SlotDuration::get_or_compute(&*client)?, + client.clone(), + None, + client, + NothingExtra, + config.custom.inherent_data_providers.clone(), + ).map_err(Into::into) + } }, } } diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml index 98cb1650ee2d8c669b7b68dc63d7183ee46c17fe..3e0f618bc78e699ab03f477345abef7369babba2 100644 --- a/node/executor/Cargo.toml +++ b/node/executor/Cargo.toml @@ -3,33 +3,35 @@ name = "node-executor" version = "0.1.0" authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." +edition = "2018" [dependencies] -hex-literal = "0.1" -trie-root = { git = "https://github.com/paritytech/trie" } -parity-codec = "2.1" -sr-io = { path = "../../core/sr-io" } -substrate-state-machine = { path = "../../core/state-machine" } +trie-root = "0.11" +parity-codec = "3.2" +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +state_machine = { package = "substrate-state-machine", path = "../../core/state-machine" } substrate-executor = { path = "../../core/executor" } -substrate-primitives = { path = "../../core/primitives" } -substrate-trie = { path = "../../core/trie" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +trie = { package = "substrate-trie", path = "../../core/trie" } node-primitives = { path = "../primitives" } node-runtime = { path = "../runtime" } [dev-dependencies] -substrate-keyring = { path = "../../core/keyring" } -sr-primitives = { path = "../../core/sr-primitives" } -srml-support = { path = "../../srml/support" } -srml-balances = { path = "../../srml/balances" } -srml-session = { path = "../../srml/session" } -srml-staking = { path = "../../srml/staking" } -srml-system = { path = "../../srml/system" } -srml-consensus = { path = "../../srml/consensus" } -srml-timestamp = { path = "../../srml/timestamp" } -srml-treasury = { path = "../../srml/treasury" } -srml-contract = { path = "../../srml/contract" } -srml-grandpa = { path = "../../srml/grandpa" } -wabt = "0.7" +keyring = { package = "substrate-keyring", path = "../../core/keyring" } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives" } +runtime_support = { package = "srml-support", path = "../../srml/support" } +balances = { package = "srml-balances", path = "../../srml/balances" } +session = { package = "srml-session", path = "../../srml/session" } +staking = { package = "srml-staking", path = "../../srml/staking" } +system = { package = "srml-system", path = "../../srml/system" } +consensus = { package = "srml-consensus", path = "../../srml/consensus" } +timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } +treasury = { package = "srml-treasury", path = "../../srml/treasury" } +contract = { package = "srml-contract", path = "../../srml/contract" } +grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } +indices = { package = "srml-indices", path = "../../srml/indices" } +fees = { package = "srml-fees", path = "../../srml/fees" } +wabt = "~0.7.4" [features] benchmarks = [] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 632230133a3d4a060bc73562e9cc1c65fe6cc3f2..84b2de336ed5809d563030d17230cdceeaedd6cc 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,33 +19,10 @@ #![cfg_attr(feature = "benchmarks", feature(test))] -extern crate node_runtime; -#[macro_use] extern crate substrate_executor; -#[cfg_attr(test, macro_use)] extern crate substrate_primitives as primitives; - #[cfg(feature = "benchmarks")] extern crate test; -#[cfg(test)] extern crate substrate_keyring as keyring; -#[cfg(test)] extern crate sr_primitives as runtime_primitives; -#[cfg(test)] extern crate srml_support as runtime_support; -#[cfg(test)] extern crate srml_balances as balances; -#[cfg(test)] extern crate srml_session as session; -#[cfg(test)] extern crate srml_staking as staking; -#[cfg(test)] extern crate srml_system as system; -#[cfg(test)] extern crate srml_consensus as consensus; -#[cfg(test)] extern crate srml_timestamp as timestamp; -#[cfg(test)] extern crate srml_treasury as treasury; -#[cfg(test)] extern crate srml_contract as contract; -#[cfg(test)] extern crate srml_grandpa as grandpa; -#[cfg(test)] extern crate node_primitives; -#[cfg(test)] extern crate parity_codec as codec; -#[cfg(test)] extern crate sr_io as runtime_io; -#[cfg(test)] extern crate substrate_trie as trie; -#[cfg(test)] extern crate substrate_state_machine as state_machine; -#[cfg(test)] #[macro_use] extern crate hex_literal; -#[cfg(test)] extern crate wabt; - pub use substrate_executor::NativeExecutor; +use substrate_executor::native_executor_instance; native_executor_instance!(pub Executor, node_runtime::api::dispatch, node_runtime::native_version, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm")); #[cfg(test)] @@ -53,48 +30,67 @@ mod tests { use runtime_io; use super::Executor; use substrate_executor::{WasmExecutor, NativeExecutionDispatch}; - use codec::{Encode, Decode, Joiner}; - use keyring::Keyring; - use runtime_support::{Hashable, StorageValue, StorageMap}; + use parity_codec::{Encode, Decode, Joiner}; + use keyring::{AccountKeyring, AuthorityKeyring}; + use runtime_support::{Hashable, StorageValue, StorageMap, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities}; - use primitives::{twox_128, Blake2Hasher, ChangesTrieConfiguration, - ed25519::{Public, Pair}}; + use primitives::{twox_128, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, + NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; - use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT}; + use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; use runtime_primitives::{generic, generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use {balances, staking, session, system, consensus, timestamp, treasury, contract}; + use {balances, indices, session, system, staking, consensus, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, - SystemConfig, GrandpaConfig, Event, Log}; + SystemConfig, GrandpaConfig, IndicesConfig, FeesConfig, Event, Log}; use wabt; + use primitives::map; const BLOATY_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm"); const COMPACT_CODE: &[u8] = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"); const GENESIS_HASH: [u8; 32] = [69u8; 32]; fn alice() -> AccountId { - AccountId::from(Keyring::Alice.to_raw_public()) + AccountKeyring::Alice.into() } fn bob() -> AccountId { - AccountId::from(Keyring::Bob.to_raw_public()) + AccountKeyring::Bob.into() } fn charlie() -> AccountId { - AccountId::from(Keyring::Charlie.to_raw_public()) + AccountKeyring::Charlie.into() + } + + fn dave() -> AccountId { + AccountKeyring::Dave.into() + } + + fn eve() -> AccountId { + AccountKeyring::Eve.into() + } + + fn ferdie() -> AccountId { + AccountKeyring::Ferdie.into() } fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { match xt.signed { Some((signed, index)) => { let era = Era::mortal(256, 0); - let payload = (index, xt.function, era, GENESIS_HASH); - let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap()); - let signature = pair.sign(&payload.encode()).into(); + let payload = (index.into(), xt.function, era, GENESIS_HASH); + let key = AccountKeyring::from_public(&signed).unwrap(); + let signature = payload.using_encoded(|b| { + if b.len() > 256 { + key.sign(&runtime_io::blake2_256(b)) + } else { + key.sign(b) + } + }).into(); UncheckedExtrinsic { - signature: Some((balances::address::Address::Id(signed), signature, payload.0, era)), + signature: Some((indices::address::Address::Id(signed), signature, payload.0, era)), function: payload.1, } } @@ -108,7 +104,7 @@ mod tests { fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { signed: Some((alice(), 0)), - function: Call::Balances(balances::Call::transfer::(bob().into(), 69.into())), + function: Call::Balances(balances::Call::transfer::(bob().into(), 69)), }) } @@ -117,68 +113,104 @@ mod tests { } fn executor() -> ::substrate_executor::NativeExecutor { - ::substrate_executor::NativeExecutor::new() + ::substrate_executor::NativeExecutor::new(None) } #[test] fn panic_execution_with_foreign_code_gives_error() { - let mut t = TestExternalities::::new(map![ + let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = executor().call(&mut t, 8, BLOATY_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_initialise_block", + &vec![].and(&from_block_number(1u64)), + true, + None, + ).0; assert!(r.is_ok()); - let v = executor().call(&mut t, 8, BLOATY_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); - let r = ApplyResult::decode(&mut &v[..]).unwrap(); + let v = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0.unwrap(); + let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { - let mut t = TestExternalities::::new(map![ + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = executor().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_initialise_block", + &vec![].and(&from_block_number(1u64)), + true, + None, + ).0; assert!(r.is_ok()); - let v = executor().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0.unwrap(); - let r = ApplyResult::decode(&mut &v[..]).unwrap(); + let v = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0.unwrap(); + let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { - let mut t = TestExternalities::::new(map![ + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = executor().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_initialise_block", + &vec![].and(&from_block_number(1u64)), + true, + None, + ).0; assert!(r.is_ok()); - let r = executor().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0; assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { @@ -189,21 +221,33 @@ mod tests { #[test] fn successful_execution_with_foreign_code_gives_ok() { - let mut t = TestExternalities::::new(map![ + let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = executor().call(&mut t, 8, BLOATY_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64)), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_initialise_block", + &vec![].and(&from_block_number(1u64)), + true, + None, + ).0; assert!(r.is_ok()); - let r = executor().call(&mut t, 8, BLOATY_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true).0; + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0; assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { @@ -212,10 +256,9 @@ mod tests { }); } - fn new_test_ext(support_changes_trie: bool) -> TestExternalities { - use keyring::Keyring::*; - let three = [3u8; 32].into(); - TestExternalities::new(GenesisConfig { + fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { + let three = AccountId::from_raw([3u8; 32]); + TestExternalities::new_with_code(code, GenesisConfig { consensus: Some(Default::default()), system: Some(SystemConfig { changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { @@ -224,26 +267,40 @@ mod tests { }) } else { None }, ..Default::default() }), + indices: Some(IndicesConfig { + ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], + }), balances: Some(BalancesConfig { balances: vec![ (alice(), 111), + (bob(), 100), (charlie(), 100_000_000), + (dave(), 111), + (eve(), 101), + (ferdie(), 100), ], - transaction_base_fee: 1, - transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - reclaim_rebate: 0, + vesting: vec![], }), session: Some(SessionConfig { session_length: 2, - validators: vec![One.to_raw_public().into(), Two.to_raw_public().into(), three], + validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three], + keys: vec![ + (alice(), AuthorityKeyring::Alice.into()), + (bob(), AuthorityKeyring::Bob.into()), + (charlie(), AuthorityKeyring::Charlie.into()) + ] }), staking: Some(StakingConfig { sessions_per_era: 2, current_era: 0, - intentions: vec![alice(), bob(), Charlie.to_raw_public().into()], + stakers: vec![ + (dave(), alice(), 111, staking::StakerStatus::Validator), + (eve(), bob(), 100, staking::StakerStatus::Validator), + (ferdie(), charlie(), 100, staking::StakerStatus::Validator) + ], validator_count: 3, minimum_validator_count: 0, bonding_duration: 0, @@ -252,6 +309,7 @@ mod tests { current_offline_slash: 0, current_session_reward: 0, offline_slash_grace: 0, + invulnerables: vec![alice(), bob(), charlie()], }), democracy: Some(Default::default()), council_seats: Some(Default::default()), @@ -259,121 +317,155 @@ mod tests { timestamp: Some(Default::default()), treasury: Some(Default::default()), contract: Some(Default::default()), - upgrade_key: Some(Default::default()), + sudo: Some(Default::default()), grandpa: Some(GrandpaConfig { - authorities: vec![ // set these so no GRANDPA events fire when session changes - (Alice.to_raw_public().into(), 1), - (Bob.to_raw_public().into(), 1), - (Charlie.to_raw_public().into(), 1), - ], + authorities: vec![], + }), + fees: Some(FeesConfig { + transaction_base_fee: 1, + transaction_byte_fee: 0, }), }.build_storage().unwrap().0) } - fn changes_trie_log(changes_root: Hash) -> Log { - Log::from(system::RawLog::ChangesTrieRoot::(changes_root)) - } - fn construct_block( + env: &mut TestExternalities, number: BlockNumber, parent_hash: Hash, - state_root: Hash, - logs: Vec, - extrinsics: Vec + extrinsics: Vec, ) -> (Vec, Hash) { use trie::ordered_trie_root; + // sign extrinsics. let extrinsics = extrinsics.into_iter().map(sign).collect::>(); - let extrinsics_root = ordered_trie_root::(extrinsics.iter() - .map(Encode::encode)) - .to_fixed_bytes() - .into(); - let mut digest = generic::Digest::::default(); - for item in logs { - digest.push(item); - } + // calculate the header fields that we can. + let extrinsics_root = ordered_trie_root::( + extrinsics.iter().map(Encode::encode) + ).to_fixed_bytes() + .into(); let header = Header { parent_hash, number, - state_root, extrinsics_root, - digest, + state_root: Default::default(), + digest: Default::default(), + }; + + // execute the block to get the real header. + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( + env, + "Core_initialise_block", + &header.encode(), + true, + None, + ).0.unwrap(); + + for i in extrinsics.iter() { + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( + env, + "BlockBuilder_apply_extrinsic", + &i.encode(), + true, + None, + ).0.unwrap(); + } + + let header = match Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( + env, + "BlockBuilder_finalise_block", + &[0u8;0], + true, + None, + ).0.unwrap() { + NativeOrEncoded::Native(_) => unreachable!(), + NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), }; - let hash = header.blake2_256(); + let hash = header.blake2_256(); (Block { header, extrinsics }.encode(), hash.into()) } - fn block1(support_changes_trie: bool) -> (Vec, Hash) { + fn changes_trie_block() -> (Vec, Hash) { construct_block( + &mut new_test_ext(COMPACT_CODE, true), 1, GENESIS_HASH.into(), - if support_changes_trie { - hex!("1a7758d96d7353732f3054a3dacb18f04f42fc48f6706378d6f7be744c6022f1").into() - } else { - hex!("1cf270c8a484df4931af562f7afdc9f44d99ae1bd35fe30fbd2cf3c1be2e933b").into() - }, - if support_changes_trie { - vec![changes_trie_log( - hex!("cda28e5c630db8eb0e4309b58ce504597c6cbb59bda43fd65e96bb2be73a4586").into(), - )] - } else { - vec![] - }, vec![ CheckedExtrinsic { signed: None, - function: Call::Timestamp(timestamp::Call::set(42.into())), + function: Call::Timestamp(timestamp::Call::set(42)), }, CheckedExtrinsic { signed: Some((alice(), 0)), - function: Call::Balances(balances::Call::transfer(bob().into(), 69.into())), + function: Call::Balances(balances::Call::transfer(bob().into(), 69)), }, ] ) } - fn block2() -> (Vec, Hash) { - construct_block( + // block 1 and 2 must be created together to ensure transactions are only signed once (since they + // are not guaranteed to be deterministic) and to ensure that the correct state is propagated + // from block1's execution to block2 to derive the correct storage_root. + fn blocks() -> ((Vec, Hash), (Vec, Hash)) { + let mut t = new_test_ext(COMPACT_CODE, false); + let block1 = construct_block( + &mut t, + 1, + GENESIS_HASH.into(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(timestamp::Call::set(42)), + }, + CheckedExtrinsic { + signed: Some((alice(), 0)), + function: Call::Balances(balances::Call::transfer(bob().into(), 69)), + }, + ] + ); + let block2 = construct_block( + &mut t, 2, - block1(false).1, - hex!("a208e27269f8a17e7f7cf9513396d3579066df10a853e030345847ec96593c2e").into(), - vec![ // session changes here, so we add a grandpa change signal log. - Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![ - (Keyring::One.to_raw_public().into(), 1), - (Keyring::Two.to_raw_public().into(), 1), - ([3u8; 32].into(), 1), - ])) - ], + block1.1.clone(), vec![ CheckedExtrinsic { signed: None, - function: Call::Timestamp(timestamp::Call::set(52.into())), + function: Call::Timestamp(timestamp::Call::set(52)), }, CheckedExtrinsic { signed: Some((bob(), 0)), - function: Call::Balances(balances::Call::transfer(alice().into(), 5.into())), + function: Call::Balances(balances::Call::transfer(alice().into(), 5)), }, CheckedExtrinsic { signed: Some((alice(), 1)), - function: Call::Balances(balances::Call::transfer(bob().into(), 15.into())), + function: Call::Balances(balances::Call::transfer(bob().into(), 15)), } ] - ) + ); + + // let mut digest = generic::Digest::::default(); + // digest.push(Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![ + // (Keyring::Charlie.to_raw_public().into(), 1), + // (Keyring::Bob.to_raw_public().into(), 1), + // (Keyring::Alice.to_raw_public().into(), 1), + // ]))); + let digest = generic::Digest::::default(); // TODO test this + assert_eq!(Header::decode(&mut &block2.0[..]).unwrap().digest, digest); + + (block1, block2) } - fn block1big() -> (Vec, Hash) { + fn big_block() -> (Vec, Hash) { construct_block( + &mut new_test_ext(COMPACT_CODE, false), 1, GENESIS_HASH.into(), - hex!("a506a69fefa4dc1be6838b68dc6e5799bd5fec545ef890cadac20edc0254d37a").into(), - vec![], vec![ CheckedExtrinsic { signed: None, - function: Call::Timestamp(timestamp::Call::set(42.into())), + function: Call::Timestamp(timestamp::Call::set(42)), }, CheckedExtrinsic { signed: Some((alice(), 0)), @@ -385,27 +477,33 @@ mod tests { #[test] fn full_native_block_import_works() { - let mut t = new_test_ext(false); + let mut t = new_test_ext(COMPACT_CODE, false); - executor().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1(false).0, true).0.unwrap(); + let (block1, block2) = blocks(); + + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_execute_block", + &block1.0, + true, + None, + ).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 41); - assert_eq!(Balances::total_balance(&bob()), 69); + // block1 transfers from alice 69 to bob. + // -1 is the default fee + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1); + assert_eq!(Balances::total_balance(&bob()), 100 + 69); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: Event::system(system::Event::ExtrinsicSuccess) }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::balances(balances::RawEvent::NewAccount(bob(), 2, balances::NewAccountOutcome::NoHint)) - }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::balances(balances::RawEvent::Transfer( - hex!["d172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f"].into(), - hex!["d7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9"].into(), + alice().into(), + bob().into(), 69, 0 )) @@ -425,15 +523,28 @@ mod tests { EventRecord { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Rollover(0)) + }, + EventRecord { + phase: Phase::Finalization, + event: Event::fees(fees::RawEvent::Charged(1, 1)) } ]); }); - executor().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2().0, true).0.unwrap(); + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_execute_block", + &block2.0, + true, + None, + ).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 30); - assert_eq!(Balances::total_balance(&bob()), 78); + // bob sends 5, alice sends 15 | bob += 10, alice -= 10 + // 111 - 69 - 1 - 10 - 1 = 30 + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); + // 100 + 69 + 10 - 1 = 178 + assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), @@ -443,8 +554,8 @@ mod tests { phase: Phase::ApplyExtrinsic(1), event: Event::balances( balances::RawEvent::Transfer( - hex!["d7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9"].into(), - hex!["d172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f"].into(), + bob().into(), + alice().into(), 5, 0 ) @@ -458,8 +569,8 @@ mod tests { phase: Phase::ApplyExtrinsic(2), event: Event::balances( balances::RawEvent::Transfer( - hex!["d172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f"].into(), - hex!["d7568e5f0a7eda67a82691ff379ac4bba4f9c9b859fe779b5d46363b61ad2db9"].into(), + alice().into(), + bob().into(), 15, 0 ) @@ -473,29 +584,33 @@ mod tests { phase: Phase::Finalization, event: Event::session(session::RawEvent::NewSession(1)) }, + // EventRecord { // TODO: this might be wrong. + // phase: Phase::Finalization, + // event: Event::grandpa(::grandpa::RawEvent::NewAuthorities(vec![ + // (Keyring::Charlie.to_raw_public().into(), 1), + // (Keyring::Bob.to_raw_public().into(), 1), + // (Keyring::Alice.to_raw_public().into(), 1), + // ])), + // }, EventRecord { phase: Phase::Finalization, - event: Event::staking(staking::RawEvent::Reward(0)) + event: Event::treasury(treasury::RawEvent::Spending(0)) }, EventRecord { phase: Phase::Finalization, - event: Event::grandpa(::grandpa::RawEvent::NewAuthorities(vec![ - (Keyring::One.to_raw_public().into(), 1), - (Keyring::Two.to_raw_public().into(), 1), - ([3u8; 32].into(), 1), - ])), + event: Event::treasury(treasury::RawEvent::Burnt(0)) }, EventRecord { phase: Phase::Finalization, - event: Event::treasury(treasury::RawEvent::Spending(0)) + event: Event::treasury(treasury::RawEvent::Rollover(0)) }, EventRecord { phase: Phase::Finalization, - event: Event::treasury(treasury::RawEvent::Burnt(0)) + event: Event::fees(fees::RawEvent::Charged(1, 1)) }, EventRecord { phase: Phase::Finalization, - event: Event::treasury(treasury::RawEvent::Rollover(0)) + event: Event::fees(fees::RawEvent::Charged(2, 1)) } ]); }); @@ -503,20 +618,27 @@ mod tests { #[test] fn full_wasm_block_import_works() { - let mut t = new_test_ext(false); + let mut t = new_test_ext(COMPACT_CODE, false); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1(false).0).unwrap(); + let (block1, block2) = blocks(); + + WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 41); - assert_eq!(Balances::total_balance(&bob()), 69); + // block1 transfers from alice 69 to bob. + // -1 is the default fee + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1); + assert_eq!(Balances::total_balance(&bob()), 100 + 69); }); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2().0).unwrap(); + WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2.0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 30); - assert_eq!(Balances::total_balance(&bob()), 78); + // bob sends 5, alice sends 15 | bob += 10, alice -= 10 + // 111 - 69 - 1 - 10 - 1 = 30 + assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1); + // 100 + 69 + 10 - 1 = 178 + assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1); }); } @@ -535,6 +657,8 @@ mod tests { (import "env" "ext_input_size" (func $ext_input_size (result i32))) (import "env" "ext_input_copy" (func $ext_input_copy (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) + (func (export "deploy") + ) (func (export "call") (block $fail ;; fail if ext_input_size != 4 @@ -602,95 +726,61 @@ mod tests { ) "#; - /// Convert a byte slice to a string with hex values. - /// Convert a byte slice to a string with hex values. - /// - /// Each value is preceeded with a `\` character. - fn escaped_bytestring(bytes: &[u8]) -> String { - use std::fmt::Write; - let mut result = String::new(); - for b in bytes { - write!(result, "\\{:02x}", b).unwrap(); - } - result - } - - /// Create a constructor for the specified code. - /// - /// When constructor is executed, it will call `ext_return` with code that - /// specified in `child_bytecode`. - fn code_ctor(child_bytecode: &[u8]) -> String { - format!( - r#" - (module - ;; ext_return(data_ptr: u32, data_len: u32) -> ! - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (call $ext_return - (i32.const 4) - (i32.const {code_len}) - ) - ;; ext_return is diverging, i.e. doesn't return. - unreachable - ) - (data (i32.const 4) "{escaped_bytecode}") - ) - "#, - escaped_bytecode = escaped_bytestring(child_bytecode), - code_len = child_bytecode.len(), - ) - } - #[test] fn deploying_wasm_contract_should_work() { - let mut t = new_test_ext(false); - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - let code_ctor_transfer = wabt::wat2wasm(&code_ctor(&code_transfer)).unwrap(); + let transfer_code = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + let transfer_ch = ::Hashing::hash(&transfer_code); let addr = ::DetermineContractAddress::contract_address_for( - &code_ctor_transfer, + &transfer_ch, &[], &charlie(), ); let b = construct_block( + &mut new_test_ext(COMPACT_CODE, false), 1, GENESIS_HASH.into(), - hex!("3af4e1ba0769122b1e92b138fecf7ce8bb2fe4f2a65fba3b423f87942f1ba8c8").into(), - vec![], vec![ CheckedExtrinsic { signed: None, - function: Call::Timestamp(timestamp::Call::set(42.into())), + function: Call::Timestamp(timestamp::Call::set(42)), }, CheckedExtrinsic { signed: Some((charlie(), 0)), function: Call::Contract( - contract::Call::create::(10.into(), 10_000.into(), code_ctor_transfer, Vec::new()) + contract::Call::put_code::(10_000, transfer_code) ), }, CheckedExtrinsic { signed: Some((charlie(), 1)), function: Call::Contract( - contract::Call::call::(addr, 10.into(), 10_000.into(), vec![0x00, 0x01, 0x02, 0x03]) + contract::Call::create::(10, 10_000, transfer_ch, Vec::new()) + ), + }, + CheckedExtrinsic { + signed: Some((charlie(), 2)), + function: Call::Contract( + contract::Call::call::(indices::address::Address::Id(addr.clone()), 10, 10_000, vec![0x00, 0x01, 0x02, 0x03]) ), }, ] ); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &b.0).unwrap(); + let mut t = new_test_ext(COMPACT_CODE, false); + + WasmExecutor::new().call(&mut t, 8, COMPACT_CODE,"Core_execute_block", &b.0).unwrap(); runtime_io::with_externalities(&mut t, || { // Verify that the contract constructor worked well and code of TRANSFER contract is actually deployed. - assert_eq!(&contract::CodeOf::::get(addr), &code_transfer); + assert_eq!(&contract::CodeHashOf::::get(addr).unwrap(), &transfer_ch); }); } #[test] fn wasm_big_block_import_fails() { - let mut t = new_test_ext(false); + let mut t = new_test_ext(COMPACT_CODE, false); assert!( WasmExecutor::new().call( @@ -698,81 +788,79 @@ mod tests { 8, COMPACT_CODE, "Core_execute_block", - &block1big().0 + &big_block().0 ).is_err() ); } #[test] fn native_big_block_import_succeeds() { - let mut t = new_test_ext(false); + let mut t = new_test_ext(COMPACT_CODE, false); - Executor::new().call( + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( &mut t, - 8, - COMPACT_CODE, "Core_execute_block", - &block1big().0, - true + &big_block().0, + true, + None, ).0.unwrap(); } #[test] fn native_big_block_import_fails_on_fallback() { - let mut t = new_test_ext(false); + let mut t = new_test_ext(COMPACT_CODE, false); assert!( - Executor::new().call( + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( &mut t, - 8, - COMPACT_CODE, "Core_execute_block", - &block1big().0, - false + &big_block().0, + false, + None, ).0.is_err() ); } #[test] fn panic_execution_gives_error() { - let mut t = TestExternalities::::new(map![ + let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm"); + let mut t = TestExternalities::::new_with_code(foreign_code, map![ twox_128(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![70u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm"); - let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "Core_initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } #[test] fn successful_execution_gives_ok() { - let mut t = TestExternalities::::new(map![ + let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"); + let mut t = TestExternalities::::new_with_code(foreign_code, map![ twox_128(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32] + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(&>::key_for(0)).to_vec() => vec![0u8; 32], + twox_128(>::key()).to_vec() => vec![0u8; 16], + twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"); - let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "Core_initialise_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialise_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor::new().call(&mut t, 8, &foreign_code[..], "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Ok(ApplyOutcome::Success)); @@ -784,16 +872,28 @@ mod tests { #[test] fn full_native_block_import_works_with_changes_trie() { - let mut t = new_test_ext(true); - Executor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1(true).0, true).0.unwrap(); + let block1 = changes_trie_block(); + let block_data = block1.0; + let block = Block::decode(&mut &block_data[..]).unwrap(); + + let mut t = new_test_ext(COMPACT_CODE, true); + Executor::new(None).call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_execute_block", + &block.encode(), + true, + None, + ).0.unwrap(); assert!(t.storage_changes_root(Default::default(), 0).is_some()); } #[test] fn full_wasm_block_import_works_with_changes_trie() { - let mut t = new_test_ext(true); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1(true).0).unwrap(); + let block1 = changes_trie_block(); + + let mut t = new_test_ext(COMPACT_CODE, true); + WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); assert!(t.storage_changes_root(Default::default(), 0).is_some()); } @@ -805,10 +905,12 @@ mod tests { #[bench] fn wasm_execute_block(b: &mut Bencher) { + let (block1, block2) = blocks(); + b.iter(|| { - let mut t = new_test_ext(false); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1(false).0).unwrap(); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2().0).unwrap(); + let mut t = new_test_ext(COMPACT_CODE, false); + WasmExecutor::new().call(&mut t, "Core_execute_block", &block1.0).unwrap(); + WasmExecutor::new().call(&mut t, "Core_execute_block", &block2.0).unwrap(); }); } } diff --git a/node/primitives/Cargo.toml b/node/primitives/Cargo.toml index a28714f6ee040dee93235b8462a3512e741f56c7..b7da80c9a879e3b03f6d02758334b9828f02fea5 100644 --- a/node/primitives/Cargo.toml +++ b/node/primitives/Cargo.toml @@ -2,28 +2,29 @@ name = "node-primitives" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } [dev-dependencies] substrate-serializer = { path = "../../core/serializer" } -pretty_assertions = "0.4" +pretty_assertions = "0.5" [features] default = ["std"] std = [ "parity-codec-derive/std", "parity-codec/std", - "substrate-primitives/std", - "sr-std/std", - "sr-primitives/std", + "primitives/std", + "rstd/std", + "runtime_primitives/std", "serde_derive", - "serde/std", + "serde", ] diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index e2336acafdc482e92b53c84e47bdcbfc305251e7..8c23e5d32bf25bc9515e8bfd1847f0b5732143f7 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,31 +21,19 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate sr_std as rstd; -extern crate sr_primitives as runtime_primitives; -extern crate substrate_primitives as primitives; - -use rstd::prelude::*; -use runtime_primitives::generic; -#[cfg(feature = "std")] -use primitives::bytes; -use runtime_primitives::traits::{BlakeTwo256, self}; - -pub use runtime_primitives::BasicInherentData as InherentData; +use runtime_primitives::{ + generic, traits::{Verify, BlakeTwo256}, OpaqueExtrinsic +}; /// An index to a block. pub type BlockNumber = u64; -/// Alias to Ed25519 pubkey that identifies an account on the chain. This will almost -/// certainly continue to be the same as the substrate's `AuthorityId`. -pub type AccountId = ::primitives::H256; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = primitives::sr25519::Signature; + +/// 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; /// The type for looking up accounts. We don't expect more than 4 billion of them, but you /// never know... @@ -56,7 +44,10 @@ pub type Balance = u128; /// The Ed25519 pub key of an session that belongs to an authority of the chain. This is /// exactly equivalent to what the substrate calls an "authority". -pub type SessionKey = primitives::AuthorityId; +pub type AuthorityId = ::Signer; + +/// Alias to 512-bit hash when used in the context of a session signature on the chain. +pub type AuthoritySignature = primitives::ed25519::Signature; /// Index of a transaction in the chain. pub type Index = u64; @@ -64,26 +55,16 @@ pub type Index = u64; /// A hash of some data used by the chain. pub type Hash = primitives::H256; -/// Alias to 512-bit hash when used in the context of a signature on the chain. -pub type Signature = runtime_primitives::Ed25519Signature; - /// A timestamp: seconds since the unix epoch. pub type Timestamp = u64; /// Header type. -pub type Header = generic::Header>; +/// +pub type Header = generic::Header>; /// Block type. pub type Block = generic::Block; /// Block ID. pub type BlockId = generic::BlockId; /// Opaque, encoded, unchecked extrinsic. -#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -pub struct UncheckedExtrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl traits::Extrinsic for UncheckedExtrinsic { - fn is_signed(&self) -> Option { - None - } -} +pub type UncheckedExtrinsic = OpaqueExtrinsic; diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml index 65c2faa01ffa0e6da0e88671c780be5cf6da855b..6a5d33468736f5e316c3eceba48bff78194cad17 100644 --- a/node/runtime/Cargo.toml +++ b/node/runtime/Cargo.toml @@ -2,63 +2,75 @@ name = "node-runtime" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -rustc-hex = "1.0" -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +integer-sqrt = { version = "0.1.2" } safe-mix = { version = "1.0", default-features = false } -parity-codec = "2.1" -parity-codec-derive = "2.1" -sr-std = { path = "../../core/sr-std" } -srml-support = { path = "../../srml/support" } -substrate-primitives = { path = "../../core/primitives" } -substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false } -substrate-client = { path = "../../core/client" } -substrate-keyring = { path = "../../core/keyring" } -srml-aura = { path = "../../srml/aura" } -srml-balances = { path = "../../srml/balances" } -srml-consensus = { path = "../../srml/consensus" } -srml-contract = { path = "../../srml/contract" } -srml-council = { path = "../../srml/council" } -srml-democracy = { path = "../../srml/democracy" } -srml-executive = { path = "../../srml/executive" } -srml-grandpa = { path = "../../srml/grandpa" } -sr-primitives = { path = "../../core/sr-primitives" } -srml-session = { path = "../../srml/session" } -srml-staking = { path = "../../srml/staking" } -srml-system = { path = "../../srml/system" } -srml-timestamp = { path = "../../srml/timestamp" } -srml-treasury = { path = "../../srml/treasury" } -srml-upgrade-key = { path = "../../srml/upgrade-key" } -sr-version = { path = "../../core/sr-version" } -node-primitives = { path = "../primitives" } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +substrate-primitives = { path = "../../core/primitives", default-features = false } +client = { package = "substrate-client", path = "../../core/client", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +version = { package = "sr-version", path = "../../core/sr-version", default-features = false } +support = { package = "srml-support", path = "../../srml/support", default-features = false } +aura = { package = "srml-aura", path = "../../srml/aura", default-features = false } +balances = { package = "srml-balances", path = "../../srml/balances", default-features = false } +consensus = { package = "srml-consensus", path = "../../srml/consensus", default-features = false } +contract = { package = "srml-contract", path = "../../srml/contract", default-features = false } +council = { package = "srml-council", path = "../../srml/council", default-features = false } +democracy = { package = "srml-democracy", path = "../../srml/democracy", default-features = false } +executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } +finality-tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false } +grandpa = { package = "srml-grandpa", path = "../../srml/grandpa", default-features = false } +indices = { package = "srml-indices", path = "../../srml/indices", default-features = false } +session = { package = "srml-session", path = "../../srml/session", default-features = false } +staking = { package = "srml-staking", path = "../../srml/staking", default-features = false } +system = { package = "srml-system", path = "../../srml/system", default-features = false } +timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } +treasury = { package = "srml-treasury", path = "../../srml/treasury", default-features = false } +sudo = { package = "srml-sudo", path = "../../srml/sudo", default-features = false } +srml-upgrade-key = { path = "../../srml/upgrade-key", default-features = false } +fees = { package = "srml-fees", path = "../../srml/fees", default-features = false } +node-primitives = { path = "../primitives", default-features = false } +consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default-features = false } +rustc-hex = { version = "2.0", optional = true } +hex-literal = { version = "0.1.0", optional = true } +serde = { version = "1.0", optional = true } +substrate-keyring = { path = "../../core/keyring", optional = true } [features] default = ["std"] std = [ "parity-codec/std", "substrate-primitives/std", - "sr-std/std", - "srml-support/std", - "srml-balances/std", - "srml-consensus/std", - "srml-contract/std", - "srml-council/std", - "srml-democracy/std", - "srml-executive/std", - "srml-grandpa/std", - "sr-primitives/std", - "srml-session/std", - "srml-staking/std", - "srml-system/std", - "srml-timestamp/std", - "srml-treasury/std", + "rstd/std", + "runtime_primitives/std", + "support/std", + "balances/std", + "consensus/std", + "contract/std", + "council/std", + "democracy/std", + "executive/std", + "grandpa/std", + "indices/std", + "session/std", + "staking/std", + "system/std", + "timestamp/std", + "treasury/std", + "sudo/std", "srml-upgrade-key/std", - "sr-version/std", + "fees/std", + "version/std", "node-primitives/std", - "serde/std", + "serde", "safe-mix/std", - "substrate-client/std", - "substrate-consensus-aura-primitives/std", + "client/std", + "consensus_aura/std", + "rustc-hex", + "hex-literal", + "serde", + "substrate-keyring", ] diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index aaef785f64294e0c1c76c6c8297674c38e99f286..7ca5c697f6fcbe349da9d1f74cc6332c5ed91729 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,56 +20,21 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit="256"] -#[macro_use] -extern crate srml_support; - -#[macro_use] -extern crate sr_primitives as runtime_primitives; - -extern crate substrate_primitives; - -#[macro_use] -extern crate substrate_client as client; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate parity_codec as codec; - -extern crate sr_std as rstd; -extern crate srml_aura as aura; -extern crate srml_balances as balances; -extern crate srml_consensus as consensus; -extern crate srml_contract as contract; -extern crate srml_council as council; -extern crate srml_democracy as democracy; -extern crate srml_executive as executive; -extern crate srml_grandpa as grandpa; -extern crate srml_session as session; -extern crate srml_staking as staking; -extern crate srml_system as system; -extern crate srml_timestamp as timestamp; -extern crate srml_treasury as treasury; -extern crate srml_upgrade_key as upgrade_key; -#[macro_use] -extern crate sr_version as version; -extern crate node_primitives; -extern crate substrate_consensus_aura_primitives as consensus_aura; - use rstd::prelude::*; +use support::construct_runtime; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{ - AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature + AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AuthorityId, Signature, AuthoritySignature }; use grandpa::fg_primitives::{self, ScheduledChange}; use client::{ - block_builder::api as block_builder_api, runtime_api as client_api + block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult}, + runtime_api as client_api, impl_runtime_apis }; -use runtime_primitives::{ApplyResult, CheckInherentError, BasicInherentData}; +use runtime_primitives::{ApplyResult, generic, create_runtime_str}; use runtime_primitives::transaction_validity::TransactionValidity; -use runtime_primitives::generic; use runtime_primitives::traits::{ - Convert, BlakeTwo256, Block as BlockT, DigestFor, NumberFor, ProvideInherent + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, }; use version::RuntimeVersion; use council::{motions as council_motions, voting as council_voting}; @@ -78,7 +43,6 @@ use council::seats as council_seats; #[cfg(any(feature = "std", test))] use version::NativeVersion; use substrate_primitives::OpaqueMetadata; -use consensus_aura::api as aura_api; #[cfg(any(feature = "std", test))] pub use runtime_primitives::BuildStorage; @@ -86,18 +50,16 @@ pub use consensus::Call as ConsensusCall; pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use runtime_primitives::{Permill, Perbill}; -pub use srml_support::{StorageValue, RuntimeMetadata}; - -const TIMESTAMP_SET_POSITION: u32 = 0; -const NOTE_OFFLINE_POSITION: u32 = 1; +pub use support::StorageValue; +pub use staking::StakerStatus; /// Runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), - authoring_version: 1, - spec_version: 1, - impl_version: 0, + authoring_version: 10, + spec_version: 35, + impl_version: 38, apis: RUNTIME_API_VERSIONS, }; @@ -118,6 +80,7 @@ impl system::Trait for Runtime { type Hashing = BlakeTwo256; type Digest = generic::Digest; type AccountId = AccountId; + type Lookup = Indices; type Header = generic::Header; type Event = Event; type Log = Log; @@ -127,50 +90,53 @@ impl aura::Trait for Runtime { type HandleReport = aura::StakingSlasher; } +impl indices::Trait for Runtime { + type AccountIndex = AccountIndex; + type IsDeadAccount = Balances; + type ResolveHint = indices::SimpleResolveHint; + type Event = Event; +} + impl balances::Trait for Runtime { type Balance = Balance; - type AccountIndex = AccountIndex; - type OnFreeBalanceZero = ((Staking, Contract), Democracy); - type EnsureAccountLiquid = (Staking, Democracy); + type OnFreeBalanceZero = ((Staking, Contract), Session); + type OnNewAccount = Indices; type Event = Event; } +impl fees::Trait for Runtime { + type Event = Event; + type TransferAsset = Balances; +} + impl consensus::Trait for Runtime { - const NOTE_OFFLINE_POSITION: u32 = NOTE_OFFLINE_POSITION; type Log = Log; - type SessionKey = SessionKey; + type SessionKey = AuthorityId; - // the aura module handles offline-reports internally + // The Aura module handles offline-reports internally // rather than using an explicit report system. type InherentOfflineReport = (); } impl timestamp::Trait for Runtime { - const TIMESTAMP_SET_POSITION: u32 = TIMESTAMP_SET_POSITION; type Moment = u64; type OnTimestampSet = Aura; } -/// Session key conversion. -pub struct SessionKeyConversion; -impl Convert for SessionKeyConversion { - fn convert(a: AccountId) -> SessionKey { - a.to_fixed_bytes().into() - } -} - impl session::Trait for Runtime { - type ConvertAccountIdToSessionKey = SessionKeyConversion; + type ConvertAccountIdToSessionKey = (); type OnSessionChange = (Staking, grandpa::SyncedAuthorities); type Event = Event; } impl staking::Trait for Runtime { + type Currency = balances::Module; type OnRewardMinted = Treasury; type Event = Event; } impl democracy::Trait for Runtime { + type Currency = balances::Module; type Proposal = Call; type Event = Event; } @@ -190,57 +156,65 @@ impl council::motions::Trait for Runtime { } impl treasury::Trait for Runtime { + type Currency = balances::Module; type ApproveOrigin = council_motions::EnsureMembers<_4>; type RejectOrigin = council_motions::EnsureMembers<_2>; type Event = Event; } impl contract::Trait for Runtime { + type Call = Call; + type Event = Event; type Gas = u64; type DetermineContractAddress = contract::SimpleAddressDeterminator; - type Event = Event; + type ComputeDispatchFee = contract::DefaultDispatchFeeComputor; } -impl upgrade_key::Trait for Runtime { +impl sudo::Trait for Runtime { type Event = Event; + type Proposal = Call; } impl grandpa::Trait for Runtime { - type SessionKey = SessionKey; + type SessionKey = AuthorityId; type Log = Log; type Event = Event; } +impl finality_tracker::Trait for Runtime { + type OnFinalizationStalled = grandpa::SyncedAuthorities; +} + construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, NodeBlock = node_primitives::Block, - InherentData = BasicInherentData + UncheckedExtrinsic = UncheckedExtrinsic { System: system::{default, Log(ChangesTrieRoot)}, - Aura: aura::{Module}, + Aura: aura::{Module, Inherent(Timestamp)}, Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, + Indices: indices, Balances: balances, Session: session, - Staking: staking, + Staking: staking::{default, OfflineWorker}, Democracy: democracy, Council: council::{Module, Call, Storage, Event}, CouncilVoting: council_voting, CouncilMotions: council_motions::{Module, Call, Storage, Event, Origin}, CouncilSeats: council_seats::{Config}, + FinalityTracker: finality_tracker::{Module, Call, Inherent}, Grandpa: grandpa::{Module, Call, Storage, Config, Log(), Event}, Treasury: treasury, - Contract: contract::{Module, Call, Config, Event}, - UpgradeKey: upgrade_key, + Contract: contract::{Module, Call, Storage, Config, Event}, + Sudo: sudo, + Fees: fees::{Module, Storage, Config, Event}, } ); /// The address format for describing accounts. -pub use balances::address::Address as RawAddress; - -/// The address format for describing accounts. -pub type Address = balances::Address; +pub type Address = ::Source; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. @@ -250,11 +224,11 @@ pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedMortalExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive, Balances, AllModules>; +pub type Executive = executive::Executive, Fees, AllModules>; impl_runtime_apis! { impl client_api::Core for Runtime { @@ -262,7 +236,7 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { + fn authorities() -> Vec { Consensus::authorities() } @@ -270,8 +244,8 @@ impl_runtime_apis! { Executive::execute_block(block) } - fn initialise_block(header: ::Header) { - Executive::initialise_block(&header) + fn initialise_block(header: &::Header) { + Executive::initialise_block(header) } } @@ -281,7 +255,7 @@ impl_runtime_apis! { } } - impl block_builder_api::BlockBuilder for Runtime { + impl block_builder_api::BlockBuilder for Runtime { fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { Executive::apply_extrinsic(extrinsic) } @@ -290,46 +264,12 @@ impl_runtime_apis! { Executive::finalise_block() } - fn inherent_extrinsics(data: BasicInherentData) -> Vec<::Extrinsic> { - let mut inherent = Vec::new(); - - inherent.extend( - Timestamp::create_inherent_extrinsics(data.timestamp) - .into_iter() - .map(|v| (v.0, UncheckedExtrinsic::new_unsigned(Call::Timestamp(v.1)))) - ); - - inherent.extend( - Consensus::create_inherent_extrinsics(data.consensus) - .into_iter() - .map(|v| (v.0, UncheckedExtrinsic::new_unsigned(Call::Consensus(v.1)))) - ); - - inherent.as_mut_slice().sort_unstable_by_key(|v| v.0); - inherent.into_iter().map(|v| v.1).collect() + fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() } - fn check_inherents(block: Block, data: BasicInherentData) -> Result<(), CheckInherentError> { - let expected_slot = data.aura_expected_slot; - - // draw timestamp out from extrinsics. - let set_timestamp = block.extrinsics() - .get(TIMESTAMP_SET_POSITION as usize) - .and_then(|xt: &UncheckedExtrinsic| match xt.function { - Call::Timestamp(TimestampCall::set(ref t)) => Some(t.clone()), - _ => None, - }) - .ok_or_else(|| CheckInherentError::Other("No valid timestamp in block.".into()))?; - - // take the "worse" result of normal verification and the timestamp vs. seal - // check. - CheckInherentError::combine_results( - Runtime::check_inherents(block, data), - || { - Aura::verify_inherent(set_timestamp.into(), expected_slot) - .map_err(|s| CheckInherentError::Other(s.into())) - }, - ) + fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { + data.check_extrinsics(&block) } fn random_seed() -> ::Hash { @@ -344,12 +284,12 @@ impl_runtime_apis! { } impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_pending_change(digest: DigestFor) + fn grandpa_pending_change(digest: &DigestFor) -> Option>> { for log in digest.logs.iter().filter_map(|l| match l { Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal), - _=> None + _ => None }) { if let Some(change) = Grandpa::scrape_digest_change(log) { return Some(change); @@ -358,12 +298,26 @@ impl_runtime_apis! { None } - fn grandpa_authorities() -> Vec<(SessionKey, u64)> { + fn grandpa_forced_change(digest: &DigestFor) + -> Option<(NumberFor, ScheduledChange>)> + { + for log in digest.logs.iter().filter_map(|l| match l { + Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal), + _ => None + }) { + if let Some(change) = Grandpa::scrape_digest_forced_change(log) { + return Some(change); + } + } + None + } + + fn grandpa_authorities() -> Vec<(AuthorityId, u64)> { Grandpa::grandpa_authorities() } } - impl aura_api::AuraApi for Runtime { + impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { Aura::slot_duration() } diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index bf8132106496f3c6ad64d1e6fec6c2daa26ebac1..6d704abe36c8792f41e42879a59daf9ba2a183a2 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -1,30 +1,51 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -37,37 +58,80 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmask" +version = "0.5.0" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" + [[package]] name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.25" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -77,7 +141,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -95,8 +167,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam" -version = "0.2.12" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "crossbeam-deque" @@ -109,11 +200,20 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -121,10 +221,10 @@ name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -132,31 +232,40 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -169,9 +278,72 @@ name = "crunchy" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crypto-mac" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -187,18 +359,43 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fixed-hash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -221,6 +418,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -241,21 +443,42 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "gcc" -version = "0.3.55" +name = "generic-array" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "hash-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -266,9 +489,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -283,6 +511,35 @@ dependencies = [ "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -295,7 +552,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -308,7 +582,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -317,6 +591,11 @@ name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -329,20 +608,15 @@ dependencies = [ [[package]] name = "kvdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "lazy_static" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -352,24 +626,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "lock_api" -version = "0.1.5" +name = "libsecp256k1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "log" -version = "0.3.9" +name = "lock_api" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -377,30 +656,17 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mashup" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "mashup-impl" -version = "0.1.9" +name = "matches" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "matches" -version = "0.1.8" +name = "memchr" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -410,10 +676,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -422,6 +688,17 @@ name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "merlin" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.16" @@ -432,11 +709,11 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -448,7 +725,7 @@ dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,7 +734,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -477,8 +754,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -486,10 +763,10 @@ dependencies = [ name = "node-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -499,11 +776,13 @@ dependencies = [ name = "node-runtime" version = "0.1.0" dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -514,9 +793,13 @@ dependencies = [ "srml-council 0.1.0", "srml-democracy 0.1.0", "srml-executive 0.1.0", + "srml-fees 0.1.0", + "srml-finality-tracker 0.1.0", "srml-grandpa 0.1.0", + "srml-indices 0.1.0", "srml-session 0.1.0", "srml-staking 0.1.0", + "srml-sudo 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", @@ -524,9 +807,17 @@ dependencies = [ "srml-upgrade-key 0.1.0", "substrate-client 0.1.0", "substrate-consensus-aura-primitives 0.1.0", + "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", ] +[[package]] +name = "node-runtime-wasm" +version = "0.1.0" +dependencies = [ + "node-runtime 0.1.0", +] + [[package]] name = "nodrop" version = "0.1.13" @@ -547,44 +838,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" -version = "0.10.15" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.39" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "owning_ref" version = "0.4.0" @@ -596,25 +893,27 @@ dependencies = [ [[package]] name = "parity-bytes" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" [[package]] name = "parity-codec" -version = "2.1.5" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-codec-derive" -version = "2.1.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -622,69 +921,58 @@ name = "parity-wasm" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.7.0" +name = "parking_lot_core" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.2.14" +name = "paste" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.3.1" +name = "paste-impl" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot_core" -version = "0.4.0" +name = "pbkdf2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -697,6 +985,25 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "primitive-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack" version = "0.4.1" @@ -705,6 +1012,16 @@ dependencies = [ "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack-impl" version = "0.4.1" @@ -712,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -720,82 +1037,84 @@ dependencies = [ [[package]] name = "pwasm-utils" -version = "0.3.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -803,7 +1122,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -811,31 +1130,56 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_xorshift" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "0.8.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -845,31 +1189,60 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.43" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ring" -version = "0.12.1" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -898,6 +1271,23 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "schnorrkel" +version = "0.0.0" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -918,27 +1308,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -946,9 +1336,44 @@ name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sha2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha3" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -972,37 +1397,40 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "slog-scope" -version = "4.0.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "spin" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "sr-api-macros" version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1010,13 +1438,15 @@ name = "sr-io" version = "0.1.0" dependencies = [ "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1026,10 +1456,9 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", "substrate-primitives 0.1.0", @@ -1039,11 +1468,11 @@ dependencies = [ name = "sr-sandbox" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1057,10 +1486,10 @@ dependencies = [ name = "sr-version" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -1069,52 +1498,47 @@ dependencies = [ name = "srml-aura" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", + "srml-session 0.1.0", "srml-staking 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", - "substrate-primitives 0.1.0", + "substrate-inherents 0.1.0", ] [[package]] name = "srml-balances" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-keyring 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-consensus" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -1122,18 +1546,20 @@ dependencies = [ name = "srml-contract" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-sandbox 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", + "srml-fees 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "srml-timestamp 0.1.0", "substrate-primitives 0.1.0", ] @@ -1141,15 +1567,13 @@ dependencies = [ name = "srml-council" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-balances 0.1.0", "srml-democracy 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", @@ -1160,28 +1584,24 @@ dependencies = [ name = "srml-democracy" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-balances 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-executive" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1190,17 +1610,47 @@ dependencies = [ ] [[package]] -name = "srml-grandpa" +name = "srml-fees" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-finality-tracker" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-inherents 0.1.0", +] + +[[package]] +name = "srml-grandpa" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-consensus 0.1.0", + "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", @@ -1208,14 +1658,31 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "srml-indices" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", ] @@ -1224,98 +1691,112 @@ dependencies = [ name = "srml-session" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-staking" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "srml-timestamp 0.1.0", "substrate-keyring 0.1.0", - "substrate-primitives 0.1.0", +] + +[[package]] +name = "srml-sudo" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-support-procedural 0.1.0", + "srml-system 0.1.0", ] [[package]] name = "srml-support" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-metadata 0.1.0", "srml-support-procedural 0.1.0", + "substrate-inherents 0.1.0", ] [[package]] name = "srml-support-procedural" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-system" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", @@ -1327,51 +1808,42 @@ dependencies = [ name = "srml-timestamp" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", - "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", + "substrate-inherents 0.1.0", ] [[package]] name = "srml-treasury" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-balances 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "srml-upgrade-key" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", - "srml-support-procedural 0.1.0", "srml-system 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] @@ -1384,6 +1856,17 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "substrate-bip39" +version = "0.2.0" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" +dependencies = [ + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-client" version = "0.1.0" @@ -1391,24 +1874,24 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", - "substrate-telemetry 0.3.0", + "substrate-telemetry 0.3.1", "substrate-trie 0.4.0", ] @@ -1416,131 +1899,157 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-version 0.1.0", - "srml-support 0.1.0", "substrate-client 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] name = "substrate-consensus-common" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", - "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-executor" version = "0.1.0" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-finality-grandpa-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-client 0.1.0", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-inherents" +version = "0.1.0" +dependencies = [ + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + [[package]] name = "substrate-keyring" version = "0.1.0" dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-primitives" version = "0.1.0" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", + "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-serializer" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" -version = "0.3.0" +version = "0.3.1" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1548,30 +2057,41 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "memory-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" -version = "0.14.9" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "syn" -version = "0.15.22" +name = "synstructure" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1585,39 +2105,62 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1625,101 +2168,114 @@ name = "tokio-codec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-tcp" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1727,49 +2283,57 @@ name = "tokio-udp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1777,16 +2341,27 @@ name = "twox-hash" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1800,25 +2375,20 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "untrusted" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1832,21 +2402,21 @@ dependencies = [ ] [[package]] -name = "vcpkg" -version = "0.2.6" +name = "utf8-ranges" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "void" -version = "1.0.2" +name = "vcpkg" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1885,16 +2455,16 @@ name = "ws" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1908,64 +2478,96 @@ dependencies = [ ] [metadata] -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitmask 0.5.0 (git+https://github.com/paritytech/bitmask)" = "" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" -"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" +"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" "checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" +"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" +"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" -"checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "83c2dda19c01176e8e7148f7bdb88bbdf215a8db0641f89fc40e4b81736aeda5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" @@ -1974,92 +2576,113 @@ dependencies = [ "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" -"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" -"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" +"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum parity-codec 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21c9c3a1623c71ed83964ff28cac6126e178920f7646d32c337eacb9152b2907" +"checksum parity-codec-derive 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "864e9f66b58c0b38f0d6b511b6576afa2b678ae801b64220553bced57ac12df9" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9723236a9525c757d9725b993511e3fc941e33f27751942232f0058298297edf" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" +"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" -"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" -"checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "053344c94c0e2b22da6305efddb698d7c485809427cf40555dc936085f67a9df" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1415431cb2398d84da64173f8473c792808314427d4a6f2f3ea85ae67239fe3" +"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" -"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" -"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" -"checksum trie-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-root 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" +"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" -"checksum uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a60b9508cff2b7c27ed41200dd668806280740fadc8c88440e9c88625e84f1a" +"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/node/runtime/wasm/Cargo.toml b/node/runtime/wasm/Cargo.toml index 400ec9d0f96d6ceadc0a314afd15de82bd3ac2b3..3512971a44d43e3e40a460c12a5cd00f430d789c 100644 --- a/node/runtime/wasm/Cargo.toml +++ b/node/runtime/wasm/Cargo.toml @@ -1,64 +1,20 @@ [package] -name = "node-runtime" +name = "node-runtime-wasm" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [lib] +name = "node_runtime" crate-type = ["cdylib"] [dependencies] -integer-sqrt = { version = "0.1.2" } -safe-mix = { version = "1.0", default-features = false } -parity-codec-derive = { version = "2.1" } -parity-codec = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../../core/primitives", default-features = false } -substrate-client = { path = "../../../core/client", default-features = false } -sr-std = { path = "../../../core/sr-std", default-features = false } -srml-support = { path = "../../../srml/support", default-features = false } -srml-aura = { path = "../../../srml/aura", default-features = false } -srml-balances = { path = "../../../srml/balances", default-features = false } -srml-consensus = { path = "../../../srml/consensus", default-features = false } -srml-contract = { path = "../../../srml/contract", default-features = false } -srml-council = { path = "../../../srml/council", default-features = false } -srml-democracy = { path = "../../../srml/democracy", default-features = false } -srml-executive = { path = "../../../srml/executive", default-features = false } -sr-primitives = { path = "../../../core/sr-primitives", default-features = false } -srml-session = { path = "../../../srml/session", default-features = false } -srml-staking = { path = "../../../srml/staking", default-features = false } -srml-system = { path = "../../../srml/system", default-features = false } -srml-timestamp = { path = "../../../srml/timestamp", default-features = false } -srml-treasury = { path = "../../../srml/treasury", default-features = false } -srml-upgrade-key = { path = "../../../srml/upgrade-key", default-features = false } -srml-grandpa = { path = "../../../srml/grandpa", default-features = false } -sr-version = { path = "../../../core/sr-version", default-features = false } -node-primitives = { path = "../../primitives", default-features = false } -substrate-consensus-aura-primitives = { path = "../../../core/consensus/aura/primitives", default-features = false } +node-runtime = { path = "..", default-features = false } [features] default = [] std = [ - "safe-mix/std", - "parity-codec/std", - "substrate-primitives/std", - "substrate-client/std", - "sr-std/std", - "sr-primitives/std", - "srml-support/std", - "srml-balances/std", - "srml-consensus/std", - "srml-contract/std", - "srml-council/std", - "srml-democracy/std", - "srml-executive/std", - "srml-session/std", - "srml-staking/std", - "srml-system/std", - "srml-timestamp/std", - "srml-treasury/std", - "srml-upgrade-key/std", - "srml-grandpa/std", - "sr-version/std", - "node-primitives/std", + "node-runtime/std", ] [profile.release] diff --git a/node/runtime/wasm/build.sh b/node/runtime/wasm/build.sh index 8cabead3fa5393d289b446c96c343ac4683e70f9..f0b7c961bda7b9253fb8054ba01059afa1c04e9c 100755 --- a/node/runtime/wasm/build.sh +++ b/node/runtime/wasm/build.sh @@ -6,7 +6,7 @@ if cargo --version | grep -q "nightly"; then else CARGO_CMD="cargo +nightly" fi -$CARGO_CMD build --target=wasm32-unknown-unknown --release +CARGO_INCREMENTAL=0 RUSTFLAGS="-C link-arg=--export-table" $CARGO_CMD build --target=wasm32-unknown-unknown --release for i in node_runtime do wasm-gc target/wasm32-unknown-unknown/release/$i.wasm target/wasm32-unknown-unknown/release/$i.compact.wasm diff --git a/node/runtime/wasm/src b/node/runtime/wasm/src deleted file mode 120000 index 5cd551cf2693e4b4f65d7954ec621454c2b20326..0000000000000000000000000000000000000000 --- a/node/runtime/wasm/src +++ /dev/null @@ -1 +0,0 @@ -../src \ No newline at end of file diff --git a/node/runtime/wasm/src/lib.rs b/node/runtime/wasm/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..a87b3f7c79dbd94a34a14537822b8c94fc67fab7 --- /dev/null +++ b/node/runtime/wasm/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The Substrate runtime reexported for WebAssembly compile. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use node_runtime::*; diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 5a4b831429ee5696c0cfb871071fbc47a4ee4007..f6ba616469aea564d52c8ce6382e4235bec26b1f 100644 Binary files a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/node/src/main.rs b/node/src/main.rs index 1f55cd7aab5762f00a6f200a8385c6347aed992a..5ff0d7ff3b0e68fae90eca12154bd1409d866d80 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,13 +18,6 @@ #![warn(missing_docs)] -extern crate node_cli as cli; -extern crate ctrlc; -extern crate futures; - -#[macro_use] -extern crate error_chain; - use cli::VersionInfo; use futures::sync::oneshot; use futures::{future, Future}; @@ -50,15 +43,17 @@ impl cli::IntoExit for Exit { } } -quick_main!(run); +error_chain::quick_main!(run); fn run() -> cli::error::Result<()> { let version = VersionInfo { + name: "Substrate Node", commit: env!("VERGEN_SHA_SHORT"), version: env!("CARGO_PKG_VERSION"), executable_name: "substrate", - author: "Parity Team ", + author: "Parity Technologies ", description: "Generic substrate node", + support_url: "https://github.com/paritytech/substrate/issues/new", }; cli::run(::std::env::args(), Exit, version) } diff --git a/scripts/common.sh b/scripts/common.sh index c7629f2d9e918ad2127238bada5ffdf83bdb43df..8aff9acc578ec5c3671e39b269a32c13110a1566 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -6,6 +6,7 @@ ROOT=`dirname "$0"` SRCS=( "core/executor/wasm" "node/runtime/wasm" + "node-template/runtime/wasm" "core/test-runtime/wasm" ) diff --git a/scripts/gitlab/check_merge_conflict.sh b/scripts/gitlab/check_merge_conflict.sh new file mode 100755 index 0000000000000000000000000000000000000000..dd677ff7620d1d8ee467ba65bb9db67e8aed2918 --- /dev/null +++ b/scripts/gitlab/check_merge_conflict.sh @@ -0,0 +1,110 @@ +#!/bin/sh +# +# check if there is a merge conflict with this pull request only about wasm +# binary blobs. if so trigger a rebuild of it and push it on the feature +# branch if owned by paritytech +# + +set -e # fail on any error + +TEST_RUNTIME="core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm" +NODE_RUNTIME="node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm" + + + +jsonfile="$(mktemp)" + +attemptno="1" +while ( ! test -s ${jsonfile} ) \ + || ( [ "$(jq -r .mergeable ${jsonfile})" = "null" ] \ + && [ "${attemptno}" -lt 5 ] ) +do + echo "| checking pull request status (attempt no ${attemptno})" + curl -sS -o ${jsonfile} -H "Accept: application/vnd.github.v3+json" \ + "${GITHUB_API}/repos/paritytech/substrate/pulls/${CI_COMMIT_REF_NAME}" + sleep 3 + attemptno="$(( ${attemptno} + 1 ))" +done + + + +baseref="$(jq -r .head.ref ${jsonfile})" +baserepo="$(jq -r .head.repo.full_name ${jsonfile})" +mergeable="$(jq -r .mergeable ${jsonfile})" + +rm -f ${jsonfile} + + +cat <<-EOT +| +| pr is of feature branch ${baseref} on ${baserepo} +| +| tell me github is this branch mergeable into the master branch? +| +EOT + +test "${mergeable}" = "true" && echo "| yes, it is." && exit 0 + +if [ "${baseref}" = "null" -o "${baserepo}" = "null" ] +then + echo "| either connectivity issues with github or pull request not existant" + exit 3 +fi + +cat <<-EOT +| not mergeable +| +| github sees a conflict - check if it's only about the following wasm blobs +| +| - ${TEST_RUNTIME} +| - ${NODE_RUNTIME} +| +EOT + +git fetch origin master +git config --global user.email "devops-team+substrate-ci-merge-conflict@parity.io" +git config --global user.name "I shall never commit to anything" + +cat <<-EOT +| +| trying to merge with the master branch to see if there is a conflict about +| the wasm files only +| +EOT + +if git merge --no-commit --no-ff origin/master | grep '^CONFLICT ' \ + | grep -v -e ${TEST_RUNTIME} -e ${NODE_RUNTIME} +then + git merge --abort + echo "| there are more conflicting files than the wasm blobs" + exit 1 +fi +git merge --abort + + +cat <<-EOT +| +| only wasm blobs block the merge. +| +| triggering rebuild of wasm blobs which will be pushed onto the feature +| branch of this pull request upon success. +| +| see: +| +EOT + + + +curl -sS -X POST \ + -F "token=${CI_JOB_TOKEN}" \ + -F "ref=master" \ + -F "variables[REBUILD_WASM]=\"${baserepo}:${baseref}\"" \ + ${GITLAB_API}/projects/${GITHUB_API_PROJECT}/trigger/pipeline \ + | jq -r .web_url + +# fail as there will be another commit on top of that feature branch that will +# be tested anyway. +exit 1 + + +# vim: noexpandtab diff --git a/scripts/gitlab/check_runtime.sh b/scripts/gitlab/check_runtime.sh new file mode 100755 index 0000000000000000000000000000000000000000..61068e7eb8885d18ebaafd4511be1efcb48d45d0 --- /dev/null +++ b/scripts/gitlab/check_runtime.sh @@ -0,0 +1,142 @@ +#!/bin/sh +# +# +# check for any changes in the node/src/runtime, srml/ and core/sr_* trees. if +# there are any changes found, it should mark the PR breaksconsensus and +# "auto-fail" the PR in some way unless a) the runtime is rebuilt and b) there +# isn't a change in the runtime/src/lib.rs file that alters the version. + +set -e # fail on any error + + +# give some context +git log --graph --oneline --decorate=short -n 10 + + +RUNTIME="node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm" +VERSIONS_FILE="node/runtime/src/lib.rs" + +github_label () { + echo + echo "# run github-api job for labelling it ${1}" + curl -sS -X POST \ + -F "token=${CI_JOB_TOKEN}" \ + -F "ref=master" \ + -F "variables[LABEL]=${1}" \ + -F "variables[PRNO]=${CI_COMMIT_REF_NAME}" \ + ${GITLAB_API}/projects/${GITHUB_API_PROJECT}/trigger/pipeline +} + + + + +# check if the wasm sources changed +if ! git diff --name-only origin/master...${CI_COMMIT_SHA} \ + | grep -q -e '^node/src/runtime' -e '^srml/' -e '^core/sr-' +then + cat <<-EOT + + no changes to the runtime source code detected + + EOT + + exit 0 +fi + + + +# check for spec_version updates: if the spec versions changed, then there is +# consensus-critical logic that has changed. the runtime wasm blobs must be +# rebuilt. + +add_spec_version="$(git diff origin/master...${CI_COMMIT_SHA} ${VERSIONS_FILE} \ + | sed -n -r "s/^\+[[:space:]]+spec_version: +([0-9]+),$/\1/p")" +sub_spec_version="$(git diff origin/master...${CI_COMMIT_SHA} ${VERSIONS_FILE} \ + | sed -n -r "s/^\-[[:space:]]+spec_version: +([0-9]+),$/\1/p")" + + +# see if the version and the binary blob changed +if [ "${add_spec_version}" != "${sub_spec_version}" ] +then + + github_label "B2-breaksapi" + + if git diff --name-only origin/master...${CI_COMMIT_SHA} \ + | grep -q "${RUNTIME}" + then + cat <<-EOT + + changes to the runtime sources and changes in the spec version. Wasm + binary blob is rebuilt. Looks good. + + spec_version: ${sub_spec_version} -> ${add_spec_version} + + EOT + exit 0 + else + cat <<-EOT + + changes to the runtime sources and changes in the spec version. Wasm + binary blob needs rebuilding! + + spec_version: ${sub_spec_version} -> ${add_spec_version} + + EOT + + # drop through into pushing `gotissues` and exit 1... + fi +else + # check for impl_version updates: if only the impl versions changed, we assume + # there is no consensus-critical logic that has changed. + + add_impl_version="$(git diff origin/master...${CI_COMMIT_SHA} ${VERSIONS_FILE} \ + | sed -n -r 's/^\+[[:space:]]+impl_version: +([0-9]+),$/\1/p')" + sub_impl_version="$(git diff origin/master...${CI_COMMIT_SHA} ${VERSIONS_FILE} \ + | sed -n -r 's/^\-[[:space:]]+impl_version: +([0-9]+),$/\1/p')" + + + # see if the impl version changed + if [ "${add_impl_version}" != "${sub_impl_version}" ] + then + cat <<-EOT + + changes to the runtime sources and changes in the impl version. + + impl_version: ${sub_impl_version} -> ${add_impl_version} + + EOT + exit 0 + fi + + + cat <<-EOT + + wasm source files changed but not the spec/impl version and the runtime + binary blob. If changes made do not alter logic, just bump 'impl_version'. + If they do change logic, bump 'spec_version' and rebuild wasm. + + source file directories: + - node/src/runtime + - srml + - core/sr-* + + versions file: ${VERSIONS_FILE} + + note: if the master branch was merged in as automated wasm rebuilds do it + might be the case that a {spec,impl}_version has been changed. but for pull + requests that involve wasm source file changes a version has to be changed + in the pull request itself. + + EOT + + # drop through into pushing `gotissues` and exit 1... +fi + +# dropped through. there's something wrong; mark `gotissues` and exit 1. + +github_label "A4-gotissues" + + +exit 1 + +# vim: noexpandtab diff --git a/scripts/kubernetes/Chart.yaml b/scripts/kubernetes/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4dd133c860bb12f93af80182620b79a23877f565 --- /dev/null +++ b/scripts/kubernetes/Chart.yaml @@ -0,0 +1,12 @@ +name: substrate +version: 0.1 +appVersion: 0.9.1 +description: "Substrate: The platform for blockchain innovators" +home: https://substrate.network/ +icon: https://substrate.network/favicon.ico +sources: + - https://github.com/paritytech/substrate/ +maintainers: + - name: Paritytech Devops Team + email: devops-team@parity.io +tillerVersion: ">=2.8.0" diff --git a/scripts/kubernetes/README.md b/scripts/kubernetes/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0f3ec38990375bc9c76ae67f6ce144805957a7ab --- /dev/null +++ b/scripts/kubernetes/README.md @@ -0,0 +1,47 @@ + + +# Substrate Kubernetes Helm Chart + +This [Helm Chart](https://helm.sh/) can be used for deploying containerized +**Substrate** to a [Kubernetes](https://kubernetes.io/) cluster. + + +## Prerequisites + +- Tested on Kubernetes 1.10.7-gke.6 + +## Installation + +To install the chart with the release name `my-release` into namespace +`my-namespace` from within this directory: + +```console +$ helm install --namespace my-namespace --name my-release --values values.yaml ./ +``` + +The command deploys Substrate on the Kubernetes cluster in the configuration +given in `values.yaml`. When the namespace is omitted it'll be installed in +the default one. + + +## Removal of the Chart + +To uninstall/delete the `my-release` deployment: + +```console +$ helm delete --namespace my-namespace my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + + +## Upgrading + +Once the chart is installed and a new version should be deployed helm takes +care of this by + +```console +$ helm upgrade --namespace my-namespace --values values.yaml my-release ./ +``` + + diff --git a/scripts/kubernetes/templates/poddisruptionbudget.yaml b/scripts/kubernetes/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000000000000000000000000000000000000..af40522842c2359b4bd69571a746c3bffece71d4 --- /dev/null +++ b/scripts/kubernetes/templates/poddisruptionbudget.yaml @@ -0,0 +1,10 @@ +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: substrate +spec: + selector: + matchLabels: + app: substrate + maxUnavailable: 1 + diff --git a/scripts/kubernetes/templates/secrets.yaml b/scripts/kubernetes/templates/secrets.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e00738448258a59bdfd5612f3cb1eb2cfbaa58a6 --- /dev/null +++ b/scripts/kubernetes/templates/secrets.yaml @@ -0,0 +1,11 @@ +{{- if .Values.validator.keys }} +apiVersion: v1 +kind: Secret +metadata: + name: substrate-secrets + labels: + app: substrate +type: Opaque +data: + secrets: {{ .Values.validator.keys | default "" }} +{{- end }} diff --git a/scripts/kubernetes/templates/service.yaml b/scripts/kubernetes/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..27baa59dc4e0541f2c5f28e5777027136bb853a3 --- /dev/null +++ b/scripts/kubernetes/templates/service.yaml @@ -0,0 +1,39 @@ +# see: +# https://kubernetes.io/docs/tutorials/services/ +# https://kubernetes.io/docs/concepts/services-networking/service/ +# headless service for rpc +apiVersion: v1 +kind: Service +metadata: + name: substrate-rpc + labels: + app: substrate +spec: + ports: + - port: 9933 + name: http-rpc + - port: 9944 + name: websocket-rpc + selector: + app: substrate + sessionAffinity: None + type: ClusterIP + clusterIP: None +--- +apiVersion: v1 +kind: Service +metadata: + name: substrate +spec: + ports: + - port: 30333 + name: p2p + nodePort: 30333 + protocol: TCP + selector: + app: substrate + sessionAffinity: None + type: NodePort + # don't route exteral traffic to non-local pods + externalTrafficPolicy: Local + diff --git a/scripts/kubernetes/templates/serviceaccount.yaml b/scripts/kubernetes/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5a0018a121b9809fe4222e1ef970eb39d024ba8f --- /dev/null +++ b/scripts/kubernetes/templates/serviceaccount.yaml @@ -0,0 +1,10 @@ +{{- if .Values.rbac.enable }} +# service account for substrate pods themselves +# no permissions for the api are required +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: substrate + name: {{ .Values.rbac.name }} +{{- end }} diff --git a/scripts/kubernetes/templates/statefulset.yaml b/scripts/kubernetes/templates/statefulset.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ec491f63494a173cac3f6b81326db2d620fd12a5 --- /dev/null +++ b/scripts/kubernetes/templates/statefulset.yaml @@ -0,0 +1,135 @@ +# https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/ +# https://cloud.google.com/kubernetes-engine/docs/concepts/statefulset +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: substrate +spec: + selector: + matchLabels: + app: substrate + serviceName: substrate + replicas: {{ .Values.nodes.replicas }} + updateStrategy: + type: RollingUpdate + podManagementPolicy: Parallel + template: + metadata: + labels: + app: substrate + spec: + {{- if .Values.rbac.enable }} + serviceAccountName: {{ .Values.rbac.name }} + {{- else }} + serviceAccountName: default + {{- end }} + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node + operator: In + values: + - substrate + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "app" + operator: In + values: + - substrate + topologyKey: "kubernetes.io/hostname" + terminationGracePeriodSeconds: 300 + {{- if .Values.validator.keys }} + volumes: + - name: substrate-validator-secrets + secret: + secretName: substrate-secrets + initContainers: + - name: prepare-secrets + image: busybox + command: [ "/bin/sh" ] + args: + - -c + - sed -n -r "s/^${POD_NAME}-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/key; + sed -n -r "s/^${POD_NAME}-node-key ([^ ]+)$/\1/p" /etc/validator/secrets > {{ .Values.image.basepath }}/node-key + env: + # from (workaround for hostname) + # https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/ + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: substrate-validator-secrets + readOnly: true + mountPath: "/etc/validator" + - name: substratedir + mountPath: {{ .Values.image.basepath }} + {{- end }} + containers: + - name: substrate + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + {{- if .Values.resources }} + resources: + requests: + memory: {{ .Values.resources.memory }} + cpu: {{ .Values.resources.cpu }} + {{- end }} + ports: + - containerPort: 30333 + name: p2p + - containerPort: 9933 + name: http-rpc + - containerPort: 9944 + name: websocket-rpc + command: ["/bin/sh"] + args: + - -c + - exec /usr/local/bin/substrate + --base-path {{ .Values.image.basepath }} + --name $(POD_NAME) + {{- if .Values.validator.enable }} + --validator + {{- end }} + {{- if .Values.validator.keys }} + --key $(cat {{ .Values.image.basepath }}/key) + --node-key $(cat {{ .Values.image.basepath }}/node-key) + {{- end }} + {{- range .Values.nodes.args }} {{ . }} {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + volumeMounts: + - name: substratedir + mountPath: {{ .Values.image.basepath }} + readinessProbe: + httpGet: + path: /health + port: http-rpc + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /health + port: http-rpc + initialDelaySeconds: 10 + periodSeconds: 10 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + volumeClaimTemplates: + - metadata: + name: substratedir + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: ssd + resources: + requests: + storage: 32Gi + diff --git a/scripts/kubernetes/values.yaml b/scripts/kubernetes/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..213ccaebe476e0f749cdb85e36c6f4cfa8fce0eb --- /dev/null +++ b/scripts/kubernetes/values.yaml @@ -0,0 +1,53 @@ +# set tag manually --set image.tag=latest +image: + repository: parity/substrate + tag: latest + pullPolicy: Always + basepath: /substrate + + +# if set to true a service account for substrate will be created +rbac: + enable: true + name: substrate + + +nodes: + replicas: 2 + args: + # name and data directory are set by the chart itself + # key and node-key may be provided on commandline invocation + # + # - --chain + # - krummelanke + # serve rpc within the local network + # - fenced off the world via firewall + # - used for health checks + - --rpc-external + - --ws-external + # - --log + # - sub-libp2p=trace + + +validator: + enable: True + # adds --validator commandline option + # + # key and node-key can be given in a base64 encoded keyfile string (at + # validator.keys) which has the following format: + # + # substrate-0-key + # substrate-0-node-key + # substrate-1-key + # substrate-1-node-key + # + # pod names are canonical. changing these or providing different amount of + # keys than the replicas count will lead to behaviour noone ever has + # experienced before. + + +# maybe adopt resource limits here to the nodes of the pool +# resources: +# memory: "5Gi" +# cpu: "1.5" + diff --git a/scripts/node-template-release.sh b/scripts/node-template-release.sh new file mode 100755 index 0000000000000000000000000000000000000000..3b2c0d6f0f6b82f702d70ed85feaedd4a1c7f61e --- /dev/null +++ b/scripts/node-template-release.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -e + +export TERM=xterm +PROJECT_ROOT=`git rev-parse --show-toplevel` + +if [ "$#" -ne 1 ]; then + echo "node-template-release.sh path_to_target_archive" + exit 1 +fi + +PATH_TO_ARCHIVE=$(pwd)/$1 +cd $PROJECT_ROOT/scripts/node-template-release + +cargo run $PROJECT_ROOT/node-template $PATH_TO_ARCHIVE diff --git a/scripts/node-template-release/Cargo.toml b/scripts/node-template-release/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..95538e8b210b3fa5208f803e8ffcdfaaf29b8824 --- /dev/null +++ b/scripts/node-template-release/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "node-template-release" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +toml = "0.4" +tar = "0.4" +glob = "0.2" +structopt = "0.2" +tempfile = "3" +fs_extra = "1" +git2 = "0.8" +flate2 = "1.0" + +[workspace] diff --git a/scripts/node-template-release/src/main.rs b/scripts/node-template-release/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..871cc078ed0c70fd73be54e953064bff328f7e4d --- /dev/null +++ b/scripts/node-template-release/src/main.rs @@ -0,0 +1,200 @@ +use structopt::StructOpt; + +use std::{ + path::{PathBuf, Path}, collections::HashMap, fs::{File, self}, io::{Read, Write}, + process::Command +}; + +use glob; + +use fs_extra::dir::{self, CopyOptions}; + +use tempfile; + +use git2; + +use toml; + +use tar; + +use flate2::{write::GzEncoder, Compression}; + +const SUBSTRATE_GIT_URL: &str = "https://github.com/paritytech/substrate.git"; + +type CargoToml = HashMap; + +#[derive(StructOpt)] +struct Options { + /// The path to the `node-template` source. + #[structopt(parse(from_os_str))] + node_template: PathBuf, + /// The path where to output the generated `tar.gz` file. + #[structopt(parse(from_os_str))] + output: PathBuf, +} + +/// Find all `Cargo.toml` files in the given path. +fn find_cargo_tomls(path: PathBuf) -> Vec { + let path = format!("{}/**/*.toml", path.display()); + + let glob = glob::glob(&path).expect("Generates globbing pattern"); + + let mut result = Vec::new(); + glob.into_iter().for_each(|file| { + match file { + Ok(file) => result.push(file), + Err(e) => println!("{:?}", e), + } + }); + + if result.is_empty() { + panic!("Did not found any `Cargo.toml` files."); + } + + result +} + +/// Copy the `node-template` to the given path. +fn copy_node_template(node_template: &Path, dest_path: &Path) { + let options = CopyOptions::new(); + dir::copy(node_template, dest_path, &options).expect("Copies node-template to tmp dir"); +} + +/// Gets the latest commit id of the repository given by `path`. +fn get_git_commit_id(path: &Path) -> String { + let repo = git2::Repository::discover(path) + .expect(&format!("Node template ({}) should be in a git repository.", path.display())); + + let commit_id = repo + .head() + .expect("Repository should have a head") + .peel_to_commit() + .expect("Head references a commit") + .id(); + + format!("{}", commit_id) +} + +/// Parse the given `Cargo.toml` into a `HashMap` +fn parse_cargo_toml(file: &Path) -> CargoToml { + let mut content = String::new(); + File::open(file).expect("Cargo.toml exists").read_to_string(&mut content).expect("Reads file"); + toml::from_str(&content).expect("Cargo.toml is a valid toml file") +} + +/// Replaces all substrate path dependencies with a git dependency. +fn replace_path_dependencies_with_git(cargo_toml_path: &Path, commit_id: &str, cargo_toml: &mut CargoToml) { + let mut cargo_toml_path = cargo_toml_path.to_path_buf(); + // remove `Cargo.toml` + cargo_toml_path.pop(); + + let mut dependencies: toml::value::Table = match cargo_toml + .remove("dependencies") + .and_then(|v| v.try_into().ok()) { + Some(deps) => deps, + None => return, + }; + + let deps_rewritten = dependencies + .iter() + .filter_map(|(k, v)| v.clone().try_into::().ok().map(move |v| (k, v))) + .filter(|t| t.1.contains_key("path")) + .filter(|t| { + // if the path does not exists, we need to add this as git dependency + t.1.get("path").unwrap().as_str().map(|path| !cargo_toml_path.join(path).exists()).unwrap_or(false) + }) + .map(|(k, mut v)| { + // remove `path` and add `git` and `rev` + v.remove("path"); + v.insert("git".into(), SUBSTRATE_GIT_URL.into()); + v.insert("rev".into(), commit_id.into()); + + (k.clone(), v.into()) + }).collect::>(); + + dependencies.extend(deps_rewritten.into_iter()); + + cargo_toml.insert("dependencies".into(), dependencies.into()); +} + +/// Add `profile.release` = `panic = unwind` to the given `Cargo.toml` +fn cargo_toml_add_profile_release(cargo_toml: &mut CargoToml) { + let mut panic_unwind = toml::value::Table::new(); + panic_unwind.insert("panic".into(), "unwind".into()); + + let mut profile = toml::value::Table::new(); + profile.insert("release".into(), panic_unwind.into()); + + cargo_toml.insert("profile".into(), profile.into()); +} + +fn write_cargo_toml(path: &Path, cargo_toml: CargoToml) { + let content = toml::to_string_pretty(&cargo_toml).expect("Creates `Cargo.toml`"); + let mut file = File::create(path).expect(&format!("Creates `{}`.", path.display())); + write!(file, "{}", content).expect("Writes `Cargo.toml`"); +} + +/// Build and test the generated node-template +fn build_and_test(path: &Path, cargo_tomls: &[PathBuf]) { + // Build wasm + assert!(Command::new(path.join("build.sh")).current_dir(path).status().expect("Compiles wasm").success()); + + // Build node + assert!(Command::new("cargo").args(&["build", "--all"]).current_dir(path).status().expect("Compiles node").success()); + + // Test node + assert!(Command::new("cargo").args(&["test", "--all"]).current_dir(path).status().expect("Tests node").success()); + + // Remove all `target` directories + for toml in cargo_tomls { + let mut target_path = toml.clone(); + target_path.pop(); + target_path = target_path.join("target"); + + if target_path.exists() { + fs::remove_dir_all(&target_path).expect(&format!("Removes `{}`", target_path.display())); + } + } +} + +fn main() { + let options = Options::from_args(); + + let build_dir = tempfile::tempdir().expect("Creates temp build dir"); + + let node_template_folder = options + .node_template + .canonicalize() + .expect("Node template path exists") + .file_name() + .expect("Node template folder is last element of path") + .to_owned(); + + // The path to the node-template in the build dir. + let node_template_path = build_dir.path().join(node_template_folder); + + copy_node_template(&options.node_template, build_dir.path()); + let cargo_tomls = find_cargo_tomls(build_dir.path().to_owned()); + + let commit_id = get_git_commit_id(&options.node_template); + + cargo_tomls.iter().for_each(|t| { + let mut cargo_toml = parse_cargo_toml(&t); + replace_path_dependencies_with_git(&t, &commit_id, &mut cargo_toml); + + // If this is the top-level `Cargo.toml`, add `profile.release` + if &node_template_path.join("Cargo.toml") == t { + cargo_toml_add_profile_release(&mut cargo_toml); + } + + write_cargo_toml(&t, cargo_toml); + }); + + build_and_test(&node_template_path, &cargo_tomls); + + let output = GzEncoder::new(File::create(&options.output) + .expect("Creates output file"), Compression::default()); + let mut tar = tar::Builder::new(output); + tar.append_dir_all("substrate-node-template", node_template_path) + .expect("Writes substrate-node-template archive"); +} diff --git a/srml/assets/Cargo.toml b/srml/assets/Cargo.toml index e695453c1e731dac33c1a6cb5fd4f7c3820def58..f274661e6c84e85740305cff5a79c5f3589f2a0c 100644 --- a/srml/assets/Cargo.toml +++ b/srml/assets/Cargo.toml @@ -2,29 +2,30 @@ name = "srml-assets" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +# Needed for various traits. In our case, `OnFinalise`. +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +# Needed for type-safe access to storage DB. srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } +# `system` module provides us with all sorts of useful stuff and macros depend on it being around. +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../core/primitives" } +sr-std = { path = "../../core/sr-std" } +runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", - "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", - "sr-primitives/std", + "primitives/std", "srml-support/std", - "srml-system/std", + "system/std", ] diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index c84620f4e763e26184b50ab16b99de0b67028b2a..14dba1d198dd50bc9f2594fc6e383caab7e54a36 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,34 +19,8 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -// Assert macros used in tests. -extern crate sr_std; - -// Needed for tests (`with_externalities`). -#[cfg(test)] -extern crate sr_io as runtime_io; - -// Needed for the set of mock primitives used in our tests. -#[cfg(test)] -extern crate substrate_primitives; - -// Needed for deriving `Encode` and `Decode` for `RawEvent`. -#[macro_use] -extern crate parity_codec_derive; -extern crate parity_codec as codec; - -// Needed for type-safe access to storage DB. -#[macro_use] -extern crate srml_support as runtime_support; - -// Needed for various traits. In our case, `OnFinalise`. -extern crate sr_primitives as primitives; -// `system` module provides us with all sorts of useful stuff and macros -// depend on it being around. -extern crate srml_system as system; - -use runtime_support::{StorageValue, StorageMap, Parameter}; -use primitives::traits::{Member, SimpleArithmetic, Zero}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage, ensure}; +use primitives::traits::{Member, SimpleArithmetic, Zero, StaticLookup}; use system::ensure_signed; pub trait Trait: system::Trait { @@ -62,11 +36,11 @@ type AssetId = u32; decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Issue a new class of fungible assets. There are, and will only ever be, `total` /// such assets and they'll all belong to the `origin` initially. It will have an /// identifier `AssetId` instance: this will be specified in the `Issued` event. - fn issue(origin, total: T::Balance) { + fn issue(origin, #[compact] total: T::Balance) { let origin = ensure_signed(origin)?; let id = Self::next_asset_id(); @@ -79,10 +53,15 @@ decl_module! { } /// Move some assets from one holder to another. - fn transfer(origin, id: AssetId, target: T::AccountId, amount: T::Balance) { + fn transfer(origin, + #[compact] id: AssetId, + target: ::Source, + #[compact] amount: T::Balance + ) { let origin = ensure_signed(origin)?; let origin_account = (id, origin.clone()); let origin_balance = >::get(&origin_account); + let target = T::Lookup::lookup(target)?; ensure!(!amount.is_zero(), "transfer amount should be non-zero"); ensure!(origin_balance >= amount, "origin account balance must be greater than or equal to the transfer amount"); @@ -92,7 +71,7 @@ decl_module! { } /// Destroy any assets of `id` owned by `origin`. - fn destroy(origin, id: AssetId) { + fn destroy(origin, #[compact] id: AssetId) { let origin = ensure_signed(origin)?; let balance = >::take((id, origin.clone())); ensure!(!balance.is_zero(), "origin balance should be non-zero"); @@ -148,10 +127,15 @@ mod tests { use super::*; use runtime_io::with_externalities; + use srml_support::{impl_outer_origin, assert_ok, assert_noop}; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use primitives::{BuildStorage, traits::{BlakeTwo256}, testing::{Digest, DigestItem, Header}}; + use primitives::{ + BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, + testing::{Digest, DigestItem, Header} + }; impl_outer_origin! { pub enum Origin for Test {} @@ -170,6 +154,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml index 2c8ea28eb8a874496918dd70c019bfdaa0d8d1af..9d1eda38c055fe18c1d3d67496bc4b654f8513bf 100644 --- a/srml/aura/Cargo.toml +++ b/srml/aura/Cargo.toml @@ -2,39 +2,39 @@ name = "srml-aura" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -serde = { version = "1.0", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +parity-codec-derive = { version = "3.1", default-features = false } +serde = { version = "1.0", optional = true } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-consensus = { path = "../consensus", default-features = false } -srml-timestamp = { path = "../timestamp", default-features = false } -srml-staking = { path = "../staking", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } +staking = { package = "srml-staking", path = "../staking", default-features = false } +session = { package = "srml-session", path = "../session", default-features = false } [dev-dependencies] lazy_static = "1.0" -parking_lot = "0.6" +parking_lot = "0.7.1" +substrate-primitives = { path = "../../core/primitives" } +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +consensus = { package = "srml-consensus", path = "../consensus" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", - "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-system/std", - "srml-consensus/std", - "srml-timestamp/std", - "srml-staking/std", + "primitives/std", + "system/std", + "timestamp/std", + "staking/std", + "inherents/std", ] diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index b0bc50d69bc54593e2666300f489f9c877ea29e6..553bebec75af7cd795b4e540cf9a314f44f1f91d 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,44 +18,94 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[allow(unused_imports)] -#[macro_use] -extern crate sr_std as rstd; +pub use timestamp; -#[macro_use] -extern crate parity_codec_derive; -extern crate parity_codec; +use rstd::{result, prelude::*}; +use srml_support::storage::StorageValue; +use srml_support::{decl_storage, decl_module}; +use primitives::traits::{As, Zero}; +use timestamp::OnTimestampSet; +#[cfg(feature = "std")] +use timestamp::TimestampInherentData; +use parity_codec::{Encode, Decode}; +use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; +#[cfg(feature = "std")] +use inherents::{InherentDataProviders, ProvideInherentData}; -#[macro_use] -extern crate srml_support as runtime_support; +mod mock; +mod tests; -extern crate sr_primitives as primitives; -extern crate srml_system as system; -extern crate srml_timestamp as timestamp; -extern crate srml_staking as staking; -extern crate substrate_primitives; +/// The aura inherent identifier. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"auraslot"; -#[cfg(test)] -extern crate srml_consensus as consensus; +/// The type of the aura inherent. +pub type InherentType = u64; -#[cfg(test)] -extern crate sr_io as runtime_io; +/// Auxiliary trait to extract aura inherent data. +pub trait AuraInherentData { + /// Get aura inherent data. + fn aura_inherent_data(&self) -> result::Result; + /// Replace aura inherent data. + fn aura_replace_inherent_data(&mut self, new: InherentType); +} -#[cfg(test)] -#[macro_use] -extern crate lazy_static; +impl AuraInherentData for InherentData { + fn aura_inherent_data(&self) -> result::Result { + self.get_data(&INHERENT_IDENTIFIER) + .and_then(|r| r.ok_or_else(|| "Aura inherent data not found".into())) + } -#[cfg(test)] -extern crate parking_lot; + fn aura_replace_inherent_data(&mut self, new: InherentType) { + self.replace_data(INHERENT_IDENTIFIER, &new); + } +} -use rstd::prelude::*; -use runtime_support::storage::StorageValue; -use runtime_support::dispatch::Result; -use primitives::traits::{As, Zero}; -use timestamp::OnTimestampSet; +/// Provides the slot duration inherent data for `Aura`. +#[cfg(feature = "std")] +pub struct InherentDataProvider { + slot_duration: u64, +} -mod mock; -mod tests; +#[cfg(feature = "std")] +impl InherentDataProvider { + pub fn new(slot_duration: u64) -> Self { + Self { + slot_duration + } + } +} + +#[cfg(feature = "std")] +impl ProvideInherentData for InherentDataProvider { + fn on_register( + &self, + providers: &InherentDataProviders, + ) -> result::Result<(), RuntimeString> { + if !providers.has_provider(×tamp::INHERENT_IDENTIFIER) { + // Add the timestamp inherent data provider, as we require it. + providers.register_provider(timestamp::InherentDataProvider) + } else { + Ok(()) + } + } + + fn inherent_identifier(&self) -> &'static inherents::InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data( + &self, + inherent_data: &mut InherentData, + ) -> result::Result<(), RuntimeString> { + let timestamp = inherent_data.timestamp_inherent_data()?; + let slot_num = timestamp / self.slot_duration; + inherent_data.put_data(INHERENT_IDENTIFIER, &slot_num) + } + + fn error_to_string(&self, error: &[u8]) -> Option { + RuntimeString::decode(&mut &error[..]).map(Into::into) + } +} /// Something which can handle Aura consensus reports. pub trait HandleReport { @@ -98,28 +148,13 @@ impl AuraReport { pub fn punish(&self, validator_count: usize, mut punish_with: F) where F: FnMut(usize, usize) { - let start_slot = self.start_slot % validator_count; - - // the number of times everyone was skipped. - let skipped_all = self.skipped / validator_count; - // the number of validators who were skipped once after that. - let skipped_after = self.skipped % validator_count; - - let iter = (start_slot..validator_count).into_iter() - .chain(0..start_slot) - .enumerate(); - - for (rel_index, actual_index) in iter { - let slash_count = skipped_all + if rel_index < skipped_after { - 1 - } else { - // avoid iterating over all authorities when skipping a couple. - if skipped_all == 0 { break } - 0 - }; - - if slash_count > 0 { - punish_with(actual_index, slash_count); + // If all validators have been skipped, then it implies some sort of + // systematic problem common to all rather than a minority of validators + // unfulfilling their specific duties. In this case, it doesn't make + // sense to punish anyone, so we guard against it. + if self.skipped < validator_count { + for index in 0..self.skipped { + punish_with((self.start_slot + index) % validator_count, 1); } } } @@ -133,20 +168,6 @@ impl Module { >::block_period().as_().saturating_mul(2) } - /// Verify an inherent slot that is used in a block seal against a timestamp - /// extracted from the block. - // TODO: ensure `ProvideInherent` can deal with dependencies like this. - // https://github.com/paritytech/substrate/issues/1228 - pub fn verify_inherent(timestamp: T::Moment, seal_slot: u64) -> Result { - let timestamp_based_slot = timestamp.as_() / Self::slot_duration(); - - if timestamp_based_slot == seal_slot { - Ok(()) - } else { - Err("timestamp set in block doesn't match slot in seal".into()) - } - } - fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { let last = Self::last(); ::LastTimestamp::put(now.clone()); @@ -186,7 +207,7 @@ pub struct StakingSlasher(::rstd::marker::PhantomData); impl HandleReport for StakingSlasher { fn handle_report(report: AuraReport) { - let validators = staking::Module::::validators(); + let validators = session::Module::::validators(); report.punish( validators.len(), @@ -197,3 +218,30 @@ impl HandleReport for StakingSlasher { ); } } + +impl ProvideInherent for Module { + type Call = timestamp::Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_: &InherentData) -> Option { + None + } + + fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { + let timestamp = match call { + timestamp::Call::set(ref timestamp) => timestamp.clone(), + _ => return Ok(()), + }; + + let timestamp_based_slot = timestamp.as_() / Self::slot_duration(); + + let seal_slot = data.aura_inherent_data()?; + + if timestamp_based_slot == seal_slot { + Ok(()) + } else { + Err(RuntimeString::from("timestamp set in block doesn't match slot in seal").into()) + } + } +} diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index 125466c9c048a664603717554faef18e2cce739c..6a0afb646951c0fbcdab17ce819222d0b8e41286 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,10 +18,11 @@ #![cfg(test)] -use primitives::{BuildStorage, testing::{Digest, DigestItem, Header}}; +use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}}; +use srml_support::impl_outer_origin; use runtime_io; use substrate_primitives::{H256, Blake2Hasher}; -use {Trait, Module, consensus, system, timestamp}; +use crate::{Trait, Module}; impl_outer_origin!{ pub enum Origin for Test {} @@ -32,9 +33,8 @@ impl_outer_origin!{ pub struct Test; impl consensus::Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; type Log = DigestItem; - type SessionKey = u64; + type SessionKey = UintAuthorityId; type InherentOfflineReport = (); } @@ -46,14 +46,13 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; - type Moment = u64; type OnTimestampSet = Aura; } @@ -66,7 +65,7 @@ pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities::default().build_storage().unwrap().0; t.extend(consensus::GenesisConfig::{ code: vec![], - authorities, + authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(), }.build_storage().unwrap().0); t.extend(timestamp::GenesisConfig::{ period: 1, diff --git a/srml/aura/src/tests.rs b/srml/aura/src/tests.rs index 6f215b8fe25e74c2743fb6e1746e9292fa9cd4fe..98b57a1251248a290f9fddc0bb4b4cb78a1a4ccd 100644 --- a/srml/aura/src/tests.rs +++ b/srml/aura/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,31 +18,44 @@ #![cfg(test)] -use mock::{System, Aura, new_test_ext}; +use lazy_static::lazy_static; +use crate::mock::{System, Aura, new_test_ext}; use primitives::traits::Header; use runtime_io::with_externalities; use parking_lot::Mutex; -use {AuraReport, HandleReport}; +use crate::{AuraReport, HandleReport}; #[test] fn aura_report_gets_skipped_correctly() { let mut report = AuraReport { - start_slot: 0, - skipped: 30, + start_slot: 3, + skipped: 15, }; let mut validators = vec![0; 10]; report.punish(10, |idx, count| validators[idx] += count); + assert_eq!(validators, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - assert_eq!(validators, vec![3; 10]); + let mut validators = vec![0; 10]; + report.skipped = 5; + report.punish(10, |idx, count| validators[idx] += count); + assert_eq!(validators, vec![0, 0, 0, 1, 1, 1, 1, 1, 0, 0]); + + let mut validators = vec![0; 10]; + report.start_slot = 8; + report.punish(10, |idx, count| validators[idx] += count); + assert_eq!(validators, vec![1, 1, 1, 0, 0, 0, 0, 0, 1, 1]); let mut validators = vec![0; 4]; + report.start_slot = 1; + report.skipped = 3; report.punish(4, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![8, 8, 7, 7]); + assert_eq!(validators, vec![0, 1, 1, 1]); + let mut validators = vec![0; 4]; report.start_slot = 2; report.punish(4, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![15, 15, 15, 15]); + assert_eq!(validators, vec![1, 0, 1, 1]); } #[test] diff --git a/srml/balances/Cargo.toml b/srml/balances/Cargo.toml index 9f7fd249b065090fe3852e35e85a33ef53c1b942..43759643ddfad3b3b14efeace9967d6bf0b7c5dc 100644 --- a/srml/balances/Cargo.toml +++ b/srml/balances/Cargo.toml @@ -2,33 +2,32 @@ name = "srml-balances" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "substrate-keyring", "parity-codec/std", - "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-system/std", + "primitives/std", + "system/std", ] diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index deadbfd656523d9c3998e4a572eed227d99980a0..ff0493f35fd51cf37ffbff200083a5c57e7f2dcd 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,184 +24,51 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[macro_use] -extern crate srml_support as runtime_support; - -extern crate sr_std as rstd; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate parity_codec as codec; -extern crate sr_primitives as primitives; -extern crate srml_system as system; - -#[cfg(test)] -extern crate sr_io as runtime_io; -#[cfg(test)] -extern crate substrate_primitives; - use rstd::prelude::*; use rstd::{cmp, result}; -use codec::{Encode, Decode, Codec, Input, Output, HasCompact}; -use runtime_support::{StorageValue, StorageMap, Parameter}; -use runtime_support::dispatch::Result; -use primitives::traits::{Zero, One, SimpleArithmetic, MakePayment, - As, Lookup, Member, CheckedAdd, CheckedSub, CurrentHeight, BlockNumberToHash}; -use address::Address as RawAddress; -use system::ensure_signed; +use parity_codec::{Codec, Encode, Decode}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module, ensure}; +use srml_support::traits::{ + UpdateBalanceOutcome, Currency, OnFreeBalanceZero, TransferAsset, + WithdrawReason, WithdrawReasons, ArithmeticType, LockIdentifier, LockableCurrency +}; +use srml_support::dispatch::Result; +use primitives::traits::{ + Zero, SimpleArithmetic, As, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug +}; +use system::{IsDeadAccount, OnNewAccount, ensure_signed}; mod mock; - -pub mod address; mod tests; -/// Number of account IDs stored per enum set. -const ENUM_SET_SIZE: usize = 64; - -/// The byte to identify intention to reclaim an existing account index. -const RECLAIM_INDEX_MAGIC: usize = 0x69; - -pub type Address = RawAddress<::AccountId, ::AccountIndex>; - -/// The account with the given id was killed. -pub trait OnFreeBalanceZero { - /// The account was the given id was killed. - fn on_free_balance_zero(who: &AccountId); -} - -impl OnFreeBalanceZero for () { - fn on_free_balance_zero(_who: &AccountId) {} -} -impl< - AccountId, - X: OnFreeBalanceZero, - Y: OnFreeBalanceZero, -> OnFreeBalanceZero for (X, Y) { - fn on_free_balance_zero(who: &AccountId) { - X::on_free_balance_zero(who); - Y::on_free_balance_zero(who); - } -} - -/// Trait for a hook to get called when some balance has been minted, causing dilution. -pub trait OnDilution { - /// Some `portion` of the total balance just "grew" by `minted`. `portion` is the pre-growth - /// amount (it doesn't take account of the recent growth). - fn on_dilution(minted: Balance, portion: Balance); -} - -impl OnDilution for () { - fn on_dilution(_minted: Balance, _portion: Balance) {} -} - -/// Determinator for whether a given account is able to transfer balance. -pub trait EnsureAccountLiquid { - /// Returns `Ok` iff the account is able to transfer funds normally. `Err(...)` - /// with the reason why not otherwise. - fn ensure_account_liquid(who: &AccountId) -> Result; -} -impl< - AccountId, - X: EnsureAccountLiquid, - Y: EnsureAccountLiquid, -> EnsureAccountLiquid for (X, Y) { - fn ensure_account_liquid(who: &AccountId) -> Result { - X::ensure_account_liquid(who)?; - Y::ensure_account_liquid(who) - } -} -impl EnsureAccountLiquid for () { - fn ensure_account_liquid(_who: &AccountId) -> Result { Ok(()) } -} - -pub trait Trait: system::Trait { +pub trait Trait: system::Trait { /// The balance of an account. - type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As + As + As; - /// Type used for storing an account's index; implies the maximum number of accounts the system - /// can hold. - type AccountIndex: Parameter + Member + Codec + Default + SimpleArithmetic + As + As + As + As + As + Copy; + type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As + As + MaybeSerializeDebug; + /// A function which is invoked when the free-balance has fallen below the existential deposit and /// has been reduced to zero. /// /// Gives a chance to clean up resources associated with the given account. type OnFreeBalanceZero: OnFreeBalanceZero; - /// A function that returns true iff a given account can transfer its funds to another account. - type EnsureAccountLiquid: EnsureAccountLiquid; + /// Handler for when a new account is created. + type OnNewAccount: OnNewAccount; /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; } -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Transfer some liquid free balance to another staker. - pub fn transfer( - origin, - dest: RawAddress, - value: ::Type - ) { - let transactor = ensure_signed(origin)?; - - let dest = Self::lookup(dest)?; - let value = value.into(); - let from_balance = Self::free_balance(&transactor); - let to_balance = Self::free_balance(&dest); - let would_create = to_balance.is_zero(); - let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; - let liability = match value.checked_add(&fee) { - Some(l) => l, - None => return Err("got overflow after adding a fee to value"), - }; - - let new_from_balance = match from_balance.checked_sub(&liability) { - Some(b) => b, - None => return Err("balance too low to send value"), - }; - if would_create && value < Self::existential_deposit() { - return Err("value too low to create account"); - } - T::EnsureAccountLiquid::ensure_account_liquid(&transactor)?; - - // NOTE: total stake being stored in the same type means that this could never overflow - // but better to be safe than sorry. - let new_to_balance = match to_balance.checked_add(&value) { - Some(b) => b, - None => return Err("destination balance too high to receive value"), - }; - - if transactor != dest { - Self::set_free_balance(&transactor, new_from_balance); - Self::decrease_total_stake_by(fee); - Self::set_free_balance_creating(&dest, new_to_balance); - Self::deposit_event(RawEvent::Transfer(transactor, dest, value, fee)); - } - } - - /// Set the balances of a given account. - fn set_balance( - who: RawAddress, - free: ::Type, - reserved: ::Type - ) { - let who = Self::lookup(who)?; - Self::set_free_balance(&who, free.into()); - Self::set_reserved_balance(&who, reserved.into()); - } - } +impl ArithmeticType for Module { + type Type = ::Balance; } decl_event!( - pub enum Event where + pub enum Event where ::AccountId, - ::AccountIndex, - ::Balance + >::Balance { /// A new account was created. - NewAccount(AccountId, AccountIndex, NewAccountOutcome), + NewAccount(AccountId, Balance), /// An account was reaped. ReapedAccount(AccountId), /// Transfer succeeded (from, to, value, fees). @@ -209,27 +76,70 @@ decl_event!( } ); +/// Struct to encode the vesting schedule of an individual account. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct VestingSchedule { + /// Locked amount at genesis. + pub offset: Balance, + /// Amount that gets unlocked every block from genesis. + pub per_block: Balance, +} + +impl> VestingSchedule { + /// Amount locked at block `n`. + pub fn locked_at>(&self, n: BlockNumber) -> Balance { + if let Some(x) = Balance::sa(n.as_()).checked_mul(&self.per_block) { + self.offset.max(x) - x + } else { + Zero::zero() + } + } +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct BalanceLock { + pub id: LockIdentifier, + pub amount: Balance, + pub until: BlockNumber, + pub reasons: WithdrawReasons, +} + decl_storage! { - trait Store for Module as Balances { + trait Store for Module, I: Instance=DefaultInstance> as Balances { /// The total amount of stake on the system. - pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { + pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n) }): T::Balance; /// The minimum amount allowed to keep an account open. pub ExistentialDeposit get(existential_deposit) config(): T::Balance; - /// The amount credited to a destination's account whose index was reclaimed. - pub ReclaimRebate get(reclaim_rebate) config(): T::Balance; /// The fee required to make a transfer. pub TransferFee get(transfer_fee) config(): T::Balance; /// The fee required to create an account. At least as big as ReclaimRebate. pub CreationFee get(creation_fee) config(): T::Balance; - /// The next free enumeration set. - pub NextEnumSet get(next_enum_set) build(|config: &GenesisConfig| { - T::AccountIndex::sa(config.balances.len() / ENUM_SET_SIZE) - }): T::AccountIndex; - /// The enumeration sets. - pub EnumSet get(enum_set): map T::AccountIndex => Vec; + /// Information regarding the vesting of a given account. + pub Vesting get(vesting) build(|config: &GenesisConfig| { + config.vesting.iter().filter_map(|&(ref who, begin, length)| { + let begin: u64 = begin.as_(); + let length: u64 = length.as_(); + let begin: T::Balance = As::sa(begin); + let length: T::Balance = As::sa(length); + + config.balances.iter() + .find(|&&(ref w, _)| w == who) + .map(|&(_, balance)| { + // <= begin it should be >= balance + // >= begin+length it should be <= 0 + + let per_block = balance / length; + let offset = begin * per_block + balance; + + (who.clone(), VestingSchedule { offset, per_block }) + }) + }).collect::>() + }): map T::AccountId => Option>; /// The 'free' balance of a given account. /// @@ -242,7 +152,7 @@ decl_storage! { /// /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. - pub FreeBalance get(free_balance) build(|config: &GenesisConfig| config.balances.clone()): map T::AccountId => T::Balance; + pub FreeBalance get(free_balance) build(|config: &GenesisConfig| config.balances.clone()): map T::AccountId => T::Balance; /// The amount of the balance of a given account that is externally reserved; this can still get /// slashed, but gets slashed last of all. @@ -258,104 +168,67 @@ decl_storage! { /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. pub ReservedBalance get(reserved_balance): map T::AccountId => T::Balance; - - // Payment stuff. - - /// The fee to be paid for making a transaction; the base. - pub TransactionBaseFee get(transaction_base_fee) config(): T::Balance; - /// The fee to be paid for making a transaction; the per-byte portion. - pub TransactionByteFee get(transaction_byte_fee) config(): T::Balance; + /// Any liquidity locks on some account balances. + pub Locks get(locks): map T::AccountId => Vec>; } add_extra_genesis { config(balances): Vec<(T::AccountId, T::Balance)>; - build(|storage: &mut primitives::StorageMap, _: &mut primitives::ChildrenStorageMap, config: &GenesisConfig| { - let ids: Vec<_> = config.balances.iter().map(|x| x.0.clone()).collect(); - for i in 0..(ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { - storage.insert(GenesisConfig::::hash(&>::key_for(T::AccountIndex::sa(i))).to_vec(), - ids[i * ENUM_SET_SIZE..ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); - } - }); + config(vesting): Vec<(T::AccountId, T::BlockNumber, T::BlockNumber)>; // begin, length } + extra_genesis_skip_phantom_data_field; } -/// Whatever happened about the hint given when creating the new account. -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone, Copy)] -pub enum NewAccountOutcome { - NoHint, - GoodHint, - BadHint, -} - -/// Outcome of a balance update. -pub enum UpdateBalanceOutcome { - /// Account balance was simply updated. - Updated, - /// The update has led to killing of the account. - AccountKilled, -} - -impl Module { - // PUBLIC IMMUTABLES - - /// The combined balance of `who`. - pub fn total_balance(who: &T::AccountId) -> T::Balance { - Self::free_balance(who) + Self::reserved_balance(who) - } - - /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no - /// balance changes in the meantime and only the reserved balance is not taken into account. - pub fn can_slash(who: &T::AccountId, value: T::Balance) -> bool { - Self::free_balance(who) >= value - } +decl_module! { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + fn deposit_event() = default; - /// Same result as `reserve(who, value)` (but without the side-effects) assuming there - /// are no balance changes in the meantime. - pub fn can_reserve(who: &T::AccountId, value: T::Balance) -> bool { - if T::EnsureAccountLiquid::ensure_account_liquid(who).is_ok() { - Self::free_balance(who) >= value - } else { - false + /// Transfer some liquid free balance to another staker. + pub fn transfer( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + Self::make_transfer(&transactor, &dest, value)?; } - } - /// Lookup an T::AccountIndex to get an Id, if there's one there. - pub fn lookup_index(index: T::AccountIndex) -> Option { - let enum_set_size = Self::enum_set_size(); - let set = Self::enum_set(index / enum_set_size); - let i: usize = (index % enum_set_size).as_(); - set.get(i).map(|x| x.clone()) + /// Set the balances of a given account. + fn set_balance( + who: ::Source, + #[compact] free: T::Balance, + #[compact] reserved: T::Balance + ) { + let who = T::Lookup::lookup(who)?; + Self::set_free_balance(&who, free); + Self::set_reserved_balance(&who, reserved); + } } +} - /// `true` if the account `index` is ready for reclaim. - pub fn can_reclaim(try_index: T::AccountIndex) -> bool { - let enum_set_size = Self::enum_set_size(); - let try_set = Self::enum_set(try_index / enum_set_size); - let i = (try_index % enum_set_size).as_(); - i < try_set.len() && Self::total_balance(&try_set[i]).is_zero() - } +// For funding methods, see Currency trait +impl, I: Instance> Module { - /// Lookup an address to get an Id, if there's one there. - pub fn lookup_address(a: address::Address) -> Option { - match a { - address::Address::Id(i) => Some(i), - address::Address::Index(i) => Self::lookup_index(i), + /// Get the amount that is currently being vested and cannot be transfered out of this account. + pub fn vesting_balance(who: &T::AccountId) -> T::Balance { + if let Some(v) = Self::vesting(who) { + Self::free_balance(who).min(v.locked_at(>::block_number())) + } else { + Zero::zero() } } - //PUBLIC MUTABLES (DANGEROUS) - /// Set the free balance of an account to some new value. /// /// Will enforce ExistentialDeposit law, anulling the account as needed. /// In that case it will return `AccountKilled`. pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { if balance < Self::existential_deposit() { - >::insert(who, balance); + >::insert(who, balance); Self::on_reserved_too_low(who); UpdateBalanceOutcome::AccountKilled } else { - >::insert(who, balance); + >::insert(who, balance); UpdateBalanceOutcome::Updated } } @@ -371,11 +244,11 @@ impl Module { // Commented out for no - but consider it instructive. // assert!(!Self::total_balance(who).is_zero()); if balance < Self::existential_deposit() { - >::insert(who, balance); + >::insert(who, balance); Self::on_free_too_low(who); UpdateBalanceOutcome::AccountKilled } else { - >::insert(who, balance); + >::insert(who, balance); UpdateBalanceOutcome::Updated } } @@ -388,7 +261,7 @@ impl Module { /// /// [`set_free_balance`]: #method.set_free_balance pub fn set_free_balance_creating(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - let ed = >::existential_deposit(); + let ed = >::existential_deposit(); // If the balance is too low, then the account is reaped. // NOTE: There are two balances for every account: `reserved_balance` and // `free_balance`. This contract subsystem only cares about the latter: whenever @@ -399,61 +272,172 @@ impl Module { // account is reaped). // NOTE: This is orthogonal to the `Bondage` value that an account has, a high // value of which makes even the `free_balance` unspendable. - // TODO: enforce this for the other balance-altering functions. if balance < ed { Self::set_free_balance(who, balance); UpdateBalanceOutcome::AccountKilled } else { - if !>::exists(who) { - let outcome = Self::new_account(&who, balance); - let credit = match outcome { - NewAccountOutcome::GoodHint => balance + >::reclaim_rebate(), - _ => balance, - }; - Self::set_free_balance(who, credit); - Self::increase_total_stake_by(credit - balance); - } else { - Self::set_free_balance(who, balance); + if !>::exists(who) { + Self::new_account(&who, balance); } + Self::set_free_balance(who, balance); UpdateBalanceOutcome::Updated } } - /// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created. - /// - /// This is a sensitive function since it circumvents any fees associated with account - /// setup. Ensure it is only called by trusted code. - /// - /// NOTE: This assumes that the total stake remains unchanged after this operation. If - /// you mean to actually mint value into existence, then use `reward` instead. - pub fn increase_free_balance_creating(who: &T::AccountId, value: T::Balance) -> UpdateBalanceOutcome { - Self::set_free_balance_creating(who, Self::free_balance(who) + value) + /// Transfer some liquid free balance to another staker. + pub fn make_transfer(transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance) -> Result { + let from_balance = Self::free_balance(transactor); + let to_balance = Self::free_balance(dest); + let would_create = to_balance.is_zero(); + let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() }; + let liability = match value.checked_add(&fee) { + Some(l) => l, + None => return Err("got overflow after adding a fee to value"), + }; + + let new_from_balance = match from_balance.checked_sub(&liability) { + None => return Err("balance too low to send value"), + Some(b) => b, + }; + if would_create && value < Self::existential_deposit() { + return Err("value too low to create account"); + } + Self::ensure_account_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; + + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. + let new_to_balance = match to_balance.checked_add(&value) { + Some(b) => b, + None => return Err("destination balance too high to receive value"), + }; + + if transactor != dest { + Self::set_free_balance(transactor, new_from_balance); + Self::decrease_total_stake_by(fee); + Self::set_free_balance_creating(dest, new_to_balance); + Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); + } + + Ok(()) } - /// Substrates `value` from the free balance of `who`. If the whole amount cannot be - /// deducted, an error is returned. - /// - /// NOTE: This assumes that the total stake remains unchanged after this operation. If - /// you mean to actually burn value out of existence, then use `slash` instead. - pub fn decrease_free_balance( + /// Register a new account (with existential balance). + fn new_account(who: &T::AccountId, balance: T::Balance) { + T::OnNewAccount::on_new_account(&who); + Self::deposit_event(RawEvent::NewAccount(who.clone(), balance.clone())); + } + + fn reap_account(who: &T::AccountId) { + >::remove(who); + Self::deposit_event(RawEvent::ReapedAccount(who.clone())); + } + + /// Kill an account's free portion. + fn on_free_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::free_balance(who)); + >::remove(who); + >::remove(who); + + T::OnFreeBalanceZero::on_free_balance_zero(who); + + if Self::reserved_balance(who).is_zero() { + Self::reap_account(who); + } + } + + /// Kill an account's reserved portion. + fn on_reserved_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::reserved_balance(who)); + >::remove(who); + + if Self::free_balance(who).is_zero() { + Self::reap_account(who); + } + } + + /// Increase TotalIssuance by Value. + pub fn increase_total_stake_by(value: T::Balance) { + if let Some(v) = >::total_issuance().checked_add(&value) { + >::put(v); + } + } + /// Decrease TotalIssuance by Value. + pub fn decrease_total_stake_by(value: T::Balance) { + if let Some(v) = >::total_issuance().checked_sub(&value) { + >::put(v); + } + } + + /// Returns `Ok` iff the account is able to make a withdrawal of the given amount + /// for the given reason. + /// + /// `Err(...)` with the reason why not otherwise. + pub fn ensure_account_can_withdraw( who: &T::AccountId, - value: T::Balance - ) -> result::Result { - T::EnsureAccountLiquid::ensure_account_liquid(who)?; - let b = Self::free_balance(who); - if b < value { - return Err("account has too few funds") + _amount: T::Balance, + reason: WithdrawReason, + new_balance: T::Balance, + ) -> Result { + match reason { + WithdrawReason::Reserve | WithdrawReason::Transfer if Self::vesting_balance(who) > new_balance => + return Err("vesting balance too high to send value"), + _ => {} + } + let locks = Self::locks(who); + if locks.is_empty() { + return Ok(()) + } + let now = >::block_number(); + if Self::locks(who).into_iter() + .all(|l| now >= l.until || new_balance >= l.amount || !l.reasons.contains(reason)) + { + Ok(()) + } else { + Err("account liquidity restrictions prevent withdrawal") } - Ok(Self::set_free_balance(who, b - value)) } +} - /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the - /// free balance. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - pub fn slash(who: &T::AccountId, value: T::Balance) -> Option { +impl, I: Instance> Currency for Module +where + T::Balance: MaybeSerializeDebug +{ + type Balance = T::Balance; + + fn total_balance(who: &T::AccountId) -> Self::Balance { + Self::free_balance(who) + Self::reserved_balance(who) + } + + fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool { + Self::free_balance(who) >= value + } + + fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { + Self::free_balance(who) + .checked_sub(&value) + .map_or(false, |new_balance| + Self::ensure_account_can_withdraw(who, value, WithdrawReason::Reserve, new_balance).is_ok() + ) + } + + fn total_issuance() -> Self::Balance { + >::get() + } + + fn minimum_balance() -> Self::Balance { + Self::existential_deposit() + } + + fn free_balance(who: &T::AccountId) -> Self::Balance { + >::get(who) + } + + fn reserved_balance(who: &T::AccountId) -> Self::Balance { + >::get(who) + } + + fn slash(who: &T::AccountId, value: Self::Balance) -> Option { let free_balance = Self::free_balance(who); let free_slash = cmp::min(free_balance, value); Self::set_free_balance(who, free_balance - free_slash); @@ -465,10 +449,7 @@ impl Module { } } - /// Adds up to `value` to the free balance of `who`. - /// - /// If `who` doesn't exist, nothing is done and an Err returned. - pub fn reward(who: &T::AccountId, value: T::Balance) -> Result { + fn reward(who: &T::AccountId, value: Self::Balance) -> result::Result<(), &'static str> { if Self::total_balance(who).is_zero() { return Err("beneficiary account must pre-exist"); } @@ -477,27 +458,23 @@ impl Module { Ok(()) } - /// Moves `value` from balance to reserved balance. - /// - /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will - /// be returned to notify of this. This is different behaviour to `unreserve`. - pub fn reserve(who: &T::AccountId, value: T::Balance) -> Result { + fn increase_free_balance_creating(who: &T::AccountId, value: Self::Balance) -> UpdateBalanceOutcome { + Self::set_free_balance_creating(who, Self::free_balance(who) + value) + } + + fn reserve(who: &T::AccountId, value: Self::Balance) -> result::Result<(), &'static str> { let b = Self::free_balance(who); if b < value { return Err("not enough free funds") } - T::EnsureAccountLiquid::ensure_account_liquid(who)?; + let new_balance = b - value; + Self::ensure_account_can_withdraw(who, value, WithdrawReason::Reserve, new_balance)?; Self::set_reserved_balance(who, Self::reserved_balance(who) + value); - Self::set_free_balance(who, b - value); + Self::set_free_balance(who, new_balance); Ok(()) } - /// Moves up to `value` from reserved balance to balance. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - /// NOTE: This is different to `reserve`. - pub fn unreserve(who: &T::AccountId, value: T::Balance) -> Option { + fn unreserve(who: &T::AccountId, value: Self::Balance) -> Option { let b = Self::reserved_balance(who); let actual = cmp::min(b, value); Self::set_free_balance(who, Self::free_balance(who) + actual); @@ -509,11 +486,7 @@ impl Module { } } - /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - pub fn slash_reserved(who: &T::AccountId, value: T::Balance) -> Option { + fn slash_reserved(who: &T::AccountId, value: Self::Balance) -> Option { let b = Self::reserved_balance(who); let slash = cmp::min(b, value); Self::set_reserved_balance(who, b - slash); @@ -525,17 +498,11 @@ impl Module { } } - /// Moves up to `value` from reserved balance of account `slashed` to free balance of account - /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be - /// returned. - /// - /// As much funds up to `value` will be moved as possible. If this is less than `value`, then - /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. - pub fn repatriate_reserved( + fn repatriate_reserved( slashed: &T::AccountId, beneficiary: &T::AccountId, - value: T::Balance - ) -> result::Result, &'static str> { + value: Self::Balance + ) -> result::Result, &'static str> { if Self::total_balance(beneficiary).is_zero() { return Err("beneficiary account must pre-exist"); } @@ -549,172 +516,111 @@ impl Module { Ok(Some(value - slash)) } } +} - fn enum_set_size() -> T::AccountIndex { - T::AccountIndex::sa(ENUM_SET_SIZE) - } +impl, I: Instance> LockableCurrency for Module +where + T::Balance: MaybeSerializeDebug +{ + type Moment = T::BlockNumber; - /// Register a new account (with existential balance). - fn new_account(who: &T::AccountId, balance: T::Balance) -> NewAccountOutcome { - let enum_set_size = Self::enum_set_size(); - let next_set_index = Self::next_enum_set(); - let reclaim_index_magic = T::AccountIndex::sa(RECLAIM_INDEX_MAGIC); - let reclaim_index_modulus = T::AccountIndex::sa(256usize); - let quantization = T::AccountIndex::sa(256usize); - - // A little easter-egg for reclaiming dead indexes.. - let ret = { - // we quantise the number of accounts so it stays constant over a reasonable - // period of time. - let quantized_account_count: T::AccountIndex = (next_set_index * enum_set_size / quantization + One::one()) * quantization; - // then modify the starting balance to be modulo this to allow it to potentially - // identify an account index for reuse. - let maybe_try_index = balance % >::sa(quantized_account_count * reclaim_index_modulus); - let maybe_try_index = As::::as_(maybe_try_index); - - // this identifier must end with magic byte 0x69 to trigger this check (a minor - // optimisation to ensure we don't check most unintended account creations). - if maybe_try_index % reclaim_index_modulus == reclaim_index_magic { - // reuse is probably intended. first, remove magic byte. - let try_index = maybe_try_index / reclaim_index_modulus; - - // then check to see if this balance identifies a dead account index. - let set_index = try_index / enum_set_size; - let mut try_set = Self::enum_set(set_index); - let item_index = (try_index % enum_set_size).as_(); - if item_index < try_set.len() { - if Self::total_balance(&try_set[item_index]).is_zero() { - // yup - this index refers to a dead account. can be reused. - try_set[item_index] = who.clone(); - >::insert(set_index, try_set); - - Self::deposit_event(RawEvent::NewAccount(who.clone(), try_index, NewAccountOutcome::GoodHint)); - - return NewAccountOutcome::GoodHint - } - } - NewAccountOutcome::BadHint + fn set_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + let now = >::block_number(); + let mut new_lock = Some(BalanceLock { id, amount, until, reasons }); + let mut locks = Self::locks(who).into_iter().filter_map(|l| + if l.id == id { + new_lock.take() + } else if l.until > now { + Some(l) } else { - NewAccountOutcome::NoHint - } - }; - - // insert normally as a back up - let mut set_index = next_set_index; - // defensive only: this loop should never iterate since we keep NextEnumSet up to date later. - let mut set = loop { - let set = Self::enum_set(set_index); - if set.len() < ENUM_SET_SIZE { - break set; - } - set_index += One::one(); - }; - - let index = T::AccountIndex::sa(set_index.as_() * ENUM_SET_SIZE + set.len()); - - // update set. - set.push(who.clone()); - - // keep NextEnumSet up to date - if set.len() == ENUM_SET_SIZE { - >::put(set_index + One::one()); - } - - // write set. - >::insert(set_index, set); - - Self::deposit_event(RawEvent::NewAccount(who.clone(), index, ret)); - - ret - } - - fn reap_account(who: &T::AccountId) { - >::remove(who); - Self::deposit_event(RawEvent::ReapedAccount(who.clone())); - } - - /// Kill an account's free portion. - fn on_free_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::free_balance(who)); - >::remove(who); - - T::OnFreeBalanceZero::on_free_balance_zero(who); - - if Self::reserved_balance(who).is_zero() { - Self::reap_account(who); - } - } - - /// Kill an account's reserved portion. - fn on_reserved_too_low(who: &T::AccountId) { - Self::decrease_total_stake_by(Self::reserved_balance(who)); - >::remove(who); - - if Self::free_balance(who).is_zero() { - Self::reap_account(who); + None + }).collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) } + >::insert(who, locks); } - /// Increase TotalIssuance by Value. - pub fn increase_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_issuance().checked_add(&value) { - >::put(v); - } - } - /// Decrease TotalIssuance by Value. - pub fn decrease_total_stake_by(value: T::Balance) { - if let Some(v) = >::total_issuance().checked_sub(&value) { - >::put(v); + fn extend_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + let now = >::block_number(); + let mut new_lock = Some(BalanceLock { id, amount, until, reasons }); + let mut locks = Self::locks(who).into_iter().filter_map(|l| + if l.id == id { + new_lock.take().map(|nl| { + BalanceLock { + id: l.id, + amount: l.amount.max(nl.amount), + until: l.until.max(nl.until), + reasons: l.reasons | nl.reasons, + } + }) + } else if l.until > now { + Some(l) + } else { + None + }).collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) } + >::insert(who, locks); } - pub fn lookup(a: address::Address) -> result::Result { - match a { - address::Address::Id(i) => Ok(i), - address::Address::Index(i) => >::lookup_index(i).ok_or("invalid account index"), - } + fn remove_lock( + id: LockIdentifier, + who: &T::AccountId, + ) { + let now = >::block_number(); + let locks = Self::locks(who).into_iter().filter_map(|l| + if l.until > now && l.id != id { + Some(l) + } else { + None + }).collect::>(); + >::insert(who, locks); } } -pub struct ChainContext(::rstd::marker::PhantomData); -impl Default for ChainContext { - fn default() -> Self { - ChainContext(::rstd::marker::PhantomData) - } -} +impl, I: Instance> TransferAsset for Module { + type Amount = T::Balance; -impl Lookup for ChainContext { - type Source = address::Address; - type Target = T::AccountId; - fn lookup(&self, a: Self::Source) -> result::Result { - >::lookup(a) + fn transfer(from: &T::AccountId, to: &T::AccountId, amount: T::Balance) -> Result { + Self::make_transfer(from, to, amount) } -} -impl CurrentHeight for ChainContext { - type BlockNumber = T::BlockNumber; - fn current_height(&self) -> Self::BlockNumber { - >::block_number() + fn withdraw(who: &T::AccountId, value: T::Balance, reason: WithdrawReason) -> Result { + let b = Self::free_balance(who); + ensure!(b >= value, "account has too few funds"); + let new_balance = b - value; + Self::ensure_account_can_withdraw(who, value, reason, new_balance)?; + Self::set_free_balance(who, new_balance); + Self::decrease_total_stake_by(value); + Ok(()) } -} -impl BlockNumberToHash for ChainContext { - type BlockNumber = T::BlockNumber; - type Hash = T::Hash; - fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option { - Some(>::block_hash(n)) + fn deposit(who: &T::AccountId, value: T::Balance) -> Result { + Self::set_free_balance_creating(who, Self::free_balance(who) + value); + Self::increase_total_stake_by(value); + Ok(()) } } -impl MakePayment for Module { - fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result { - let b = Self::free_balance(transactor); - let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * >::sa(encoded_len as u64); - if b < transaction_fee + Self::existential_deposit() { - return Err("not enough funds for transaction fee"); - } - Self::set_free_balance(transactor, b - transaction_fee); - Self::decrease_total_stake_by(transaction_fee); - Ok(()) +impl, I: Instance> IsDeadAccount for Module +where + T::Balance: MaybeSerializeDebug +{ + fn is_dead_account(who: &T::AccountId) -> bool { + Self::total_balance(who).is_zero() } } diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index 8b9dbce3d4ce2b064c40e8fd4f75e82b4d98c125..55403a12aa4d1c56eb521f09601f3142dc042fa8 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,10 +19,11 @@ #![cfg(test)] use primitives::BuildStorage; -use primitives::testing::{Digest, DigestItem, Header}; +use primitives::{traits::{IdentityLookup}, testing::{Digest, DigestItem, Header}}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use {GenesisConfig, Module, Trait, system}; +use srml_support::impl_outer_origin; +use crate::{GenesisConfig, Module, Trait}; impl_outer_origin!{ pub enum Origin for Runtime {} @@ -39,15 +40,15 @@ impl system::Trait for Runtime { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl Trait for Runtime { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); + type OnNewAccount = (); type Event = (); } @@ -56,6 +57,7 @@ pub struct ExtBuilder { transfer_fee: u64, creation_fee: u64, monied: bool, + vesting: bool, } impl Default for ExtBuilder { fn default() -> Self { @@ -64,6 +66,7 @@ impl Default for ExtBuilder { transfer_fee: 0, creation_fee: 0, monied: false, + vesting: false, } } } @@ -85,6 +88,10 @@ impl ExtBuilder { self.monied = monied; self } + pub fn vesting(mut self, vesting: bool) -> Self { + self.vesting = vesting; + self + } pub fn build(self) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; let balance_factor = if self.existential_deposit > 0 { @@ -98,12 +105,14 @@ impl ExtBuilder { } else { vec![(10, balance_factor), (20, balance_factor)] }, - transaction_base_fee: 0, - transaction_byte_fee: 0, existential_deposit: self.existential_deposit, transfer_fee: self.transfer_fee, creation_fee: self.creation_fee, - reclaim_rebate: 0, + vesting: if self.vesting && self.monied { + vec![(1, 0, 10), (2, 10, 20)] + } else { + vec![] + }, }.build_storage().unwrap().0); t.into() } diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 9ad100fe6179c0e86552a9c1c9c768f8193e2569..7fded7068a47154d9aaf7e48462bef949bf54e53 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,66 +21,135 @@ use super::*; use mock::{Balances, ExtBuilder, Runtime, System}; use runtime_io::with_externalities; +use srml_support::{ + assert_noop, assert_ok, assert_err, + traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, Currency, TransferAsset} +}; + +const ID_1: LockIdentifier = *b"1 "; +const ID_2: LockIdentifier = *b"2 "; +const ID_3: LockIdentifier = *b"3 "; #[test] -fn reward_should_work() { +fn basic_locking_should_work() { with_externalities(&mut ExtBuilder::default().monied(true).build(), || { - assert_eq!(Balances::total_balance(&1), 10); - assert_ok!(Balances::reward(&1, 10)); - assert_eq!(Balances::total_balance(&1), 20); - assert_eq!(>::get(), 110); + assert_eq!(Balances::free_balance(&1), 10); + Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 5), "account liquidity restrictions prevent withdrawal"); }); } #[test] -fn indexing_lookup_should_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build(), - || { - assert_eq!(Balances::lookup_index(0), Some(1)); - assert_eq!(Balances::lookup_index(1), Some(2)); - assert_eq!(Balances::lookup_index(2), Some(3)); - assert_eq!(Balances::lookup_index(3), Some(4)); - assert_eq!(Balances::lookup_index(4), None); - }, - ); +fn partial_locking_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); } #[test] -fn default_indexing_on_new_accounts_should_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build(), - || { - assert_eq!(Balances::lookup_index(4), None); - assert_ok!(Balances::transfer(Some(1).into(), 5.into(), 10.into())); - assert_eq!(Balances::lookup_index(4), Some(5)); - }, - ); +fn lock_removal_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::remove_lock(ID_1, &1); + assert_ok!(>::transfer(&1, &2, 1)); + }); } #[test] -fn default_indexing_on_new_accounts_should_work2() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .creation_fee(50) - .monied(true) - .build(), - || { - assert_eq!(Balances::lookup_index(4), None); - // account 1 has 256 * 10 = 2560, account 5 is not exist, ext_deposit is 10, value is 10 - assert_ok!(Balances::transfer(Some(1).into(), 5.into(), 10.into())); - assert_eq!(Balances::lookup_index(4), Some(5)); +fn lock_replacement_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} - assert_eq!(Balances::free_balance(&1), 256 * 10 - 10 - 50); // 10 is value, 50 is creation_free - }, - ); +#[test] +fn double_locking_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn combination_locking_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); + Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); + Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_value_extension_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_reasons_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); + assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + assert_ok!(>::reserve(&1, 1)); + assert_ok!(>::withdraw(&1, 1, WithdrawReason::TransactionPayment)); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); + assert_ok!(>::transfer(&1, &2, 1)); + assert_noop!(>::reserve(&1, 1), "account liquidity restrictions prevent withdrawal"); + assert_ok!(>::withdraw(&1, 1, WithdrawReason::TransactionPayment)); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); + assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::reserve(&1, 1)); + assert_noop!(>::withdraw(&1, 1, WithdrawReason::TransactionPayment), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_block_number_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + + System::set_block_number(2); + assert_ok!(>::transfer(&1, &2, 1)); + }); +} + +#[test] +fn lock_block_number_extension_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + System::set_block_number(2); + Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); + assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + }); +} + +#[test] +fn lock_reasons_extension_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); + assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + }); } #[test] @@ -92,166 +161,100 @@ fn default_indexing_on_new_accounts_should_not_work2() { .monied(true) .build(), || { - assert_eq!(Balances::lookup_index(4), None); + assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist // account 1 has 256 * 10 = 2560, account 5 is not exist, ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( - Balances::transfer(Some(1).into(), 5.into(), 9.into()), + Balances::transfer(Some(1).into(), 5, 9), "value too low to create account" ); - assert_eq!(Balances::lookup_index(4), None); // account 5 should not exist + assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 256 * 10); }, ); } #[test] -fn dust_account_removal_should_work() { +fn reserved_balance_should_prevent_reclaim_count() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(256 * 10) + .existential_deposit(256 * 1) .monied(true) .build(), || { System::inc_account_nonce(&2); - assert_eq!(System::account_nonce(&2), 1); + assert_eq!(Balances::is_dead_account(&2), false); + assert_eq!(Balances::is_dead_account(&5), true); assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_ok!(Balances::transfer(Some(2).into(), 5.into(), (256 * 10 + 1).into())); // index 1 (account 2) becomes zombie - assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 256 * 10 + 1); - assert_eq!(System::account_nonce(&2), 0); - }, - ); -} - -#[test] -fn dust_account_removal_should_work2() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256 * 10) - .creation_fee(50) - .monied(true) - .build(), - || { - System::inc_account_nonce(&2); + assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved + assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted." + assert_eq!(Balances::total_balance(&2), 256 * 19 + 1); // reserve still exists. + assert_eq!(Balances::is_dead_account(&2), false); assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_ok!(Balances::transfer(Some(2).into(), 5.into(), (256 * 10).into())); // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) - assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 256 * 10); - assert_eq!(System::account_nonce(&2), 0); - }, - ); -} -#[test] -fn reclaim_indexing_on_new_accounts_should_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256 * 1) - .monied(true) - .build(), - || { - assert_eq!(Balances::lookup_index(1), Some(2)); - assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::total_balance(&2), 256 * 20); + assert_ok!(Balances::transfer(Some(4).into(), 5, 256 * 1 + 0x69)); // account 4 tries to take index 1 for account 5. + assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); + assert_eq!(Balances::is_dead_account(&5), false); - assert_ok!(Balances::transfer(Some(2).into(), 5.into(), (256 * 20).into())); // account 2 becomes zombie freeing index 1 for reclaim) - assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed + assert_eq!(Balances::total_balance(&2), 0); // "reserve" account reduced to 255 (below ED) so account deleted + assert_eq!(System::account_nonce(&2), 0); // nonce zero + assert_eq!(Balances::is_dead_account(&2), true); - assert_ok!(Balances::transfer(Some(5).into(), 6.into(), (256 * 1 + 0x69).into())); // account 6 takes index 1. + assert_ok!(Balances::transfer(Some(4).into(), 6, 256 * 1 + 0x69)); // account 4 tries to take index 1 again for account 6. assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(6)); + assert_eq!(Balances::is_dead_account(&6), false); }, ); } -#[test] -fn reclaim_indexing_on_new_accounts_should_work2() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256 * 1) - .monied(true) - .build(), - || { - assert_eq!(Balances::lookup_index(1), Some(2)); - assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::total_balance(&2), 256 * 20); - - assert_ok!(Balances::transfer(Some(2).into(), 5.into(), (256 * 20 - 50).into())); // account 2 becomes zombie freeing index 1 for reclaim) 50 is creation fee - assert_eq!(Balances::total_balance(&2), 0); - assert_ok!(Balances::transfer(Some(5).into(), 6.into(), (256 * 1 + 0x69).into())); // account 6 takes index 1. - assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(6)); - }, - ); +#[test] +fn reward_should_work() { + with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + assert_eq!(Balances::total_balance(&1), 10); + assert_ok!(Balances::reward(&1, 10)); + assert_eq!(Balances::total_balance(&1), 20); + assert_eq!(>::get(), 110); + }); } #[test] -fn reserved_balance_should_prevent_reclaim_count() { +fn dust_account_removal_should_work() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(256 * 1) + .existential_deposit(256 * 10) .monied(true) .build(), || { System::inc_account_nonce(&2); - assert_eq!(Balances::lookup_index(1), Some(2)); - assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::total_balance(&2), 256 * 20); - - assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved - assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted." - assert_eq!(Balances::total_balance(&2), 256 * 19 + 1); // reserve still exists. - assert_eq!(System::account_nonce(&2), 1); - - assert_ok!(Balances::transfer(Some(4).into(), 5.into(), (256 * 1 + 0x69).into())); // account 4 tries to take index 1 for account 5. - assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(2)); // but fails. assert_eq!(System::account_nonce(&2), 1); + assert_eq!(Balances::total_balance(&2), 256 * 20); - assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed - assert_eq!(Balances::total_balance(&2), 0); // "free" account deleted." + assert_ok!(Balances::transfer(Some(2).into(), 5, 256 * 10 + 1)); // index 1 (account 2) becomes zombie + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::total_balance(&5), 256 * 10 + 1); assert_eq!(System::account_nonce(&2), 0); - - assert_ok!(Balances::transfer(Some(4).into(), 6.into(), (256 * 1 + 0x69).into())); // account 4 tries to take index 1 again for account 6. - assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(6)); // and succeeds. }, ); } #[test] -fn reserved_balance_should_prevent_reclaim_count2() { +fn dust_account_removal_should_work2() { with_externalities( &mut ExtBuilder::default() - .existential_deposit(256 * 1) + .existential_deposit(256 * 10) + .creation_fee(50) .monied(true) .build(), || { System::inc_account_nonce(&2); - assert_eq!(Balances::lookup_index(1), Some(2)); - assert_eq!(Balances::lookup_index(4), None); - assert_eq!(Balances::total_balance(&2), 256 * 20); - - assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved - assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted." - assert_eq!(Balances::total_balance(&2), 256 * 19 + 1); // reserve still exists. - assert_eq!(System::account_nonce(&2), 1); - - assert_ok!(Balances::transfer(Some(4).into(), 5.into(), (256 * 1 + 0x69).into())); // account 4 tries to take index 1 for account 5. - assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(2)); // but fails. assert_eq!(System::account_nonce(&2), 1); - - assert_eq!(Balances::slash(&2, 256 * 18 + 2), None); // account 2 gets slashed - assert_eq!(Balances::total_balance(&2), 0); // "free" account deleted." + assert_eq!(Balances::total_balance(&2), 256 * 20); + assert_ok!(Balances::transfer(Some(2).into(), 5, 256 * 10)); // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::total_balance(&5), 256 * 10); assert_eq!(System::account_nonce(&2), 0); - - assert_ok!(Balances::transfer(Some(4).into(), 6.into(), (256 * 1 + 0x69).into())); // account 4 tries to take index 1 again for account 6. - assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); - assert_eq!(Balances::lookup_index(1), Some(6)); // and succeeds. }, ); } @@ -274,23 +277,12 @@ fn balance_transfer_works() { with_externalities(&mut ExtBuilder::default().build(), || { Balances::set_free_balance(&1, 111); Balances::increase_total_stake_by(111); - assert_ok!(Balances::transfer(Some(1).into(), 2.into(), 69.into())); + assert_ok!(Balances::transfer(Some(1).into(), 2, 69)); assert_eq!(Balances::total_balance(&1), 42); assert_eq!(Balances::total_balance(&2), 69); }); } -#[test] -fn balance_reduction_works() { - with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&1, 111); - Balances::increase_total_stake_by(111); - assert_ok!(Balances::decrease_free_balance(&1, 69).map(|_| ())); - assert_eq!(Balances::total_balance(&1), 42); - assert_noop!(Balances::decrease_free_balance(&1, 69).map(|_| ()), "account has too few funds"); - }); -} - #[test] fn reserving_balance_should_work() { with_externalities(&mut ExtBuilder::default().build(), || { @@ -313,7 +305,7 @@ fn balance_transfer_when_reserved_should_not_work() { with_externalities(&mut ExtBuilder::default().build(), || { Balances::set_free_balance(&1, 111); assert_ok!(Balances::reserve(&1, 69)); - assert_noop!(Balances::transfer(Some(1).into(), 2.into(), 69.into()), "balance too low to send value"); + assert_noop!(Balances::transfer(Some(1).into(), 2, 69), "balance too low to send value"); }); } @@ -444,7 +436,7 @@ fn transferring_too_high_value_should_not_panic() { >::insert(2, 1); assert_err!( - Balances::transfer(Some(1).into(), 2.into(), u64::max_value().into()), + Balances::transfer(Some(1).into(), 2, u64::max_value()), "destination balance too high to receive value" ); @@ -472,7 +464,7 @@ fn account_removal_on_free_too_low() { // Transfer funds from account 1 of such amount that after this transfer // the balance of account 1 will be below the exsistential threshold. // This should lead to the removal of all balance of this account. - assert_ok!(Balances::transfer(Some(1).into(), 2.into(), 20.into())); + assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); // Verify free balance removal of account 1. assert_eq!(Balances::free_balance(&1), 0); @@ -492,9 +484,113 @@ fn transfer_overflow_isnt_exploitable() { let evil_value = u64::max_value() - 49; assert_err!( - Balances::transfer(Some(1).into(), 5.into(), evil_value.into()), + Balances::transfer(Some(1).into(), 5, evil_value), "got overflow after adding a fee to value" ); } ); } + +#[test] +fn check_vesting_status() { + with_externalities( + &mut ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build(), + || { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + let user2_free_balance = Balances::free_balance(&2); + assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance + assert_eq!(user2_free_balance, 256 * 20); // Account 2 has free balance + let user1_vesting_schedule = VestingSchedule { + offset: 256 * 10, + per_block: 256, + }; + let user2_vesting_schedule = VestingSchedule { + offset: 256 * 30, + per_block: 256, + }; + assert_eq!(Balances::vesting(&1), Some(user1_vesting_schedule)); // Account 1 has a vesting schedule + assert_eq!(Balances::vesting(&2), Some(user2_vesting_schedule)); // Account 2 has a vesting schedule + + assert_eq!(Balances::vesting_balance(&1), user1_free_balance - 256); // Account 1 has only 256 units vested at block 1 + + System::set_block_number(10); + assert_eq!(System::block_number(), 10); + + assert_eq!(Balances::vesting_balance(&1), 0); // Account 1 has fully vested by block 10 + assert_eq!(Balances::vesting_balance(&2), user2_free_balance); // Account 2 has started vesting by block 10 + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + assert_eq!(Balances::vesting_balance(&1), 0); // Account 1 is still fully vested, and not negative + assert_eq!(Balances::vesting_balance(&2), 0); // Account 2 has fully vested by block 30 + + } + ); +} + +#[test] +fn unvested_balance_should_not_transfer() { + with_externalities( + &mut ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build(), + || { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance + assert_eq!(Balances::vesting_balance(&1), user1_free_balance - 256); // Account 1 has only 256 units vested at block 1 + assert_noop!( + Balances::transfer(Some(1).into(), 2, 256 * 2), + "vesting balance too high to send value" + ); // Account 1 cannot send more than vested amount + } + ); +} + +#[test] +fn vested_balance_should_transfer() { + with_externalities( + &mut ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build(), + || { + System::set_block_number(5); + assert_eq!(System::block_number(), 5); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance + + assert_eq!(Balances::vesting_balance(&1), user1_free_balance - 256 * 5); // Account 1 has 256 * 5 units vested at block 5 + assert_ok!(Balances::transfer(Some(1).into(), 2, 256 * 2)); // Account 1 can now send vested value + } + ); +} + +#[test] +fn extra_balance_should_transfer() { + with_externalities( + &mut ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build(), + || { + assert_eq!(System::block_number(), 1); + assert_ok!(Balances::transfer(Some(3).into(), 1, 256 * 10)); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 256 * 20); // Account 1 has 2560 more free balance than normal + + assert_eq!(Balances::vesting_balance(&1), 256 * 10 - 256); // Account 1 has 256 units vested at block 1 + assert_ok!(Balances::transfer(Some(1).into(), 2, 256 * 5)); // Account 1 can send extra units gained + } + ); +} diff --git a/srml/consensus/Cargo.toml b/srml/consensus/Cargo.toml index d099cb120f2c5212b4f14b12dca889d6424f2485..6adeb90d0248cd34f5701e46509a8e4e8dc38ea2 100644 --- a/srml/consensus/Cargo.toml +++ b/srml/consensus/Cargo.toml @@ -2,28 +2,33 @@ name = "srml-consensus" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", + "serde_derive", "parity-codec/std", "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-system/std", + "primitives/std", + "system/std", + "inherents/std", ] diff --git a/srml/consensus/src/lib.rs b/srml/consensus/src/lib.rs index 2c72642cf680e6e890e30b16588577f779b34d7a..3da15255ae69519e16c2311d05439aa6968e7c9a 100644 --- a/srml/consensus/src/lib.rs +++ b/srml/consensus/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,41 +18,33 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[allow(unused_imports)] -#[macro_use] -extern crate sr_std as rstd; - -#[macro_use] -extern crate srml_support as runtime_support; - -extern crate parity_codec; -#[macro_use] -extern crate parity_codec_derive; - -extern crate sr_primitives as primitives; -extern crate parity_codec as codec; -extern crate srml_system as system; -extern crate substrate_primitives; - -#[cfg(test)] -extern crate sr_io as runtime_io; - +#[cfg(feature = "std")] +use serde_derive::Serialize; use rstd::prelude::*; -use rstd::result; -use parity_codec::Encode; -use runtime_support::{storage, Parameter}; -use runtime_support::storage::StorageValue; -use runtime_support::storage::unhashed::StorageVec; -use primitives::CheckInherentError; -use primitives::traits::{ - MaybeSerializeDebug, Member, ProvideInherent, Block as BlockT -}; +use parity_codec as codec; +use codec::{Encode, Decode}; +use srml_support::{storage, Parameter, decl_storage, decl_module}; +use srml_support::storage::StorageValue; +use srml_support::storage::unhashed::StorageVec; +use primitives::traits::{MaybeSerializeDebug, Member}; use substrate_primitives::storage::well_known_keys; use system::{ensure_signed, ensure_inherent}; +use inherents::{ + ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError +}; + +#[cfg(any(feature = "std", test))] +use substrate_primitives::ed25519::Public as AuthorityId; mod mock; mod tests; +/// The identifier for consensus inherents. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"offlrep0"; + +/// The error type used by this inherent. +pub type InherentError = RuntimeString; + struct AuthorityStorageVec(rstd::marker::PhantomData); impl StorageVec for AuthorityStorageVec { type Item = S; @@ -143,21 +135,18 @@ impl RawLog { // Implementation for tests outside of this crate. #[cfg(any(feature = "std", test))] -impl From> for primitives::testing::DigestItem where N: Into { +impl From> for primitives::testing::DigestItem where N: Into { fn from(log: RawLog) -> primitives::testing::DigestItem { match log { RawLog::AuthoritiesChange(authorities) => - primitives::generic::DigestItem::AuthoritiesChange - ::(authorities.into_iter() + primitives::generic::DigestItem::AuthoritiesChange( + authorities.into_iter() .map(Into::into).collect()), } } } pub trait Trait: system::Trait { - /// The allowed extrinsic position for `note_offline` inherent. - const NOTE_OFFLINE_POSITION: u32; - /// Type for all log entries of this module. type Log: From> + Into>; @@ -178,7 +167,7 @@ decl_storage! { #[serde(with = "substrate_primitives::bytes")] config(code): Vec; - build(|storage: &mut primitives::StorageMap, _: &mut primitives::ChildrenStorageMap, config: &GenesisConfig| { + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { use codec::{Encode, KeyedVec}; let auth_count = config.authorities.len() as u32; @@ -196,19 +185,12 @@ decl_module! { /// Report some misbehaviour. fn report_misbehavior(origin, _report: Vec) { ensure_signed(origin)?; - // TODO: requires extension trait. } /// Note the previous block's validator missed their opportunity to propose a block. fn note_offline(origin, offline: ::Inherent) { ensure_inherent(origin)?; - assert!( - >::extrinsic_index() == Some(T::NOTE_OFFLINE_POSITION), - "note_offline extrinsic must be at position {} in the block", - T::NOTE_OFFLINE_POSITION - ); - T::InherentOfflineReport::handle_report(offline); } @@ -289,34 +271,38 @@ impl Module { } impl ProvideInherent for Module { - type Inherent = ::Inherent; type Call = Call; - - fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { - if ::is_empty(&data) { - vec![] + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + if let Ok(Some(data)) = + data.get_data::<::Inherent>( + &INHERENT_IDENTIFIER + ) + { + if ::is_empty(&data) { + None + } else { + Some(Call::note_offline(data)) + } } else { - vec![(T::NOTE_OFFLINE_POSITION, Call::note_offline(data))] + None } } - fn check_inherent Option<&Self::Call>>( - block: &Block, expected: Self::Inherent, extract_function: &F - ) -> result::Result<(), CheckInherentError> { - let noted_offline = block - .extrinsics() - .get(T::NOTE_OFFLINE_POSITION as usize) - .and_then(|xt| match extract_function(&xt) { - Some(Call::note_offline(ref x)) => Some(x), - _ => None, - }); + fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> { + let offline = match call { + Call::note_offline(ref offline) => offline, + _ => return Ok(()), + }; - // REVIEW: perhaps we should be passing a `None` to check_inherent. - if let Some(noted_offline) = noted_offline { - ::check_inherent(¬ed_offline, &expected) - .map_err(|e| CheckInherentError::Other(e.into()))?; - } + let expected = data + .get_data::<::Inherent>(&INHERENT_IDENTIFIER)? + .ok_or(RuntimeString::from("No `offline_report` found in the inherent data!"))?; - Ok(()) + ::check_inherent( + &offline, &expected + ).map_err(|e| RuntimeString::from(e).into()) } } diff --git a/srml/consensus/src/mock.rs b/srml/consensus/src/mock.rs index 5945a89018a2df419fbc96e26ecb0aba51036e6d..490c1ca078cb20dac7c01dad1873d565c4563f86 100644 --- a/srml/consensus/src/mock.rs +++ b/srml/consensus/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,10 +18,11 @@ #![cfg(test)] -use primitives::{BuildStorage, testing::{Digest, DigestItem, Header}}; +use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}}; +use srml_support::impl_outer_origin; use runtime_io; use substrate_primitives::{H256, Blake2Hasher}; -use {GenesisConfig, Trait, Module, system}; +use crate::{GenesisConfig, Trait, Module}; impl_outer_origin!{ pub enum Origin for Test {} @@ -31,10 +32,9 @@ impl_outer_origin!{ #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; impl Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; type Log = DigestItem; - type SessionKey = u64; - type InherentOfflineReport = ::InstantFinalityReportVec<()>; + type SessionKey = UintAuthorityId; + type InherentOfflineReport = crate::InstantFinalityReportVec<()>; } impl system::Trait for Test { type Origin = Origin; @@ -44,6 +44,7 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; @@ -53,7 +54,7 @@ pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities::default().build_storage().unwrap().0; t.extend(GenesisConfig::{ code: vec![], - authorities, + authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(), }.build_storage().unwrap().0); t.into() } diff --git a/srml/consensus/src/tests.rs b/srml/consensus/src/tests.rs index 9c57739fbc856b8d31d060805169aeedb177197c..23babba1d2e91b895bc8924df96adb714e0c2e00 100644 --- a/srml/consensus/src/tests.rs +++ b/srml/consensus/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,21 +18,27 @@ #![cfg(test)] -use primitives::{generic, testing, traits::{OnFinalise, ProvideInherent}}; +use primitives::{generic, testing::{self, UintAuthorityId}, traits::OnFinalise}; use runtime_io::with_externalities; -use substrate_primitives::H256; -use mock::{Consensus, System, new_test_ext}; +use crate::mock::{Consensus, System, new_test_ext}; +use inherents::{InherentData, ProvideInherent}; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { System::initialise(&1, &Default::default(), &Default::default()); - Consensus::set_authorities(&[4, 5, 6]); + Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); Consensus::on_finalise(1); let header = System::finalise(); assert_eq!(header.digest, testing::Digest { logs: vec![ - generic::DigestItem::AuthoritiesChange::(vec![4, 5, 6]), + generic::DigestItem::AuthoritiesChange( + vec![ + UintAuthorityId(4).into(), + UintAuthorityId(5).into(), + UintAuthorityId(6).into() + ] + ), ], }); }); @@ -54,8 +60,8 @@ fn authorities_change_is_not_logged_when_not_changed() { fn authorities_change_is_not_logged_when_changed_back_to_original() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { System::initialise(&1, &Default::default(), &Default::default()); - Consensus::set_authorities(&[4, 5, 6]); - Consensus::set_authorities(&[1, 2, 3]); + Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); + Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); Consensus::on_finalise(1); let header = System::finalise(); assert_eq!(header.digest, testing::Digest { @@ -68,7 +74,12 @@ fn authorities_change_is_not_logged_when_changed_back_to_original() { fn offline_report_can_be_excluded() { with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { System::initialise(&1, &Default::default(), &Default::default()); - assert!(Consensus::create_inherent_extrinsics(Vec::new()).is_empty()); - assert_eq!(Consensus::create_inherent_extrinsics(vec![0]).len(), 1); + assert!(Consensus::create_inherent(&InherentData::new()).is_none()); + + let offline_report: Vec = vec![0]; + let mut data = InherentData::new(); + data.put_data(super::INHERENT_IDENTIFIER, &offline_report).unwrap(); + + assert!(Consensus::create_inherent(&data).is_some()); }); } diff --git a/srml/contract/COMPLEXITY.md b/srml/contract/COMPLEXITY.md index 511f4e258fbdc5dbff21f5c101ae54d5e545c09f..219d9244ddcc65d6b1ff8164e7f35ecbced8ceb3 100644 --- a/srml/contract/COMPLEXITY.md +++ b/srml/contract/COMPLEXITY.md @@ -281,6 +281,18 @@ This function serializes the address of the caller into the scratch buffer. **complexity**: Assuming that the address is of constant size, this function has constant complexity. +## ext_random_seed + +This function serializes the current block's random seed into the scratch buffer. + +**complexity**: Assuming that the random seed is of constant size, this function has constant complexity. + +## ext_now + +This function serializes the current block's timestamp into the scratch buffer. + +**complexity**: Assuming that the timestamp is of constant size, this function has constant complexity. + ## ext_input_size **complexity**: This function is of constant complexity. diff --git a/srml/contract/Cargo.toml b/srml/contract/Cargo.toml index 0a2ad03029f36a7881ca1dad67160224d74e03ec..0d373978b0c962f3e83d30056f64185a74a3db8e 100644 --- a/srml/contract/Cargo.toml +++ b/srml/contract/Cargo.toml @@ -2,40 +2,47 @@ name = "srml-contract" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false } -pwasm-utils = { version = "0.3", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } +pwasm-utils = { version = "0.6.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } parity-wasm = { version = "0.31", default-features = false } substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-sandbox = { path = "../../core/sr-sandbox", default-features = false } +runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +sandbox = { package = "sr-sandbox", path = "../../core/sr-sandbox", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-balances = { path = "../balances", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +balances = { package = "srml-balances", path = "../balances", default-features = false } +timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } +fees = { package = "srml-fees", path = "../fees", default-features = false } [dev-dependencies] -wabt = "0.7" +wabt = "~0.7.4" assert_matches = "1.1" +hex-literal = "0.1.0" +consensus = { package = "srml-consensus", path = "../consensus" } [features] default = ["std"] std = [ - "serde/std", + "serde", + "serde_derive", "parity-codec/std", - "parity-codec-derive/std", "substrate-primitives/std", - "sr-primitives/std", - "sr-io/std", - "sr-std/std", - "srml-balances/std", - "sr-sandbox/std", + "runtime-primitives/std", + "runtime-io/std", + "rstd/std", + "balances/std", + "sandbox/std", "srml-support/std", - "srml-system/std", + "system/std", + "timestamp/std", "parity-wasm/std", "pwasm-utils/std", + "fees/std", ] diff --git a/srml/contract/src/account_db.rs b/srml/contract/src/account_db.rs index d7ff094003c97e52d014773220a63ea0cd644eea..52fd80a8a2d3f3f2b3f7da7b645aed5894090228 100644 --- a/srml/contract/src/account_db.rs +++ b/srml/contract/src/account_db.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,17 +16,17 @@ //! Auxilliaries to help with managing partial changes to accounts state. -use super::{CodeOf, StorageOf, Trait}; -use double_map::StorageDoubleMap; +use super::{CodeHash, CodeHashOf, StorageOf, Trait}; +use {balances, system}; use rstd::cell::RefCell; use rstd::collections::btree_map::{BTreeMap, Entry}; use rstd::prelude::*; -use runtime_support::StorageMap; -use {balances, system}; +use srml_support::{StorageMap, StorageDoubleMap, traits::UpdateBalanceOutcome}; pub struct ChangeEntry { balance: Option, - code: Option>, + /// In the case the outer option is None, the code_hash remains untouched, while providing `Some(None)` signifies a removing of the code in question + code: Option>>, storage: BTreeMap, Option>>, } @@ -45,7 +45,7 @@ pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry pub trait AccountDb { fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option>; - fn get_code(&self, account: &T::AccountId) -> Vec; + fn get_code(&self, account: &T::AccountId) -> Option>; fn get_balance(&self, account: &T::AccountId) -> T::Balance; fn commit(&mut self, change_set: ChangeSet); @@ -54,10 +54,10 @@ pub trait AccountDb { pub struct DirectAccountDb; impl AccountDb for DirectAccountDb { fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option> { - >::get(account.clone(), location.to_vec()) + >::get(account, &location.to_vec()) } - fn get_code(&self, account: &T::AccountId) -> Vec { - >::get(account) + fn get_code(&self, account: &T::AccountId) -> Option> { + >::get(account) } fn get_balance(&self, account: &T::AccountId) -> T::Balance { balances::Module::::free_balance(account) @@ -65,23 +65,27 @@ impl AccountDb for DirectAccountDb { fn commit(&mut self, s: ChangeSet) { for (address, changed) in s.into_iter() { if let Some(balance) = changed.balance { - if let balances::UpdateBalanceOutcome::AccountKilled = + if let UpdateBalanceOutcome::AccountKilled = balances::Module::::set_free_balance_creating(&address, balance) { // Account killed. This will ultimately lead to calling `OnFreeBalanceZero` callback - // which will make removal of CodeOf and StorageOf for this account. + // which will make removal of CodeHashOf and StorageOf for this account. // In order to avoid writing over the deleted properties we `continue` here. continue; } } if let Some(code) = changed.code { - >::insert(&address, &code); + if let Some(code) = code { + >::insert(&address, code); + } else { + >::remove(&address); + } } for (k, v) in changed.storage.into_iter() { if let Some(value) = v { - >::insert(address.clone(), k, value); + >::insert(&address, &k, value); } else { - >::remove(address.clone(), k); + >::remove(&address, &k); } } } @@ -117,7 +121,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { .storage .insert(location, value); } - pub fn set_code(&mut self, account: &T::AccountId, code: Vec) { + pub fn set_code(&mut self, account: &T::AccountId, code: Option>) { self.local .borrow_mut() .entry(account.clone()) @@ -142,7 +146,7 @@ impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { .cloned() .unwrap_or_else(|| self.underlying.get_storage(account, location)) } - fn get_code(&self, account: &T::AccountId) -> Vec { + fn get_code(&self, account: &T::AccountId) -> Option> { self.local .borrow() .get(account) diff --git a/srml/contract/src/double_map.rs b/srml/contract/src/double_map.rs deleted file mode 100644 index bd154e100eafcab8c0c5ac0ffc69f5b61ee00d32..0000000000000000000000000000000000000000 --- a/srml/contract/src/double_map.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! An implementation of double map backed by storage. -//! -//! This implementation is somewhat specialized to the tracking of the storage of accounts. - -use rstd::prelude::*; -use codec::{Codec, Encode}; -use runtime_support::storage::unhashed; -use runtime_io::{blake2_256, twox_128}; - -/// Returns only a first part of the storage key. -/// -/// Hashed by XX. -fn first_part_of_key(k1: M::Key1) -> [u8; 16] { - let mut raw_prefix = Vec::new(); - raw_prefix.extend(M::PREFIX); - raw_prefix.extend(Encode::encode(&k1)); - twox_128(&raw_prefix) -} - -/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`. -/// -/// The first part is hased by XX and then concatenated with a blake2 hash of `k2`. -fn full_key(k1: M::Key1, k2: M::Key2) -> Vec { - let first_part = first_part_of_key::(k1); - let second_part = blake2_256(&Encode::encode(&k2)); - - let mut k = Vec::new(); - k.extend(&first_part); - k.extend(&second_part); - k -} - -/// An implementation of a map with a two keys. -/// -/// It provides an important ability to efficiently remove all entries -/// that have a common first key. -/// -/// # Mapping of keys to a storage path -/// -/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. -/// The first part is a XX hash of a concatenation of the `PREFIX` and `Key1`. And the second part -/// is a blake2 hash of a `Key2`. -/// -/// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and -/// thus will be susceptible for a untrusted input. -pub trait StorageDoubleMap { - type Key1: Codec; - type Key2: Codec; - type Value: Codec + Default; - - const PREFIX: &'static [u8]; - - /// Insert an entry into this map. - fn insert(k1: Self::Key1, k2: Self::Key2, val: Self::Value) { - unhashed::put(&full_key::(k1, k2)[..], &val); - } - - /// Remove an entry from this map. - fn remove(k1: Self::Key1, k2: Self::Key2) { - unhashed::kill(&full_key::(k1, k2)[..]); - } - - /// Get an entry from this map. - /// - /// If there is entry stored under the given keys, returns `None`. - fn get(k1: Self::Key1, k2: Self::Key2) -> Option { - unhashed::get(&full_key::(k1, k2)[..]) - } - - /// Returns `true` if value under the specified keys exists. - fn exists(k1: Self::Key1, k2: Self::Key2) -> bool { - unhashed::exists(&full_key::(k1, k2)[..]) - } - - /// Removes all entries that shares the `k1` as the first key. - fn remove_prefix(k1: Self::Key1) { - unhashed::kill_prefix(&first_part_of_key::(k1)) - } -} diff --git a/srml/contract/src/exec.rs b/srml/contract/src/exec.rs index 25dfe2e8fe0c4d42da9564b127c58da7e5cca43e..0dbe8b32604101cefb5d1e53d76a4dee80da0c42 100644 --- a/srml/contract/src/exec.rs +++ b/srml/contract/src/exec.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,68 +14,295 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use super::{ContractAddressFor, Trait, Event, RawEvent, Config}; -use account_db::{AccountDb, OverlayAccountDb}; -use gas::GasMeter; -use vm; +use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait}; +use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; +use crate::gas::{GasMeter, Token, approx_gas_for_balance}; use rstd::prelude::*; -use runtime_primitives::traits::{Zero, CheckedAdd, CheckedSub}; -use balances::{self, EnsureAccountLiquid}; +use runtime_primitives::traits::{CheckedAdd, CheckedSub, Zero}; +use srml_support::traits::WithdrawReason; +use timestamp; -// TODO: Add logs -pub struct CreateReceipt { - pub address: T::AccountId, +pub type BalanceOf = ::Balance; +pub type AccountIdOf = ::AccountId; +pub type CallOf = ::Call; +pub type MomentOf = ::Moment; +pub type SeedOf = ::Hash; + +#[cfg_attr(test, derive(Debug))] +pub struct InstantiateReceipt { + pub address: AccountId, +} + +#[cfg_attr(test, derive(Debug))] +pub struct CallReceipt { + /// Output data received as a result of a call. + pub output_data: Vec, +} + +/// An interface that provides access to the external environment in which the +/// smart-contract is executed. +/// +/// This interface is specialised to an account of the executing code, so all +/// operations are implicitly performed on that account. +pub trait Ext { + type T: Trait; + + /// Returns the storage entry of the executing account by the given `key`. + /// + /// Returns `None` if the `key` wasn't previously set by `set_storage` or + /// was deleted. + fn get_storage(&self, key: &[u8]) -> Option>; + + /// Sets the storage entry by the given key to the specified value. + /// + /// If `value` is `None` then the storage entry is deleted. + fn set_storage(&mut self, key: &[u8], value: Option>); + + /// Instantiate a contract from the given code. + /// + /// The newly created account will be associated with `code`. `value` specifies the amount of value + /// transfered from this to the newly created account (also known as endowment). + fn instantiate( + &mut self, + code: &CodeHash, + value: BalanceOf, + gas_meter: &mut GasMeter, + input_data: &[u8], + ) -> Result>, &'static str>; + + /// Call (possibly transfering some amount of funds) into the specified account. + fn call( + &mut self, + to: &AccountIdOf, + value: BalanceOf, + gas_meter: &mut GasMeter, + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, + ) -> Result; + + /// Notes a call dispatch. + fn note_dispatch_call(&mut self, call: CallOf); + + /// Returns a reference to the account id of the caller. + fn caller(&self) -> &AccountIdOf; + + /// Returns a reference to the account id of the current contract. + fn address(&self) -> &AccountIdOf; + + + /// Returns the balance of the current contract. + /// + /// The `value_transferred` is already added. + fn balance(&self) -> BalanceOf; + + /// Returns the value transfered along with this call or as endowment. + fn value_transferred(&self) -> BalanceOf; + + /// Returns a reference to the timestamp of the current block + fn now(&self) -> &MomentOf; + + /// Returns a reference to the random seed for the current block + fn random_seed(&self) -> &SeedOf; +} + +/// Loader is a companion of the `Vm` trait. It loads an appropriate abstract +/// executable to be executed by an accompanying `Vm` implementation. +pub trait Loader { + type Executable; + + /// Load the initializer portion of the code specified by the `code_hash`. This + /// executable is called upon instantiation. + fn load_init(&self, code_hash: &CodeHash) -> Result; + /// Load the main portion of the code specified by the `code_hash`. This executable + /// is called for each call to a contract. + fn load_main(&self, code_hash: &CodeHash) -> Result; +} + +/// An `EmptyOutputBuf` is used as an optimization for reusing empty vectors when +/// available. +/// +/// You can create this structure from a spare vector if you have any and then +/// you can fill it (only once), converting it to `OutputBuf`. +pub struct EmptyOutputBuf(Vec); + +impl EmptyOutputBuf { + /// Create an output buffer from a spare vector which is not longer needed. + /// + /// All contents are discarded, but capacity is preserved. + pub fn from_spare_vec(mut v: Vec) -> Self { + v.clear(); + EmptyOutputBuf(v) + } + + /// Create an output buffer ready for receiving a result. + /// + /// Use this function to create output buffer if you don't have a spare + /// vector. Otherwise, use `from_spare_vec`. + pub fn new() -> Self { + EmptyOutputBuf(Vec::new()) + } + + /// Write to the buffer result of the specified size. + /// + /// Calls closure with the buffer of the requested size. + pub fn fill Result<(), E>>(mut self, size: usize, f: F) -> Result { + assert!(self.0.len() == 0, "the vector is always cleared; it's written only once"); + self.0.resize(size, 0); + f(&mut self.0).map(|()| OutputBuf(self.0)) + } } -// TODO: Add logs. -pub struct CallReceipt; +/// `OutputBuf` is the end result of filling an `EmptyOutputBuf`. +pub struct OutputBuf(Vec); -pub struct ExecutionContext<'a, T: Trait + 'a> { - // typically should be dest +#[must_use] +pub enum VmExecResult { + Ok, + Returned(OutputBuf), + /// A program executed some forbidden operation. + /// + /// This can include, e.g.: division by 0, OOB access or failure to satisfy some precondition + /// of a system call. + /// + /// Contains some vm-specific description of an trap. + Trap(&'static str), +} + +impl VmExecResult { + pub fn into_result(self) -> Result, &'static str> { + match self { + VmExecResult::Ok => Ok(Vec::new()), + VmExecResult::Returned(buf) => Ok(buf.0), + VmExecResult::Trap(description) => Err(description), + } + } +} + +/// A trait that represent a virtual machine. +/// +/// You can view a virtual machine as something that takes code, an input data buffer, +/// queries it and/or performs actions on the given `Ext` and optionally +/// returns an output data buffer. The type of code depends on the particular virtual machine. +/// +/// Execution of code can end by either implicit termination (that is, reached the end of +/// executable), explicit termination via returning a buffer or termination due to a trap. +/// +/// You can optionally provide a vector for collecting output if a spare is available. If you don't have +/// it will be created anyway. +pub trait Vm { + type Executable; + + fn execute>( + &self, + exec: &Self::Executable, + ext: &mut E, + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, + gas_meter: &mut GasMeter, + ) -> VmExecResult; +} + +#[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub enum ExecFeeToken { + /// Base fee charged for a call. + Call, + /// Base fee charged for a instantiate. + Instantiate, +} + +impl Token for ExecFeeToken { + type Metadata = Config; + #[inline] + fn calculate_amount(&self, metadata: &Config) -> T::Gas { + match *self { + ExecFeeToken::Call => metadata.call_base_fee, + ExecFeeToken::Instantiate => metadata.instantiate_base_fee, + } + } +} + +pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { pub self_account: T::AccountId, pub overlay: OverlayAccountDb<'a, T>, pub depth: usize, pub events: Vec>, + pub calls: Vec<(T::AccountId, T::Call)>, pub config: &'a Config, + pub vm: &'a V, + pub loader: &'a L, } -impl<'a, T: Trait> ExecutionContext<'a, T> { - /// Make a call to the specified address. +impl<'a, T, E, V, L> ExecutionContext<'a, T, V, L> +where + T: Trait, + L: Loader, + V: Vm, +{ + /// Create the top level execution context. + /// + /// The specified `origin` address will be used as `sender` for + pub fn top_level(origin: T::AccountId, cfg: &'a Config, vm: &'a V, loader: &'a L) -> Self { + let overlay = OverlayAccountDb::::new(&DirectAccountDb); + ExecutionContext { + self_account: origin, + depth: 0, + overlay, + events: Vec::new(), + calls: Vec::new(), + config: &cfg, + vm: &vm, + loader: &loader, + } + } + + fn nested(&self, overlay: OverlayAccountDb<'a, T>, dest: T::AccountId) -> Self { + ExecutionContext { + overlay: overlay, + self_account: dest, + depth: self.depth + 1, + events: Vec::new(), + calls: Vec::new(), + config: self.config, + vm: self.vm, + loader: self.loader, + } + } + + /// Make a call to the specified address, optionally transfering some funds. pub fn call( &mut self, - caller: T::AccountId, dest: T::AccountId, value: T::Balance, gas_meter: &mut GasMeter, - data: &[u8], - output_data: &mut Vec, + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, ) -> Result { if self.depth == self.config.max_depth as usize { return Err("reached maximum depth, cannot make a call"); } - if gas_meter.charge(self.config.call_base_fee).is_out_of_gas() { + if gas_meter + .charge(self.config, ExecFeeToken::Call) + .is_out_of_gas() + { return Err("not enough gas to pay base call fee"); } - let dest_code = self.overlay.get_code(&dest); + let dest_code_hash = self.overlay.get_code(&dest); + let mut output_data = Vec::new(); - let (change_set, events) = { - let mut overlay = OverlayAccountDb::new(&self.overlay); - - let mut nested = ExecutionContext { - overlay: overlay, - self_account: dest.clone(), - depth: self.depth + 1, - events: Vec::new(), - config: self.config, - }; + let (change_set, events, calls) = { + let mut nested = self.nested( + OverlayAccountDb::new(&self.overlay), + dest.clone() + ); if value > T::Balance::zero() { transfer( gas_meter, - false, + TransferCause::Call, &self.self_account, &dest, value, @@ -83,108 +310,155 @@ impl<'a, T: Trait> ExecutionContext<'a, T> { )?; } - if !dest_code.is_empty() { - vm::execute( - &dest_code, - data, - output_data, - &mut CallContext { - ctx: &mut nested, - caller: caller, - }, - &self.config.schedule, - gas_meter, - ).map_err(|_| "vm execute returned error while call")?; + if let Some(dest_code_hash) = dest_code_hash { + let executable = self.loader.load_main(&dest_code_hash)?; + output_data = self + .vm + .execute( + &executable, + &mut CallContext { + ctx: &mut nested, + caller: self.self_account.clone(), + value_transferred: value, + timestamp: timestamp::Module::::now(), + random_seed: system::Module::::random_seed(), + }, + input_data, + empty_output_buf, + gas_meter, + ) + .into_result()?; } - (nested.overlay.into_change_set(), nested.events) + (nested.overlay.into_change_set(), nested.events, nested.calls) }; self.overlay.commit(change_set); self.events.extend(events); + self.calls.extend(calls); - Ok(CallReceipt) + Ok(CallReceipt { output_data }) } - pub fn create( + pub fn instantiate( &mut self, - caller: T::AccountId, endowment: T::Balance, gas_meter: &mut GasMeter, - init_code: &[u8], - data: &[u8], - ) -> Result, &'static str> { + code_hash: &CodeHash, + input_data: &[u8], + ) -> Result, &'static str> { if self.depth == self.config.max_depth as usize { return Err("reached maximum depth, cannot create"); } - if gas_meter.charge(self.config.create_base_fee).is_out_of_gas() { - return Err("not enough gas to pay base create fee"); + if gas_meter + .charge(self.config, ExecFeeToken::Instantiate) + .is_out_of_gas() + { + return Err("not enough gas to pay base instantiate fee"); } - let dest = T::DetermineContractAddress::contract_address_for(init_code, data, &self.self_account); + let dest = T::DetermineContractAddress::contract_address_for( + code_hash, + input_data, + &self.self_account, + ); - if !self.overlay.get_code(&dest).is_empty() { + if self.overlay.get_code(&dest).is_some() { // It should be enough to check only the code. return Err("contract already exists"); } - let (change_set, events) = { + let (change_set, events, calls) = { let mut overlay = OverlayAccountDb::new(&self.overlay); + overlay.set_code(&dest, Some(code_hash.clone())); + let mut nested = self.nested(overlay, dest.clone()); - let mut nested = ExecutionContext { - overlay: overlay, - self_account: dest.clone(), - depth: self.depth + 1, - events: Vec::new(), - config: self.config, - }; + // Send funds unconditionally here. If the `endowment` is below existential_deposit + // then error will be returned here. + transfer( + gas_meter, + TransferCause::Instantiate, + &self.self_account, + &dest, + endowment, + &mut nested, + )?; - if endowment > T::Balance::zero() { - transfer( + let executable = self.loader.load_init(&code_hash)?; + self.vm + .execute( + &executable, + &mut CallContext { + ctx: &mut nested, + caller: self.self_account.clone(), + value_transferred: endowment, + timestamp: timestamp::Module::::now(), + random_seed: system::Module::::random_seed(), + }, + input_data, + EmptyOutputBuf::new(), gas_meter, - true, - &self.self_account, - &dest, - endowment, - &mut nested, - )?; - } + ) + .into_result()?; - let mut contract_code = Vec::new(); - vm::execute( - init_code, - data, - &mut contract_code, - &mut CallContext { - ctx: &mut nested, - caller: caller, - }, - &self.config.schedule, - gas_meter, - ).map_err(|_| "vm execute returned error while create")?; + // Deposit an instantiation event. + nested.events.push(RawEvent::Instantiated(self.self_account.clone(), dest.clone())); - nested.overlay.set_code(&dest, contract_code); - (nested.overlay.into_change_set(), nested.events) + (nested.overlay.into_change_set(), nested.events, nested.calls) }; self.overlay.commit(change_set); self.events.extend(events); + self.calls.extend(calls); - Ok(CreateReceipt { - address: dest, - }) + Ok(InstantiateReceipt { address: dest }) } } +#[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub enum TransferFeeKind { + ContractInstantiate, + AccountCreate, + Transfer, +} + +#[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub struct TransferFeeToken { + kind: TransferFeeKind, + gas_price: Balance, +} + +impl Token for TransferFeeToken { + type Metadata = Config; + + #[inline] + fn calculate_amount(&self, metadata: &Config) -> T::Gas { + let balance_fee = match self.kind { + TransferFeeKind::ContractInstantiate => metadata.contract_account_instantiate_fee, + TransferFeeKind::AccountCreate => metadata.account_create_fee, + TransferFeeKind::Transfer => metadata.transfer_fee, + }; + approx_gas_for_balance::(self.gas_price, balance_fee) + } +} + +/// Describes possible transfer causes. +enum TransferCause { + Call, + Instantiate, +} + /// Transfer some funds from `transactor` to `dest`. /// /// All balance changes are performed in the `overlay`. /// /// This function also handles charging the fee. The fee depends -/// on whether the transfer happening because of contract creation -/// (transfering endowment), specified by `contract_create` flag, -/// or because of a transfer via `call`. +/// on whether the transfer happening because of contract instantiation +/// (transfering endowment) or because of a transfer via `call`. This +/// is specified using the `cause` parameter. /// /// NOTE: that the fee is denominated in `T::Balance` units, but /// charged in `T::Gas` from the provided `gas_meter`. This means @@ -193,38 +467,47 @@ impl<'a, T: Trait> ExecutionContext<'a, T> { /// NOTE: that we allow for draining all funds of the contract so it /// can go below existential deposit, essentially giving a contract /// the chance to give up it's life. -fn transfer<'a, T: Trait>( +fn transfer<'a, T: Trait, V: Vm, L: Loader>( gas_meter: &mut GasMeter, - contract_create: bool, + cause: TransferCause, transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance, - ctx: &mut ExecutionContext<'a, T>, + ctx: &mut ExecutionContext<'a, T, V, L>, ) -> Result<(), &'static str> { + use self::TransferCause::*; + use self::TransferFeeKind::*; + let to_balance = ctx.overlay.get_balance(dest); - // This flag is totally distinct from `contract_create`, which shows if this function - // is called from `CREATE` procedure. - // // `would_create` indicates whether the account will be created if this transfer gets executed. - // For example, we can create a contract at the address which already has some funds. In this - // case `contract_create` will be `true` but `would_create` will be `false`. Another example would - // be when this function is called from `CALL`, but `dest` doesn't exist yet. In this case - // `contract_create` will be `false` but `would_create` will be `true`. + // This flag is orthogonal to `cause. + // For example, we can instantiate a contract at the address which already has some funds. In this + // `would_create` will be `false`. Another example would be when this function is called from `call`, + // and account with the address `dest` doesn't exist yet `would_create` will be `true`. let would_create = to_balance.is_zero(); - let fee: T::Balance = match (contract_create, would_create) { - // If this function is called from `CREATE` routine, then we always - // charge contract account creation fee. - (true, _) => ctx.config.contract_account_create_fee, + let token = { + let kind: TransferFeeKind = match cause { + // If this function is called from `Instantiate` routine, then we always + // charge contract account creation fee. + Instantiate => ContractInstantiate, - // Otherwise the fee depends on whether we create a new account or transfer - // to an existing one. - (false, true) => ctx.config.account_create_fee, - (false, false) => ctx.config.transfer_fee, + // Otherwise the fee depends on whether we create a new account or transfer + // to an existing one. + Call => if would_create { + TransferFeeKind::AccountCreate + } else { + TransferFeeKind::Transfer + }, + }; + TransferFeeToken { + kind, + gas_price: gas_meter.gas_price(), + } }; - if gas_meter.charge_by_balance(fee).is_out_of_gas() { + if gas_meter.charge(ctx.config, token).is_out_of_gas() { return Err("not enough gas to pay transfer fee"); } @@ -237,7 +520,7 @@ fn transfer<'a, T: Trait>( if would_create && value < ctx.config.existential_deposit { return Err("value too low to create account"); } - ::EnsureAccountLiquid::ensure_account_liquid(transactor)?; + >::ensure_account_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; let new_to_balance = match to_balance.checked_add(&value) { Some(b) => b, @@ -247,18 +530,27 @@ fn transfer<'a, T: Trait>( if transactor != dest { ctx.overlay.set_balance(transactor, new_from_balance); ctx.overlay.set_balance(dest, new_to_balance); - ctx.events.push(RawEvent::Transfer(transactor.clone(), dest.clone(), value)); + ctx.events + .push(RawEvent::Transfer(transactor.clone(), dest.clone(), value)); } Ok(()) } -struct CallContext<'a, 'b: 'a, T: Trait + 'b> { - ctx: &'a mut ExecutionContext<'b, T>, +struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm + 'b, L: Loader> { + ctx: &'a mut ExecutionContext<'b, T, V, L>, caller: T::AccountId, + value_transferred: T::Balance, + timestamp: T::Moment, + random_seed: T::Hash, } -impl<'a, 'b: 'a, T: Trait + 'b> vm::Ext for CallContext<'a, 'b, T> { +impl<'a, 'b: 'a, T, E, V, L> Ext for CallContext<'a, 'b, T, V, L> +where + T: Trait + 'b, + V: Vm, + L: Loader, +{ type T = T; fn get_storage(&self, key: &[u8]) -> Option> { @@ -271,17 +563,14 @@ impl<'a, 'b: 'a, T: Trait + 'b> vm::Ext for CallContext<'a, 'b, T> { .set_storage(&self.ctx.self_account, key.to_vec(), value) } - fn create( + fn instantiate( &mut self, - code: &[u8], + code_hash: &CodeHash, endowment: T::Balance, gas_meter: &mut GasMeter, - data: &[u8], - ) -> Result, ()> { - let caller = self.ctx.self_account.clone(); - self.ctx - .create(caller, endowment, gas_meter, code, &data) - .map_err(|_| ()) + input_data: &[u8], + ) -> Result>, &'static str> { + self.ctx.instantiate(endowment, gas_meter, code_hash, input_data) } fn call( @@ -289,17 +578,765 @@ impl<'a, 'b: 'a, T: Trait + 'b> vm::Ext for CallContext<'a, 'b, T> { to: &T::AccountId, value: T::Balance, gas_meter: &mut GasMeter, - data: &[u8], - output_data: &mut Vec, - ) -> Result<(), ()> { - let caller = self.ctx.self_account.clone(); + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, + ) -> Result { self.ctx - .call(caller, to.clone(), value, gas_meter, data, output_data) - .map_err(|_| ()) - .map(|_| ()) + .call(to.clone(), value, gas_meter, input_data, empty_output_buf) + } + + /// Notes a call dispatch. + fn note_dispatch_call(&mut self, call: CallOf) { + self.ctx.calls.push( + (self.ctx.self_account.clone(), call) + ); + } + + fn address(&self) -> &T::AccountId { + &self.ctx.self_account } fn caller(&self) -> &T::AccountId { &self.caller } + + fn balance(&self) -> T::Balance { + self.ctx.overlay.get_balance(&self.ctx.self_account) + } + + fn value_transferred(&self) -> T::Balance { + self.value_transferred + } + + fn random_seed(&self) -> &T::Hash { + &self.random_seed + } + + fn now(&self) -> &T::Moment { + &self.timestamp + } +} + +/// These tests exercise the executive layer. +/// +/// In these tests the VM/loader are mocked. Instead of dealing with wasm bytecode they use simple closures. +/// This allows you to tackle executive logic more thoroughly without writing a +/// wasm VM code. +/// +/// Because it's the executive layer: +/// +/// - no gas meter setup and teardown logic. All balances are *AFTER* gas purchase. +/// - executive layer doesn't alter any storage! +#[cfg(test)] +mod tests { + use super::{ + ExecFeeToken, ExecutionContext, Ext, Loader, EmptyOutputBuf, TransferFeeKind, TransferFeeToken, + Vm, VmExecResult, InstantiateReceipt, RawEvent, + }; + use crate::account_db::AccountDb; + use crate::gas::GasMeter; + use crate::tests::{ExtBuilder, Test}; + use crate::{CodeHash, Config}; + use runtime_io::with_externalities; + use std::cell::RefCell; + use std::collections::HashMap; + use std::marker::PhantomData; + use std::rc::Rc; + use assert_matches::assert_matches; + + const ALICE: u64 = 1; + const BOB: u64 = 2; + const CHARLIE: u64 = 3; + + struct MockCtx<'a> { + ext: &'a mut dyn Ext, + input_data: &'a [u8], + empty_output_buf: Option, + gas_meter: &'a mut GasMeter, + } + + #[derive(Clone)] + struct MockExecutable<'a>(Rc VmExecResult + 'a>); + + impl<'a> MockExecutable<'a> { + fn new(f: impl Fn(MockCtx) -> VmExecResult + 'a) -> Self { + MockExecutable(Rc::new(f)) + } + } + + struct MockLoader<'a> { + map: HashMap, MockExecutable<'a>>, + counter: u64, + } + + impl<'a> MockLoader<'a> { + fn empty() -> Self { + MockLoader { + map: HashMap::new(), + counter: 0, + } + } + + fn insert(&mut self, f: impl Fn(MockCtx) -> VmExecResult + 'a) -> CodeHash { + // Generate code hashes as monotonically increasing values. + let code_hash = ::Hash::from_low_u64_be(self.counter); + + self.counter += 1; + self.map.insert(code_hash, MockExecutable::new(f)); + code_hash + } + } + + struct MockVm<'a> { + _marker: PhantomData<&'a ()>, + } + + impl<'a> MockVm<'a> { + fn new() -> Self { + MockVm { _marker: PhantomData } + } + } + + impl<'a> Loader for MockLoader<'a> { + type Executable = MockExecutable<'a>; + + fn load_init(&self, code_hash: &CodeHash) -> Result { + self.map + .get(code_hash) + .cloned() + .ok_or_else(|| "code not found") + } + fn load_main(&self, code_hash: &CodeHash) -> Result { + self.map + .get(code_hash) + .cloned() + .ok_or_else(|| "code not found") + } + } + + impl<'a> Vm for MockVm<'a> { + type Executable = MockExecutable<'a>; + + fn execute>( + &self, + exec: &MockExecutable, + ext: &mut E, + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, + gas_meter: &mut GasMeter, + ) -> VmExecResult { + (exec.0)(MockCtx { + ext, + input_data, + empty_output_buf: Some(empty_output_buf), + gas_meter, + }) + } + } + + #[test] + fn it_works() { + let value = Default::default(); + let mut gas_meter = GasMeter::::with_limit(10000, 1); + let data = vec![]; + + let vm = MockVm::new(); + + let test_data = Rc::new(RefCell::new(vec![0usize])); + + let mut loader = MockLoader::empty(); + let exec_ch = loader.insert(|_ctx| { + test_data.borrow_mut().push(1); + VmExecResult::Ok + }); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_code(&BOB, Some(exec_ch)); + + assert_matches!( + ctx.call(BOB, value, &mut gas_meter, &data, EmptyOutputBuf::new()), + Ok(_) + ); + }); + + assert_eq!(&*test_data.borrow(), &vec![0, 1]); + } + + #[test] + fn base_fees() { + let origin = ALICE; + let dest = BOB; + + // This test verifies that base fee for call is taken. + with_externalities(&mut ExtBuilder::default().build(), || { + let vm = MockVm::new(); + let loader = MockLoader::empty(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 0); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.call(dest, 0, &mut gas_meter, &[], EmptyOutputBuf::new()); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!(toks, ExecFeeToken::Call,); + }); + + // This test verifies that base fee for instantiation is taken. + with_externalities(&mut ExtBuilder::default().build(), || { + let mut loader = MockLoader::empty(); + let code = loader.insert(|_| VmExecResult::Ok); + + let vm = MockVm::new(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + + ctx.overlay.set_balance(&origin, 100); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.instantiate(0, &mut gas_meter, &code, &[]); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!(toks, ExecFeeToken::Instantiate,); + }); + } + + #[test] + fn transfer_works() { + // This test verifies that a contract is able to transfer + // some funds to another account. + let origin = ALICE; + let dest = BOB; + + let vm = MockVm::new(); + let loader = MockLoader::empty(); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 0); + + let result = ctx.call( + dest, + 55, + &mut GasMeter::::with_limit(1000, 1), + &[], + EmptyOutputBuf::new(), + ); + assert_matches!(result, Ok(_)); + assert_eq!(ctx.overlay.get_balance(&origin), 45); + assert_eq!(ctx.overlay.get_balance(&dest), 55); + }); + } + + #[test] + fn transfer_fees() { + let origin = ALICE; + let dest = BOB; + + // This test sends 50 units of currency to a non-existent account. + // This should create lead to creation of a new account thus + // a fee should be charged. + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let vm = MockVm::new(); + let loader = MockLoader::empty(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 0); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.call(dest, 50, &mut gas_meter, &[], EmptyOutputBuf::new()); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Call, + TransferFeeToken { + kind: TransferFeeKind::AccountCreate, + gas_price: 1u64 + }, + ); + }, + ); + + // This one is similar to the previous one but transfer to an existing account. + // In this test we expect that a regular transfer fee is charged. + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let vm = MockVm::new(); + let loader = MockLoader::empty(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 15); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.call(dest, 50, &mut gas_meter, &[], EmptyOutputBuf::new()); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Call, + TransferFeeToken { + kind: TransferFeeKind::Transfer, + gas_price: 1u64 + }, + ); + }, + ); + + // This test sends 50 units of currency as an endownment to a newly + // created contract. + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let mut loader = MockLoader::empty(); + let code = loader.insert(|_| VmExecResult::Ok); + + let vm = MockVm::new(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 15); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.instantiate(50, &mut gas_meter, &code, &[]); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Instantiate, + TransferFeeToken { + kind: TransferFeeKind::ContractInstantiate, + gas_price: 1u64 + }, + ); + }, + ); + } + + #[test] + fn balance_too_low() { + // This test verifies that a contract can't send value if it's + // balance is too low. + let origin = ALICE; + let dest = BOB; + + let vm = MockVm::new(); + let loader = MockLoader::empty(); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 0); + + let result = ctx.call( + dest, + 100, + &mut GasMeter::::with_limit(1000, 1), + &[], + EmptyOutputBuf::new(), + ); + + assert_matches!(result, Err("balance too low to send value")); + assert_eq!(ctx.overlay.get_balance(&origin), 0); + assert_eq!(ctx.overlay.get_balance(&dest), 0); + }); + } + + #[test] + fn output_is_returned() { + // Verifies that if a contract returns data, this data + // is returned from the execution context. + let origin = ALICE; + let dest = BOB; + + let vm = MockVm::new(); + let mut loader = MockLoader::empty(); + let return_ch = loader.insert(|mut ctx| { + #[derive(Debug)] + enum Void {} + let empty_output_buf = ctx.empty_output_buf.take().unwrap(); + let output_buf = + empty_output_buf.fill::(4, |data| { + data.copy_from_slice(&[1, 2, 3, 4]); + Ok(()) + }) + .expect("Ok is always returned"); + VmExecResult::Returned(output_buf) + }); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_code(&BOB, Some(return_ch)); + + let result = ctx.call( + dest, + 0, + &mut GasMeter::::with_limit(1000, 1), + &[], + EmptyOutputBuf::new(), + ); + + let output_data = result.unwrap().output_data; + assert_eq!(&output_data, &[1, 2, 3, 4]); + }); + } + + #[test] + fn input_data() { + let vm = MockVm::new(); + let mut loader = MockLoader::empty(); + let input_data_ch = loader.insert(|ctx| { + assert_eq!(ctx.input_data, &[1, 2, 3, 4]); + VmExecResult::Ok + }); + + // This one tests passing the input data into a contract via call. + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_code(&BOB, Some(input_data_ch)); + + let result = ctx.call( + BOB, + 0, + &mut GasMeter::::with_limit(10000, 1), + &[1, 2, 3, 4], + EmptyOutputBuf::new(), + ); + assert_matches!(result, Ok(_)); + }); + + // This one tests passing the input data into a contract via call. + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + + let result = ctx.instantiate( + 0, + &mut GasMeter::::with_limit(10000, 1), + &input_data_ch, + &[1, 2, 3, 4], + ); + assert_matches!(result, Ok(_)); + }); + } + + #[test] + fn max_depth() { + // This test verifies that when we reach the maximal depth creation of an + // yet another context fails. + let value = Default::default(); + let reached_bottom = RefCell::new(false); + + let vm = MockVm::new(); + let mut loader = MockLoader::empty(); + let recurse_ch = loader.insert(|ctx| { + // Try to call into yourself. + let r = ctx + .ext + .call(&BOB, 0, ctx.gas_meter, &[], EmptyOutputBuf::new()); + + let mut reached_bottom = reached_bottom.borrow_mut(); + if !*reached_bottom { + // We are first time here, it means we just reached bottom. + // Verify that we've got proper error and set `reached_bottom`. + assert_matches!(r, Err("reached maximum depth, cannot make a call")); + *reached_bottom = true; + } else { + // We just unwinding stack here. + assert_matches!(r, Ok(_)); + } + + VmExecResult::Ok + }); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_code(&BOB, Some(recurse_ch)); + + let result = ctx.call( + BOB, + value, + &mut GasMeter::::with_limit(100000, 1), + &[], + EmptyOutputBuf::new(), + ); + + assert_matches!(result, Ok(_)); + }); + } + + #[test] + fn caller_returns_proper_values() { + let origin = ALICE; + let dest = BOB; + + let vm = MockVm::new(); + + let witnessed_caller_bob = RefCell::new(None::); + let witnessed_caller_charlie = RefCell::new(None::); + + let mut loader = MockLoader::empty(); + let bob_ch = loader.insert(|ctx| { + // Record the caller for bob. + *witnessed_caller_bob.borrow_mut() = Some(*ctx.ext.caller()); + + // Call into CHARLIE contract. + assert_matches!( + ctx.ext + .call(&CHARLIE, 0, ctx.gas_meter, &[], EmptyOutputBuf::new()), + Ok(_) + ); + VmExecResult::Ok + }); + let charlie_ch = loader.insert(|ctx| { + // Record the caller for charlie. + *witnessed_caller_charlie.borrow_mut() = Some(*ctx.ext.caller()); + VmExecResult::Ok + }); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_code(&dest, Some(bob_ch)); + ctx.overlay.set_code(&CHARLIE, Some(charlie_ch)); + + let result = ctx.call( + dest, + 0, + &mut GasMeter::::with_limit(10000, 1), + &[], + EmptyOutputBuf::new(), + ); + + assert_matches!(result, Ok(_)); + }); + + assert_eq!(&*witnessed_caller_bob.borrow(), &Some(origin)); + assert_eq!(&*witnessed_caller_charlie.borrow(), &Some(dest)); + } + + #[test] + fn address_returns_proper_values() { + let vm = MockVm::new(); + + let mut loader = MockLoader::empty(); + let bob_ch = loader.insert(|ctx| { + // Verify that address matches BOB. + assert_eq!(*ctx.ext.address(), BOB); + + // Call into charlie contract. + assert_matches!( + ctx.ext + .call(&CHARLIE, 0, ctx.gas_meter, &[], EmptyOutputBuf::new()), + Ok(_) + ); + VmExecResult::Ok + }); + let charlie_ch = loader.insert(|ctx| { + assert_eq!(*ctx.ext.address(), CHARLIE); + VmExecResult::Ok + }); + + with_externalities(&mut ExtBuilder::default().build(), || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_code(&BOB, Some(bob_ch)); + ctx.overlay.set_code(&CHARLIE, Some(charlie_ch)); + + let result = ctx.call( + BOB, + 0, + &mut GasMeter::::with_limit(10000, 1), + &[], + EmptyOutputBuf::new(), + ); + + assert_matches!(result, Ok(_)); + }); + } + + #[test] + fn refuse_instantiate_with_value_below_existential_deposit() { + let vm = MockVm::new(); + + let mut loader = MockLoader::empty(); + let dummy_ch = loader.insert(|_| VmExecResult::Ok); + + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + + assert_matches!( + ctx.instantiate( + 0, // <- zero endowment + &mut GasMeter::::with_limit(10000, 1), + &dummy_ch, + &[], + ), + Err(_) + ); + } + ); + } + + #[test] + fn instantiation() { + let vm = MockVm::new(); + + let mut loader = MockLoader::empty(); + let dummy_ch = loader.insert(|_| VmExecResult::Ok); + + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); + + let created_contract_address = assert_matches!( + ctx.instantiate( + 100, + &mut GasMeter::::with_limit(10000, 1), + &dummy_ch, + &[], + ), + Ok(InstantiateReceipt { address }) => address + ); + + // Check that the newly created account has the expected code hash and + // there are instantiation event. + assert_eq!(ctx.overlay.get_code(&created_contract_address).unwrap(), dummy_ch); + assert_eq!(&ctx.events, &[ + RawEvent::Transfer(ALICE, created_contract_address, 100), + RawEvent::Instantiated(ALICE, created_contract_address), + ]); + } + ); + } + + #[test] + fn instantiation_from_contract() { + let vm = MockVm::new(); + + let mut loader = MockLoader::empty(); + let dummy_ch = loader.insert(|_| VmExecResult::Ok); + let created_contract_address = Rc::new(RefCell::new(None::)); + let creator_ch = loader.insert({ + let dummy_ch = dummy_ch.clone(); + let created_contract_address = Rc::clone(&created_contract_address); + move |ctx| { + // Instantiate a contract and save it's address in `created_contract_address`. + *created_contract_address.borrow_mut() = + ctx.ext.instantiate( + &dummy_ch, + 15u64, + ctx.gas_meter, + &[] + ) + .unwrap() + .address.into(); + + VmExecResult::Ok + } + }); + + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); + ctx.overlay.set_code(&BOB, Some(creator_ch)); + + assert_matches!( + ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), &[], EmptyOutputBuf::new()), + Ok(_) + ); + + let created_contract_address = created_contract_address.borrow().as_ref().unwrap().clone(); + + // Check that the newly created account has the expected code hash and + // there are instantiation event. + assert_eq!(ctx.overlay.get_code(&created_contract_address).unwrap(), dummy_ch); + assert_eq!(&ctx.events, &[ + RawEvent::Transfer(ALICE, BOB, 20), + RawEvent::Transfer(BOB, created_contract_address, 15), + RawEvent::Instantiated(BOB, created_contract_address), + ]); + } + ); + } + + #[test] + fn instantiation_fails() { + let vm = MockVm::new(); + + let mut loader = MockLoader::empty(); + let dummy_ch = loader.insert(|_| VmExecResult::Trap("It's a trap!")); + let creator_ch = loader.insert({ + let dummy_ch = dummy_ch.clone(); + move |ctx| { + // Instantiate a contract and save it's address in `created_contract_address`. + assert_matches!( + ctx.ext.instantiate( + &dummy_ch, + 15u64, + ctx.gas_meter, + &[] + ), + Err("It's a trap!") + ); + + VmExecResult::Ok + } + }); + + with_externalities( + &mut ExtBuilder::default().existential_deposit(15).build(), + || { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); + ctx.overlay.set_code(&BOB, Some(creator_ch)); + + assert_matches!( + ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), &[], EmptyOutputBuf::new()), + Ok(_) + ); + + // The contract wasn't created so we don't expect to see an instantiation + // event here. + assert_eq!(&ctx.events, &[ + RawEvent::Transfer(ALICE, BOB, 20), + ]); + } + ); + } } diff --git a/srml/contract/src/gas.rs b/srml/contract/src/gas.rs index af94ae05c10fe2f145de8b6c4a8fd663adfc08f2..fb96ff66e52405b206d19bde54f1fa8d1676e0ee 100644 --- a/srml/contract/src/gas.rs +++ b/srml/contract/src/gas.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,10 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use {Trait, Module, GasSpent}; -use runtime_primitives::traits::{As, CheckedMul, CheckedSub, Zero}; -use runtime_support::StorageValue; +use crate::{GasSpent, Module, Trait}; use balances; +use runtime_primitives::BLOCK_FULL; +use runtime_primitives::traits::{As, CheckedMul, CheckedSub, Zero}; +use srml_support::StorageValue; + +#[cfg(test)] +use std::{any::Any, fmt::Debug}; #[must_use] #[derive(Debug, PartialEq, Eq)] @@ -35,11 +39,54 @@ impl GasMeterResult { } } +#[cfg(not(test))] +pub trait TestAuxiliaries {} +#[cfg(not(test))] +impl TestAuxiliaries for T {} + +#[cfg(test)] +pub trait TestAuxiliaries: Any + Debug + PartialEq + Eq {} +#[cfg(test)] +impl TestAuxiliaries for T {} + +/// This trait represents a token that can be used for charging `GasMeter`. +/// There is no other way of charging it. +/// +/// Implementing type is expected to be super lightweight hence `Copy` (`Clone` is added +/// for consistency). If inlined there should be no observable difference compared +/// to a hand-written code. +pub trait Token: Copy + Clone + TestAuxiliaries { + /// Metadata type, which the token can require for calculating the amount + /// of gas to charge. Can be a some configuration type or + /// just the `()`. + type Metadata; + + /// Calculate amount of gas that should be taken by this token. + /// + /// This function should be really lightweight and must not fail. It is not + /// expected that implementors will query the storage or do any kinds of heavy operations. + /// + /// That said, implementors of this function still can run into overflows + /// while calculating the amount. In this case it is ok to use saturating operations + /// since on overflow they will return `max_value` which should consume all gas. + fn calculate_amount(&self, metadata: &Self::Metadata) -> T::Gas; +} + +/// A wrapper around a type-erased trait object of what used to be a `Token`. +#[cfg(test)] +pub struct ErasedToken { + pub description: String, + pub token: Box, +} + pub struct GasMeter { limit: T::Gas, /// Amount of gas left from initial gas limit. Can reach zero. gas_left: T::Gas, gas_price: T::Balance, + + #[cfg(test)] + tokens: Vec, } impl GasMeter { #[cfg(test)] @@ -48,17 +95,37 @@ impl GasMeter { limit: gas_limit, gas_left: gas_limit, gas_price, + #[cfg(test)] + tokens: Vec::new(), } } /// Account for used gas. /// + /// Amount is calculated by the given `token`. + /// /// Returns `OutOfGas` if there is not enough gas or addition of the specified /// amount of gas has lead to overflow. On success returns `Proceed`. /// - /// NOTE that `amount` is always consumed, i.e. if there is not enough gas + /// NOTE that amount is always consumed, i.e. if there is not enough gas /// then the counter will be set to zero. - pub fn charge(&mut self, amount: T::Gas) -> GasMeterResult { + #[inline] + pub fn charge>( + &mut self, + metadata: &Tok::Metadata, + token: Tok, + ) -> GasMeterResult { + #[cfg(test)] + { + // Unconditionally add the token to the storage. + let erased_tok = ErasedToken { + description: format!("{:?}", token), + token: Box::new(token), + }; + self.tokens.push(erased_tok); + } + + let amount = token.calculate_amount(metadata); let new_value = match self.gas_left.checked_sub(&amount) { None => None, Some(val) if val.is_zero() => None, @@ -74,18 +141,6 @@ impl GasMeter { } } - /// Account for used gas expressed in balance units. - /// - /// Same as [`charge`], but amount to be charged is converted from units of balance to - /// units of gas. - /// - /// [`charge`]: #method.charge - pub fn charge_by_balance(&mut self, amount: T::Balance) -> GasMeterResult { - let amount_in_gas: T::Balance = amount / self.gas_price; - let amount_in_gas: T::Gas = >::sa(amount_in_gas); - self.charge(amount_in_gas) - } - /// Allocate some amount of gas and perform some work with /// a newly created nested gas meter. /// @@ -108,6 +163,8 @@ impl GasMeter { limit: amount, gas_left: amount, gas_price: self.gas_price, + #[cfg(test)] + tokens: Vec::new(), }; let r = f(Some(&mut nested)); @@ -118,6 +175,10 @@ impl GasMeter { } } + pub fn gas_price(&self) -> T::Balance { + self.gas_price + } + /// Returns how much gas left from the initial budget. pub fn gas_left(&self) -> T::Gas { self.gas_left @@ -127,6 +188,11 @@ impl GasMeter { fn spent(&self) -> T::Gas { self.limit - self.gas_left } + + #[cfg(test)] + pub fn tokens(&self) -> &[ErasedToken] { + &self.tokens + } } /// Buy the given amount of gas. @@ -141,7 +207,8 @@ pub fn buy_gas( // This cannot underflow since `gas_spent` is never greater than `block_gas_limit`. let gas_available = >::block_gas_limit() - >::gas_spent(); if gas_limit > gas_available { - return Err("block gas limit is reached"); + // gas limit reached, revert the transaction and retry again in the future + return Err(BLOCK_FULL); } // Buy the specified amount of gas. @@ -162,6 +229,8 @@ pub fn buy_gas( limit: gas_limit, gas_left: gas_limit, gas_price, + #[cfg(test)] + tokens: Vec::new(), }) } @@ -179,3 +248,108 @@ pub fn refund_unused_gas(transactor: &T::AccountId, gas_meter: GasMete >::set_free_balance(transactor, b + refund); >::increase_total_stake_by(refund); } + +/// A little handy utility for converting a value in balance units into approximitate value in gas units +/// at the given gas price. +pub fn approx_gas_for_balance(gas_price: T::Balance, balance: T::Balance) -> T::Gas { + let amount_in_gas: T::Balance = balance / gas_price; + >::sa(amount_in_gas) +} + +/// A simple utility macro that helps to match against a +/// list of tokens. +#[macro_export] +macro_rules! match_tokens { + ($tokens_iter:ident,) => { + }; + ($tokens_iter:ident, $x:expr, $($rest:tt)*) => { + { + let next = ($tokens_iter).next().unwrap(); + let pattern = $x; + + // Note that we don't specify the type name directly in this macro, + // we only have some expression $x of some type. At the same time, we + // have an iterator of Box and to downcast we need to specify + // the type which we want downcast to. + // + // So what we do is we assign `_pattern_typed_next_ref` to the a variable which has + // the required type. + // + // Then we make `_pattern_typed_next_ref = token.downcast_ref()`. This makes + // rustc infer the type `T` (in `downcast_ref`) to be the same as in $x. + + let mut _pattern_typed_next_ref = &pattern; + _pattern_typed_next_ref = match next.token.downcast_ref() { + Some(p) => { + assert_eq!(p, &pattern); + p + } + None => { + panic!("expected type {} got {}", stringify!($x), next.description); + } + }; + } + + match_tokens!($tokens_iter, $($rest)*); + }; +} + +#[cfg(test)] +mod tests { + use super::{GasMeter, Token}; + use crate::tests::Test; + + /// A trivial token that charges 1 unit of gas. + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + struct UnitToken; + impl Token for UnitToken { + type Metadata = (); + fn calculate_amount(&self, _metadata: &()) -> u64 { 1 } + } + + struct DoubleTokenMetadata { + multiplier: u64, + } + /// A simple token that charges for the given amount multipled to + /// a multiplier taken from a given metadata. + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + struct DoubleToken(u64); + + impl Token for DoubleToken { + type Metadata = DoubleTokenMetadata; + fn calculate_amount(&self, metadata: &DoubleTokenMetadata) -> u64 { + // Probably you want to use saturating mul in producation code. + self.0 * metadata.multiplier + } + } + + #[test] + fn it_works() { + let gas_meter = GasMeter::::with_limit(50000, 10); + assert_eq!(gas_meter.gas_left(), 50000); + } + + #[test] + fn simple() { + let mut gas_meter = GasMeter::::with_limit(50000, 10); + + let result = gas_meter.charge(&DoubleTokenMetadata { multiplier: 3 }, DoubleToken(10)); + assert!(!result.is_out_of_gas()); + + assert_eq!(gas_meter.gas_left(), 49_970); + assert_eq!(gas_meter.spent(), 30); + assert_eq!(gas_meter.gas_price(), 10); + } + + #[test] + fn tracing() { + let mut gas_meter = GasMeter::::with_limit(50000, 10); + assert!(!gas_meter.charge(&(), UnitToken).is_out_of_gas()); + assert!(!gas_meter + .charge(&DoubleTokenMetadata { multiplier: 3 }, DoubleToken(10)) + .is_out_of_gas()); + + let mut tokens = gas_meter.tokens()[0..2].iter(); + match_tokens!(tokens, UnitToken, DoubleToken(10),); + } +} diff --git a/srml/contract/src/lib.rs b/srml/contract/src/lib.rs index e87c289ed82fa14ae021b6a363420fcc12bfd4fa..3f6cbde88f17a562250a5658279b6132fac3f160 100644 --- a/srml/contract/src/lib.rs +++ b/srml/contract/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -39,7 +39,7 @@ //! This module requires performing some finalization steps at the end of the block. If not performed //! the module will have incorrect behavior. //! -//! Call [`Module::execute`] at the end of the block. The order in relation to +//! Thus [`Module::on_finalise`] must be called at the end of the block. The order in relation to //! the other module doesn't matter. //! //! ## Account killing @@ -48,75 +48,68 @@ //! exsistential deposit) then it reaps the account. That will lead to deletion of the associated //! code and storage of the account. //! -//! [`Module::execute`]: struct.Module.html#impl-OnFinalise +//! [`Module::on_finalise`]: struct.Module.html#impl-OnFinalise #![cfg_attr(not(feature = "std"), no_std)] #[macro_use] -extern crate parity_codec_derive; - -extern crate parity_wasm; -extern crate pwasm_utils; - -extern crate parity_codec as codec; -extern crate sr_io as runtime_io; -extern crate sr_sandbox as sandbox; - -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; - -extern crate srml_balances as balances; -extern crate srml_system as system; - -#[macro_use] -extern crate srml_support as runtime_support; - -extern crate sr_primitives as runtime_primitives; - -#[cfg(test)] -extern crate substrate_primitives; - -#[cfg(test)] -#[macro_use] -extern crate assert_matches; - -#[cfg(test)] -extern crate wabt; +mod gas; mod account_db; -mod double_map; mod exec; -mod vm; -mod gas; +mod wasm; #[cfg(test)] mod tests; -use exec::ExecutionContext; -use account_db::{AccountDb, OverlayAccountDb}; -use double_map::StorageDoubleMap; +use crate::exec::ExecutionContext; +use crate::account_db::AccountDb; +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; +use substrate_primitives::crypto::UncheckedFrom; use rstd::prelude::*; use rstd::marker::PhantomData; -use codec::{Codec, HasCompact}; -use runtime_primitives::traits::{Hash, As, SimpleArithmetic}; -use runtime_support::dispatch::Result; -use runtime_support::{Parameter, StorageMap, StorageValue}; -use system::ensure_signed; +use parity_codec::{Codec, Encode, Decode}; +use runtime_primitives::traits::{Hash, As, SimpleArithmetic,Bounded, StaticLookup}; +use srml_support::dispatch::{Result, Dispatchable}; +use srml_support::{Parameter, StorageMap, StorageValue, StorageDoubleMap, decl_module, decl_event, decl_storage}; +use srml_support::traits::OnFreeBalanceZero; +use system::{ensure_signed, RawOrigin}; +use runtime_io::{blake2_256, twox_128}; +use timestamp; +use fees; + +pub type CodeHash = ::Hash; + +/// A function that generates an `AccountId` for a contract upon instantiation. +pub trait ContractAddressFor { + fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &AccountId) -> AccountId; +} -pub trait Trait: balances::Trait { - /// Function type to get the contract address given the creator. - type DetermineContractAddress: ContractAddressFor; +/// A function that returns the fee for dispatching a `Call`. +pub trait ComputeDispatchFee { + fn compute_dispatch_fee(call: &Call) -> Balance; +} - // As is needed for wasm-utils - type Gas: Parameter + Default + Codec + SimpleArithmetic + Copy + As + As + As; +pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { + /// The outer call dispatch type. + type Call: Parameter + Dispatchable::Origin>; /// The overarching event type. type Event: From> + Into<::Event>; -} -pub trait ContractAddressFor { - fn contract_address_for(code: &[u8], data: &[u8], origin: &AccountId) -> AccountId; + // As is needed for wasm-utils + type Gas: Parameter + Default + Codec + SimpleArithmetic + Bounded + Copy + As + As + As; + + /// A function type to get the contract address given the creator. + type DetermineContractAddress: ContractAddressFor, Self::AccountId>; + + /// A function type that computes the fee for dispatching the given `Call`. + /// + /// It is recommended (though not required) for this function to return a fee that would be taken + /// by executive module for regular dispatch. + type ComputeDispatchFee: ComputeDispatchFee::Balance>; } /// Simple contract address determintator. @@ -126,13 +119,11 @@ pub trait ContractAddressFor { /// /// Formula: `blake2_256(blake2_256(code) + blake2_256(data) + origin)` pub struct SimpleAddressDeterminator(PhantomData); - -impl ContractAddressFor for SimpleAddressDeterminator +impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminator where - T::AccountId: From + AsRef<[u8]> + T::AccountId: UncheckedFrom + AsRef<[u8]> { - fn contract_address_for(code: &[u8], data: &[u8], origin: &T::AccountId) -> T::AccountId { - let code_hash = T::Hashing::hash(code); + fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &T::AccountId) -> T::AccountId { let data_hash = T::Hashing::hash(data); let mut buf = Vec::new(); @@ -140,27 +131,72 @@ where buf.extend_from_slice(data_hash.as_ref()); buf.extend_from_slice(origin.as_ref()); - T::Hashing::hash(&buf[..]).into() + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) + } +} + +/// The default dispatch fee computor computes the fee in the same way that +/// implementation of `ChargeBytesFee` for fees module does. +pub struct DefaultDispatchFeeComputor(PhantomData); +impl ComputeDispatchFee for DefaultDispatchFeeComputor { + fn compute_dispatch_fee(call: &T::Call) -> T::Balance { + let encoded_len = call.using_encoded(|encoded| encoded.len()); + let base_fee = >::transaction_base_fee(); + let byte_fee = >::transaction_byte_fee(); + >::sa(base_fee.as_() + byte_fee.as_() * encoded_len as u64) } } decl_module! { /// Contracts module. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - // TODO: Change AccountId to staking::Address - /// Make a call to a specified account, optionally transferring some balance. + pub struct Module for enum Call where origin: ::Origin { + fn deposit_event() = default; + + /// Updates the schedule for metering contracts. + /// + /// The schedule must have a greater version than the stored schedule. + fn update_schedule(schedule: Schedule) -> Result { + if >::current_schedule().version >= schedule.version { + return Err("new schedule must have a greater version than current"); + } + + Self::deposit_event(RawEvent::ScheduleUpdated(schedule.version)); + >::put(schedule); + + Ok(()) + } + + /// Stores code in the storage. You can instantiate contracts only with stored code. + fn put_code( + origin, + #[compact] gas_limit: T::Gas, + code: Vec + ) -> Result { + let origin = ensure_signed(origin)?; + let schedule = >::current_schedule(); + + let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; + + let result = wasm::save_code::(code, &mut gas_meter, &schedule); + if let Ok(code_hash) = result { + Self::deposit_event(RawEvent::CodeStored(code_hash)); + } + + gas::refund_unused_gas::(&origin, gas_meter); + + result.map(|_| ()) + } + /// Make a call to a specified account, optionally transferring some balance. fn call( origin, - dest: T::AccountId, - value: ::Type, - gas_limit: ::Type, + dest: ::Source, + #[compact] value: T::Balance, + #[compact] gas_limit: T::Gas, data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let value = value.into(); - let gas_limit = gas_limit.into(); + let dest = T::Lookup::lookup(dest)?; // Pay for the gas upfront. // @@ -169,16 +205,11 @@ decl_module! { let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; let cfg = Config::preload(); - let mut ctx = ExecutionContext { - self_account: origin.clone(), - depth: 0, - overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), - events: Vec::new(), - config: &cfg, - }; + let vm = crate::wasm::WasmVm::new(&cfg.schedule); + let loader = crate::wasm::WasmLoader::new(&cfg.schedule); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); - let mut output_data = Vec::new(); - let result = ctx.call(origin.clone(), dest, value, &mut gas_meter, &data, &mut output_data); + let result = ctx.call(dest, value, &mut gas_meter, &data, exec::EmptyOutputBuf::new()); if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. @@ -194,6 +225,12 @@ decl_module! { // can alter the balance of the caller. gas::refund_unused_gas::(&origin, gas_meter); + // Dispatch every recorded call with an appropriate origin. + ctx.calls.into_iter().for_each(|(who, call)| { + let result = call.dispatch(RawOrigin::Signed(who.clone()).into()); + Self::deposit_event(RawEvent::Dispatched(who, result.is_ok())); + }); + result.map(|_| ()) } @@ -208,14 +245,12 @@ decl_module! { /// upon any message received by this account. fn create( origin, - endowment: ::Type, - gas_limit: ::Type, - ctor_code: Vec, + #[compact] endowment: T::Balance, + #[compact] gas_limit: T::Gas, + code_hash: CodeHash, data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let endowment = endowment.into(); - let gas_limit = gas_limit.into(); // Pay for the gas upfront. // @@ -224,23 +259,17 @@ decl_module! { let mut gas_meter = gas::buy_gas::(&origin, gas_limit)?; let cfg = Config::preload(); - let mut ctx = ExecutionContext { - self_account: origin.clone(), - depth: 0, - overlay: OverlayAccountDb::::new(&account_db::DirectAccountDb), - events: Vec::new(), - config: &cfg, - }; - let result = ctx.create(origin.clone(), endowment, &mut gas_meter, &ctor_code, &data); - - if let Ok(ref r) = result { + let vm = crate::wasm::WasmVm::new(&cfg.schedule); + let loader = crate::wasm::WasmLoader::new(&cfg.schedule); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); + let result = ctx.instantiate(endowment, &mut gas_meter, &code_hash, &data); + + if let Ok(_) = result { // Commit all changes that made it thus far into the persistant storage. account_db::DirectAccountDb.commit(ctx.overlay.into_change_set()); // Then deposit all events produced. ctx.events.into_iter().for_each(Self::deposit_event); - - Self::deposit_event(RawEvent::Created(origin.clone(), r.address.clone())); } // Refund cost of the unused gas. @@ -249,6 +278,12 @@ decl_module! { // can alter the balance of the caller. gas::refund_unused_gas::(&origin, gas_meter); + // Dispatch every recorded call with an appropriate origin. + ctx.calls.into_iter().for_each(|(who, call)| { + let result = call.dispatch(RawOrigin::Signed(who.clone()).into()); + Self::deposit_event(RawEvent::Dispatched(who, result.is_ok())); + }); + result.map(|_| ()) } @@ -262,13 +297,24 @@ decl_event! { pub enum Event where ::Balance, - ::AccountId + ::AccountId, + ::Hash { /// Transfer happened `from` -> `to` with given `value` as part of a `message-call` or `create`. Transfer(AccountId, AccountId, Balance), /// Contract deployed by address at the specified address. - Created(AccountId, AccountId), + Instantiated(AccountId, AccountId), + + /// Code with the specified hash has been stored. + CodeStored(Hash), + + /// Triggered when the current schedule is updated. + ScheduleUpdated(u32), + + /// A call was dispatched from the given account. The bool signals whether it was + /// successful execution or not. + Dispatched(AccountId, bool), } } @@ -290,29 +336,40 @@ decl_storage! { GasSpent get(gas_spent): T::Gas; /// Current cost schedule for contracts. CurrentSchedule get(current_schedule) config(): Schedule = Schedule::default(); - /// The code associated with an account. - pub CodeOf: map T::AccountId => Vec; // TODO Vec values should be optimised to not do a length prefix. + /// The code associated with a given account. + pub CodeHashOf: map T::AccountId => Option>; + /// A mapping from an original code hash to the original code, untouched by instrumentation. + pub PristineCode: map CodeHash => Option>; + /// A mapping between an original code hash and instrumented wasm code, ready for the execution. + pub CodeStorage: map CodeHash => Option; } } -// TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime -// code in contract itself and use that. - /// The storage items associated with an account/key. /// -/// TODO: keys should also be able to take AsRef to ensure Vecs can be passed as &[u8] -pub(crate) struct StorageOf(::rstd::marker::PhantomData); -impl double_map::StorageDoubleMap for StorageOf { +pub(crate) struct StorageOf(rstd::marker::PhantomData); +impl StorageDoubleMap for StorageOf { const PREFIX: &'static [u8] = b"con:sto:"; type Key1 = T::AccountId; type Key2 = Vec; type Value = Vec; + + /// Hashed by XX + fn derive_key1(key1_data: Vec) -> Vec { + twox_128(&key1_data).to_vec() + } + + /// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and + /// thus will be susceptible for a untrusted input. + fn derive_key2(key2_data: Vec) -> Vec { + blake2_256(&key2_data).to_vec() + } } -impl balances::OnFreeBalanceZero for Module { +impl OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who); - >::remove_prefix(who.clone()); + >::remove(who); + >::remove_prefix(who); } } @@ -324,11 +381,11 @@ pub struct Config { pub schedule: Schedule, pub existential_deposit: T::Balance, pub max_depth: u32, - pub contract_account_create_fee: T::Balance, + pub contract_account_instantiate_fee: T::Balance, pub account_create_fee: T::Balance, pub transfer_fee: T::Balance, pub call_base_fee: T::Gas, - pub create_base_fee: T::Gas, + pub instantiate_base_fee: T::Gas, } impl Config { @@ -337,19 +394,25 @@ impl Config { schedule: >::current_schedule(), existential_deposit: >::existential_deposit(), max_depth: >::max_depth(), - contract_account_create_fee: >::contract_fee(), + contract_account_instantiate_fee: >::contract_fee(), account_create_fee: >::creation_fee(), transfer_fee: >::transfer_fee(), call_base_fee: >::call_base_fee(), - create_base_fee: >::create_base_fee(), + instantiate_base_fee: >::create_base_fee(), } } } /// Definition of the cost schedule and other parameterizations for wasm vm. #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, PartialEq, Eq)] pub struct Schedule { + /// Version of the schedule. + pub version: u32, + + /// Cost of putting a byte of code into the storage. + pub put_code_per_byte_cost: Gas, + /// Gas cost of a growing memory by single page. pub grow_mem_cost: Gas, @@ -360,10 +423,10 @@ pub struct Schedule { pub return_data_per_byte_cost: Gas, /// Gas cost per one byte read from the sandbox memory. - sandbox_data_read_cost: Gas, + pub sandbox_data_read_cost: Gas, /// Gas cost per one byte written to the sandbox memory. - sandbox_data_write_cost: Gas, + pub sandbox_data_write_cost: Gas, /// How tall the stack is allowed to grow? /// @@ -371,7 +434,7 @@ pub struct Schedule { /// how the stack frame cost is calculated. pub max_stack_height: u32, - //// What is the maximal memory pages amount is allowed to have for + /// What is the maximal memory pages amount is allowed to have for /// a contract. pub max_memory_pages: u32, } @@ -379,6 +442,8 @@ pub struct Schedule { impl> Default for Schedule { fn default() -> Schedule { Schedule { + version: 0, + put_code_per_byte_cost: Gas::sa(1), grow_mem_cost: Gas::sa(1), regular_op_cost: Gas::sa(1), return_data_per_byte_cost: Gas::sa(1), diff --git a/srml/contract/src/tests.rs b/srml/contract/src/tests.rs index 330f11a3b2687a4c1d6a51c259c8e4742980b751..cf280c0f007c9a4177ac16388bc7c1de615a22f2 100644 --- a/srml/contract/src/tests.rs +++ b/srml/contract/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,30 +14,47 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use double_map::StorageDoubleMap; +// TODO: #1417 Add more integration tests +// also remove the #![allow(unused)] below. + +#![allow(unused)] + use runtime_io::with_externalities; -use runtime_primitives::testing::{Digest, DigestItem, H256, Header}; -use runtime_primitives::traits::{BlakeTwo256}; +use runtime_primitives::testing::{Digest, DigestItem, H256, Header, UintAuthorityId}; +use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; use runtime_primitives::BuildStorage; -use runtime_support::StorageMap; +use runtime_io; +use srml_support::{StorageMap, StorageDoubleMap, assert_ok, impl_outer_event, impl_outer_dispatch, impl_outer_origin}; use substrate_primitives::{Blake2Hasher}; -use system::{Phase, EventRecord}; -use wabt; -use { - runtime_io, balances, system, CodeOf, ContractAddressFor, - GenesisConfig, Module, StorageOf, Trait, RawEvent, +use system::{self, Phase, EventRecord}; +use fees; +use {wabt, balances, consensus}; +use hex_literal::*; +use assert_matches::assert_matches; +use crate::{ + ContractAddressFor, GenesisConfig, Module, RawEvent, StorageOf, + Trait, ComputeDispatchFee }; -impl_outer_origin! { - pub enum Origin for Test {} -} - mod contract { + // Re-export contents of the root. This basically + // needs to give a name for the current crate. + // This hack is required for `impl_outer_event!`. pub use super::super::*; + use srml_support::impl_outer_event; } impl_outer_event! { pub enum MetaEvent for Test { - balances, contract, + balances, contract, fees, + } +} +impl_outer_origin! { + pub enum Origin for Test { } +} +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + balances::Balances, + contract::Contract, } } @@ -51,21 +68,36 @@ impl system::Trait for Test { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = Contract; - type EnsureAccountLiquid = (); + type OnNewAccount = (); + type Event = MetaEvent; +} +impl timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); +} +impl consensus::Trait for Test { + type Log = DigestItem; + type SessionKey = UintAuthorityId; + type InherentOfflineReport = (); +} +impl fees::Trait for Test { type Event = MetaEvent; + type TransferAsset = Balances; } impl Trait for Test { + type Call = Call; type Gas = u64; type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; + type ComputeDispatchFee = DummyComputeDispatchFee; } type Balances = balances::Module; @@ -73,13 +105,24 @@ type Contract = Module; type System = system::Module; pub struct DummyContractAddressFor; -impl ContractAddressFor for DummyContractAddressFor { - fn contract_address_for(_code: &[u8], _data: &[u8], origin: &u64) -> u64 { - origin + 1 +impl ContractAddressFor for DummyContractAddressFor { + fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 { + *origin + 1 + } +} + +pub struct DummyComputeDispatchFee; +impl ComputeDispatchFee for DummyComputeDispatchFee { + fn compute_dispatch_fee(call: &Call) -> u64 { + 69 } } -struct ExtBuilder { +const ALICE: u64 = 1; +const BOB: u64 = 2; +const CHARLIE: u64 = 3; + +pub struct ExtBuilder { existential_deposit: u64, gas_price: u64, block_gas_limit: u64, @@ -98,41 +141,42 @@ impl Default for ExtBuilder { } } impl ExtBuilder { - fn existential_deposit(mut self, existential_deposit: u64) -> Self { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { self.existential_deposit = existential_deposit; self } - fn gas_price(mut self, gas_price: u64) -> Self { + pub fn gas_price(mut self, gas_price: u64) -> Self { self.gas_price = gas_price; self } - fn block_gas_limit(mut self, block_gas_limit: u64) -> Self { + pub fn block_gas_limit(mut self, block_gas_limit: u64) -> Self { self.block_gas_limit = block_gas_limit; self } - fn transfer_fee(mut self, transfer_fee: u64) -> Self { + pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { self.transfer_fee = transfer_fee; self } - fn creation_fee(mut self, creation_fee: u64) -> Self { + pub fn creation_fee(mut self, creation_fee: u64) -> Self { self.creation_fee = creation_fee; self } - fn build(self) -> runtime_io::TestExternalities { + pub fn build(self) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default() .build_storage() - .unwrap().0; + .unwrap() + .0; t.extend( balances::GenesisConfig:: { balances: vec![], - transaction_base_fee: 0, - transaction_byte_fee: 0, existential_deposit: self.existential_deposit, transfer_fee: self.transfer_fee, creation_fee: self.creation_fee, - reclaim_rebate: 0, - }.build_storage() - .unwrap().0, + vesting: vec![], + } + .build_storage() + .unwrap() + .0, ); t.extend( GenesisConfig:: { @@ -143,546 +187,33 @@ impl ExtBuilder { max_depth: 100, block_gas_limit: self.block_gas_limit, current_schedule: Default::default(), - }.build_storage() - .unwrap().0, + } + .build_storage() + .unwrap() + .0, ); runtime_io::TestExternalities::new(t) } } -const CODE_TRANSFER: &str = r#" -(module - ;; ext_call( - ;; callee_ptr: u32, - ;; callee_len: u32, - ;; gas: u64, - ;; value_ptr: u32, - ;; value_len: u32, - ;; input_data_ptr: u32, - ;; input_data_len: u32 - ;; ) -> u32 - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_call - (i32.const 4) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 12) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - ) - ) - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") -) -"#; - -#[test] -fn contract_transfer() { - const CONTRACT_SHOULD_TRANSFER_VALUE: u64 = 6; - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(1, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 11); - Balances::increase_total_stake_by(11); - - assert_ok!(Contract::call(Origin::signed(0), 1, 3.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 3 - value sent with the transaction - // 2 * 26 - gas used by the contract (26) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (by transaction) - // 2 * 135 - base gas fee for call (by the contract) - 100_000_000 - 3 - (2 * 26) - (2 * 135) - (2 * 135), - ); - assert_eq!( - Balances::free_balance(&1), - 11 + 3 - CONTRACT_SHOULD_TRANSFER_VALUE, - ); - assert_eq!( - Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), - CONTRACT_SHOULD_TRANSFER_VALUE, - ); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount( - CONTRACT_SHOULD_TRANSFER_TO, - 0, - balances::NewAccountOutcome::NoHint - ) - ), - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(0, 1, 3)), - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(1, CONTRACT_SHOULD_TRANSFER_TO, 6)), - }, - ]); - }); -} - -#[test] -fn contract_transfer_to_death() { - const CONTRACT_SHOULD_TRANSFER_VALUE: u64 = 6; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().existential_deposit(5).build(), || { - >::insert(1, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - Balances::set_free_balance(&1, 6); - Balances::increase_total_stake_by(6); - >::insert(1, b"foo".to_vec(), b"1".to_vec()); - - assert_ok!(Contract::call(Origin::signed(0), 1, 0.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 2 * 26 - gas used by the contract (26) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (by transaction) - // 2 * 135 - base gas fee for call (by the contract) - 100_000_000 - (2 * 26) - (2 * 135) - (2 * 135), - ); - - assert!(!>::exists(1)); - assert!(!>::exists(1, b"foo".to_vec())); - assert_eq!(Balances::free_balance(&1), 0); - - assert_eq!(Balances::free_balance(&9), CONTRACT_SHOULD_TRANSFER_VALUE); - }); -} - -#[test] -fn contract_transfer_takes_creation_fee() { - const CONTRACT_SHOULD_TRANSFER_VALUE: u64 = 6; - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().creation_fee(105).build(), || { - >::insert(1, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 11); - Balances::increase_total_stake_by(11); - - assert_ok!(Contract::call(Origin::signed(0), 1, 3.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 3 - value sent with the transaction - // 2 * 26 - gas used by the contract (26) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (by transaction) - // 2 * 135 - base gas fee for call (by the contract) - // 104 - (rounded) fee per creation (by the contract) - 100_000_000 - 3 - (2 * 26) - (2 * 135) - (2 * 135) - 104, - ); - assert_eq!( - Balances::free_balance(&1), - 11 + 3 - CONTRACT_SHOULD_TRANSFER_VALUE, - ); - assert_eq!( - Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), - CONTRACT_SHOULD_TRANSFER_VALUE, - ); - }); -} - -#[test] -fn contract_transfer_takes_transfer_fee() { - const CONTRACT_SHOULD_TRANSFER_VALUE: u64 = 6; - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().creation_fee(105).transfer_fee(45).build(), || { - >::insert(1, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 11); - Balances::increase_total_stake_by(11); - - // Create destination account here so we can check that transfer fee - // is charged (and creation fee is not). - Balances::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 25); - - assert_ok!(Contract::call(Origin::signed(0), 1, 3.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 3 - value sent with the transaction - // 2 * 26 - gas used by the contract (26) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (by transaction) - // 44 - (rounded from 45) fee per transfer (by transaction) - // 2 * 135 - base gas fee for call (by the contract) - // 44 - (rounded from 45) fee per transfer (by the contract) - 100_000_000 - 3 - (2 * 26) - (2 * 135) - 44 - (2 * 135) - 44, - ); - assert_eq!( - Balances::free_balance(&1), - 11 + 3 - CONTRACT_SHOULD_TRANSFER_VALUE, - ); - assert_eq!( - Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), - 25 + CONTRACT_SHOULD_TRANSFER_VALUE, - ); - }); -} - -#[test] -fn contract_transfer_oog() { - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(1, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 11); - Balances::increase_total_stake_by(11); - - assert_ok!(Contract::call(Origin::signed(0), 1, 3.into(), (135 + 135 + 7).into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 3 - value sent with the transaction - // 2 * 7 - gas used by the contract (7) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (by transaction) - // 2 * 135 - base gas fee for call (by contract) - 100_000_000 - 3 - (2 * 7) - (2 * 135) - (2 * 135), - ); - - // Transaction level transfer should succeed. - assert_eq!(Balances::free_balance(&1), 14); - // But `ext_call` should not. - assert_eq!(Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 0); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(0, 1, 3)), - }, - ]); - }); -} - -#[test] -fn contract_transfer_max_depth() { - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(CONTRACT_SHOULD_TRANSFER_TO, code_transfer.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11); - Balances::increase_total_stake_by(11); - - assert_ok!(Contract::call(Origin::signed(0), CONTRACT_SHOULD_TRANSFER_TO, 3.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 3 - value sent with the transaction - // 2 * 26 * 100 - gas used by the contract (26) multiplied by gas price (2) - // multiplied by max depth (100). - // 2 * 135 * 100 - base gas fee for call (by transaction) multiplied by max depth (100). - 100_000_000 - 3 - (2 * 26 * 100) - (2 * 135 * 100), - ); - assert_eq!(Balances::free_balance(&CONTRACT_SHOULD_TRANSFER_TO), 14); - }); -} - -/// Convert a byte slice to a string with hex values. -/// -/// Each value is preceeded with a `\` character. -fn escaped_bytestring(bytes: &[u8]) -> String { - use std::fmt::Write; - let mut result = String::new(); - for b in bytes { - write!(result, "\\{:02x}", b).unwrap(); - } - result -} - -/// Create a constructor for the specified code. -/// -/// When constructor is executed, it will call `ext_return` with code that -/// specified in `child_bytecode`. -fn code_ctor(child_bytecode: &[u8]) -> String { - format!( - r#" -(module - ;; ext_return(data_ptr: u32, data_len: u32) -> ! - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (call $ext_return - (i32.const 4) - (i32.const {code_len}) - ) - ;; ext_return is diverging, i.e. doesn't return. - unreachable - ) - (data (i32.const 4) "{escaped_bytecode}") -) -"#, - escaped_bytecode = escaped_bytestring(child_bytecode), - code_len = child_bytecode.len(), - ) -} - -/// Returns code that uses `ext_create` runtime call. -/// -/// Takes bytecode of the contract that needs to be deployed. -fn code_create(constructor: &[u8]) -> String { - format!( - r#" -(module - ;; ext_create( - ;; code_ptr: u32, - ;; code_len: u32, - ;; gas: u64, - ;; value_ptr: u32, - ;; value_len: u32, - ;; input_data_ptr: u32, - ;; input_data_len: u32, - ;; ) -> u32 - (import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_create - (i32.const 12) ;; Pointer to `code` - (i32.const {code_len}) ;; Length of `code` - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 4) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - ) - ) - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\03\00\00\00\00\00\00\00") - ;; Embedded wasm code. - (data (i32.const 12) "{escaped_constructor}") -) -"#, - escaped_constructor = escaped_bytestring(constructor), - code_len = constructor.len(), - ) -} - #[test] -fn contract_create() { - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - let code_ctor_transfer = wabt::wat2wasm(&code_ctor(&code_transfer)).unwrap(); - let code_create = wabt::wat2wasm(&code_create(&code_ctor_transfer)).unwrap(); - +fn refunds_unused_gas() { with_externalities(&mut ExtBuilder::default().build(), || { Balances::set_free_balance(&0, 100_000_000); Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 0); - Balances::set_free_balance(&9, 30); - Balances::increase_total_stake_by(30); - - >::insert(1, code_create.to_vec()); - - // When invoked, the contract at address `1` must create a contract with 'transfer' code. - assert_ok!(Contract::call(Origin::signed(0), 1, 11.into(), 100_000.into(), Vec::new())); - - let derived_address = ::DetermineContractAddress::contract_address_for( - &code_ctor_transfer, - &[], - &1, - ); - - // 11 - value sent with the transaction - // 2 * 362 - gas spent by the deployer contract (362) multiplied by gas price (2) - // 2 * 135 - base gas fee for call (top level) - // 2 * 175 - base gas fee for create (by contract) - // ((21 / 2) * 2) - price per account creation - let expected_gas_after_create = - 100_000_000 - 11 - (2 * 362) - (2 * 135) - (2 * 175) - ((21 / 2) * 2); - assert_eq!(Balances::free_balance(&0), expected_gas_after_create); - assert_eq!(Balances::free_balance(&1), 8); - assert_eq!(Balances::free_balance(&derived_address), 3); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount( - derived_address, - 0, - balances::NewAccountOutcome::NoHint - ) - ), - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(0, 1, 11)), - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(1, 2, 3)), - }, - ]); - - // Initiate transfer to the newly created contract. - assert_ok!(Contract::call(Origin::signed(0), derived_address, 22.into(), 100_000.into(), Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 22 - value sent with the transaction - // (2 * 26) - gas used by the contract - // (2 * 135) - base gas fee for call (top level) - // (2 * 135) - base gas fee for call (by transfer contract) - expected_gas_after_create - 22 - (2 * 26) - (2 * 135) - (2 * 135), - ); - assert_eq!(Balances::free_balance(&derived_address), 22 - 3); - assert_eq!(Balances::free_balance(&9), 36); - }); -} - -#[test] -fn top_level_create() { - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - let code_ctor_transfer = wabt::wat2wasm(&code_ctor(&code_transfer)).unwrap(); - - with_externalities(&mut ExtBuilder::default().gas_price(3).build(), || { - let derived_address = ::DetermineContractAddress::contract_address_for( - &code_ctor_transfer, - &[], - &0, - ); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&derived_address, 30); - Balances::increase_total_stake_by(30); - assert_ok!(Contract::create( + assert_ok!(Contract::call( Origin::signed(0), - 11.into(), - 100_000.into(), - code_ctor_transfer.clone(), - Vec::new(), + 1, + 0, + 100_000, + Vec::new() )); - // 11 - value sent with the transaction - // (3 * 129) - gas spent by the init_code. - // (3 * 175) - base gas fee for create (175) (top level) multipled by gas price (3) - // ((21 / 3) * 3) - price for contract creation - assert_eq!( - Balances::free_balance(&0), - 100_000_000 - 11 - (3 * 129) - (3 * 175) - ((21 / 3) * 3) - ); - assert_eq!(Balances::free_balance(&derived_address), 30 + 11); - - assert_eq!(>::get(&derived_address), code_transfer); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(0, derived_address, 11)), - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Created(0, 1)), - }, - ]); - }); -} - -const CODE_NOP: &'static str = r#" -(module - (func (export "call") - nop - ) -) -"#; - -#[test] -fn refunds_unused_gas() { - let code_nop = wabt::wat2wasm(CODE_NOP).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(1, code_nop.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - assert_ok!(Contract::call(Origin::signed(0), 1, 0.into(), 100_000.into(), Vec::new())); - - assert_eq!(Balances::free_balance(&0), 100_000_000 - 4 - (2 * 135)); - }); -} - -#[test] -fn call_with_zero_value() { - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(1, vec![]); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - assert_ok!(Contract::call(Origin::signed(0), 1, 0.into(), 100_000.into(), Vec::new())); - assert_eq!(Balances::free_balance(&0), 100_000_000 - (2 * 135)); }); } -#[test] -fn create_with_zero_endowment() { - let code_nop = wabt::wat2wasm(CODE_NOP).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - assert_ok!(Contract::create(Origin::signed(0), 0.into(), 100_000.into(), code_nop, Vec::new())); - - assert_eq!( - Balances::free_balance(&0), - // 4 - for the gas spent by the constructor - // 2 * 175 - base gas fee for create (175) multiplied by gas price (2) (top level) - 100_000_000 - 4 - (2 * 175), - ); - }); -} - #[test] fn account_removal_removes_storage() { with_externalities( @@ -692,33 +223,33 @@ fn account_removal_removes_storage() { { Balances::set_free_balance(&1, 110); Balances::increase_total_stake_by(110); - >::insert(1, b"foo".to_vec(), b"1".to_vec()); - >::insert(1, b"bar".to_vec(), b"2".to_vec()); + >::insert(&1, &b"foo".to_vec(), b"1".to_vec()); + >::insert(&1, &b"bar".to_vec(), b"2".to_vec()); Balances::set_free_balance(&2, 110); Balances::increase_total_stake_by(110); - >::insert(2, b"hello".to_vec(), b"3".to_vec()); - >::insert(2, b"world".to_vec(), b"4".to_vec()); + >::insert(&2, &b"hello".to_vec(), b"3".to_vec()); + >::insert(&2, &b"world".to_vec(), b"4".to_vec()); } // Transfer funds from account 1 of such amount that after this transfer // the balance of account 1 is will be below than exsistential threshold. // // This should lead to the removal of all storage associated with this account. - assert_ok!(Balances::transfer(Origin::signed(1), 2.into(), 20.into())); + assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); // Verify that all entries from account 1 is removed, while // entries from account 2 is in place. { - assert_eq!(>::get(1, b"foo".to_vec()), None); - assert_eq!(>::get(1, b"bar".to_vec()), None); + assert_eq!(>::get(&1, &b"foo".to_vec()), None); + assert_eq!(>::get(&1, &b"bar".to_vec()), None); assert_eq!( - >::get(2, b"hello".to_vec()), + >::get(&2, &b"hello".to_vec()), Some(b"3".to_vec()) ); assert_eq!( - >::get(2, b"world".to_vec()), + >::get(&2, &b"world".to_vec()), Some(b"4".to_vec()) ); } @@ -726,232 +257,182 @@ fn account_removal_removes_storage() { ); } -const CODE_UNREACHABLE: &'static str = r#" +const CODE_RETURN_FROM_START_FN: &str = r#" (module - (func (export "call") - nop - unreachable - ) -) -"#; - -#[test] -fn top_level_call_refunds_even_if_fails() { - let code_unreachable = wabt::wat2wasm(CODE_UNREACHABLE).unwrap(); - with_externalities(&mut ExtBuilder::default().gas_price(4).build(), || { - >::insert(1, code_unreachable.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - assert_err!( - Contract::call(Origin::signed(0), 1, 0.into(), 100_000.into(), Vec::new()), - "vm execute returned error while call" - ); - - assert_eq!(Balances::free_balance(&0), 100_000_000 - (4 * 3) - (4 * 135)); - - assert_eq!(System::events(), vec![]); - }); -} + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "memory" (memory 1 1)) -const CODE_LOOP: &'static str = r#" -(module - (func (export "call") - (loop - (br 0) + (start $start) + (func $start + (call $ext_return + (i32.const 8) + (i32.const 4) ) + (unreachable) ) -) -"#; - -#[test] -fn block_gas_limit() { - let code_loop = wabt::wat2wasm(CODE_LOOP).unwrap(); - with_externalities( - &mut ExtBuilder::default().block_gas_limit(100_000).build(), - || { - >::insert(1, code_loop.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - // Spend 50_000 units of gas (OOG). - assert_err!( - Contract::call(Origin::signed(0), 1, 0.into(), 50_000.into(), Vec::new()), - "vm execute returned error while call" - ); - - // Ensure we can't spend more gas than available in block gas limit. - assert_err!( - Contract::call(Origin::signed(0), 1, 0.into(), 50_001.into(), Vec::new()), - "block gas limit is reached" - ); - - // However, we can spend another 50_000 - assert_err!( - Contract::call(Origin::signed(0), 1, 0.into(), 50_000.into(), Vec::new()), - "vm execute returned error while call" - ); - }, - ); -} - -const CODE_INPUT_DATA: &'static str = r#" -(module - (import "env" "ext_input_size" (func $ext_input_size (result i32))) - (import "env" "ext_input_copy" (func $ext_input_copy (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) (func (export "call") - (block $fail - ;; fail if ext_input_size != 4 - (br_if $fail - (i32.ne - (i32.const 4) - (call $ext_input_size) - ) - ) - - (call $ext_input_copy - (i32.const 0) - (i32.const 0) - (i32.const 4) - ) - - - (br_if $fail - (i32.ne - (i32.load8_u (i32.const 0)) - (i32.const 0) - ) - ) - (br_if $fail - (i32.ne - (i32.load8_u (i32.const 1)) - (i32.const 1) - ) - ) - (br_if $fail - (i32.ne - (i32.load8_u (i32.const 2)) - (i32.const 2) - ) - ) - (br_if $fail - (i32.ne - (i32.load8_u (i32.const 3)) - (i32.const 3) - ) - ) - - (return) - ) - unreachable + (unreachable) ) + (func (export "deploy")) + + (data (i32.const 8) "\01\02\03\04") ) "#; +const HASH_RETURN_FROM_START_FN: [u8; 32] = hex!("e6411d12daa2a19e4e9c7d8306c31c7d53a352cb8ed84385c8a1d48fc232e708"); #[test] -fn input_data() { - let code_input_data = wabt::wat2wasm(CODE_INPUT_DATA).unwrap(); +fn instantiate_and_call() { + let wasm = wabt::wat2wasm(CODE_RETURN_FROM_START_FN).unwrap(); + with_externalities( - &mut ExtBuilder::default().build(), + &mut ExtBuilder::default().existential_deposit(100).build(), || { - >::insert(1, code_input_data.to_vec()); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - - assert_ok!(Contract::call(Origin::signed(0), 1, 0.into(), 50_000.into(), vec![0, 1, 2, 3])); - - // all asserts are made within contract code itself. + Balances::set_free_balance(&ALICE, 1_000_000); + Balances::increase_total_stake_by(1_000_000); + + assert_ok!(Contract::put_code( + Origin::signed(ALICE), + 100_000, + wasm, + )); + + assert_ok!(Contract::create( + Origin::signed(ALICE), + 100, + 100_000, + HASH_RETURN_FROM_START_FN.into(), + vec![], + )); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(HASH_RETURN_FROM_START_FN.into())), + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(BOB, 100) + ) + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)) + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)) + } + ]); }, ); } -/// Stores the caller into the storage under the [0x00; 32] key in the contract's storage. -const CODE_CALLER_LOGGER: &'static str = r#" +const CODE_DISPATCH_CALL: &str = r#" (module - (import "env" "ext_caller" (func $ext_caller)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) (import "env" "memory" (memory 1 1)) - ;; Memory layout - ;; [0..32]: the storage key (passed as the key for ext_set_storage) - ;; [32..40]: contents of the scratch buffer (which is expected to be 8 bytes long) - (func (export "call") - ;; Fill the scratch buffer with the caller. - (call $ext_caller) - - ;; Copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_copy - (i32.const 32) ;; Store scratch's buffer contents at this address. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - (call $ext_set_storage - (i32.const 0) ;; The storage key to save the value at. 32 bytes long. - (i32.const 1) ;; value_not_null=1, i.e. we are not removing the value - (i32.const 32) ;; the pointer to the value to store - (i32.const 8) ;; the length of the value + (call $ext_dispatch_call + (i32.const 8) ;; Pointer to the start of encoded call buffer + (i32.const 11) ;; Length of the buffer ) ) + (func (export "deploy")) + + (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") ) "#; +const HASH_DISPATCH_CALL: [u8; 32] = hex!("49dfdcaf9c1553be10634467e95b8e71a3bc15a4f8bf5563c0312b0902e0afb9"); #[test] -fn caller_top_level() { - let code_caller_logger = wabt::wat2wasm(CODE_CALLER_LOGGER).unwrap(); - with_externalities( - &mut ExtBuilder::default().build(), - || { - >::insert(1, code_caller_logger.to_vec()); +fn dispatch_call() { + // This test can fail due to the encoding changes. In case it becomes too annoying + // let's rewrite so as we use this module controlled call or we serialize it in runtime. + let encoded = parity_codec::Encode::encode(&Call::Balances(balances::Call::transfer(CHARLIE, 50))); + assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - Balances::set_free_balance(&2, 100_000_000); - Balances::increase_total_stake_by(100_000_000); + let wasm = wabt::wat2wasm(CODE_DISPATCH_CALL).unwrap(); - assert_ok!(Contract::call(Origin::signed(2), 1, 0.into(), 50_000.into(), vec![])); - - // Load the zero-th slot of the storage of the caller logger contract. - // We verify here that the caller logger contract has witnessed the call coming from - // the account with address 0x02 (see the origin above) - the origin of the tx. - assert_eq!( - >::get(1, vec![0; 32]), - Some(vec![0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), - ); + with_externalities( + &mut ExtBuilder::default().existential_deposit(50).build(), + || { + Balances::set_free_balance(&ALICE, 1_000_000); + Balances::increase_total_stake_by(1_000_000); + + assert_ok!(Contract::put_code( + Origin::signed(ALICE), + 100_000, + wasm, + )); + + // Let's keep this assert even though it's redundant. If you ever need to update the + // wasm source this test will fail and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(HASH_DISPATCH_CALL.into())), + }, + ]); + + assert_ok!(Contract::create( + Origin::signed(ALICE), + 100, + 100_000, + HASH_DISPATCH_CALL.into(), + vec![], + )); + + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + 100_000, + vec![], + )); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(HASH_DISPATCH_CALL.into())), + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(BOB, 100) + ) + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)) + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)) + }, + + // Dispatching the call. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(CHARLIE, 50) + ) + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::Transfer(BOB, CHARLIE, 50, 0) + ) + }, + + // Event emited as a result of dispatch. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Dispatched(BOB, true)) + } + ]); }, ); } - -#[test] -fn caller_contract() { - const CONTRACT_SHOULD_TRANSFER_TO: u64 = 9; - - let code_caller_logger = wabt::wat2wasm(CODE_CALLER_LOGGER).unwrap(); - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - with_externalities(&mut ExtBuilder::default().build(), || { - >::insert(1, code_transfer.to_vec()); - >::insert(CONTRACT_SHOULD_TRANSFER_TO, code_caller_logger); - - Balances::set_free_balance(&0, 100_000_000); - Balances::increase_total_stake_by(100_000_000); - Balances::set_free_balance(&1, 11); - Balances::increase_total_stake_by(11); - - assert_ok!(Contract::call(Origin::signed(0), 1, 3.into(), 100_000.into(), Vec::new())); - - // Load the zero-th slot of the storage of the caller logger contract. - // We verify here that the caller logger contract has witnessed the call coming from - // the caller contract - 0x01. - assert_eq!( - >::get(CONTRACT_SHOULD_TRANSFER_TO, vec![0; 32]), - Some(vec![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), - ); - }); -} diff --git a/srml/contract/src/vm/mod.rs b/srml/contract/src/vm/mod.rs deleted file mode 100644 index b46264bbd6fc28887c19153482d55c04cf7ab460..0000000000000000000000000000000000000000 --- a/srml/contract/src/vm/mod.rs +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! This module provides a means for executing contracts -//! represented in wasm. - -use exec::CreateReceipt; -use gas::GasMeter; -use rstd::prelude::*; -use {Trait, Schedule}; -use {balances, sandbox, system}; - -type BalanceOf = ::Balance; -type AccountIdOf = ::AccountId; - -mod prepare; -#[macro_use] -mod env_def; -mod runtime; - -use self::prepare::{prepare_contract, PreparedContract}; -use self::runtime::{to_execution_result, Runtime}; - -/// An interface that provides an access to the external environment in which the -/// smart-contract is executed. -/// -/// This interface is specialised to an account of the executing code, so all -/// operations are implicitly performed on that account. -pub trait Ext { - type T: Trait; - - /// Returns the storage entry of the executing account by the given key. - fn get_storage(&self, key: &[u8]) -> Option>; - - /// Sets the storage entry by the given key to the specified value. - fn set_storage(&mut self, key: &[u8], value: Option>); - - /// Create a new account for a contract. - /// - /// The newly created account will be associated with the `code`. `value` specifies the amount of value - /// transfered from this to the newly created account. - fn create( - &mut self, - code: &[u8], - value: BalanceOf, - gas_meter: &mut GasMeter, - data: &[u8], - ) -> Result, ()>; - - /// Call (possibly transfering some amount of funds) into the specified account. - fn call( - &mut self, - to: &AccountIdOf, - value: BalanceOf, - gas_meter: &mut GasMeter, - data: &[u8], - output_data: &mut Vec, - ) -> Result<(), ()>; - - /// Returns a reference to the account id of the caller. - fn caller(&self) -> &AccountIdOf; -} - -/// Error that can occur while preparing or executing wasm smart-contract. -#[derive(Debug, PartialEq, Eq)] -pub enum Error { - /// Error happened while serializing the module. - Serialization, - - /// Error happened while deserializing the module. - Deserialization, - - /// Internal memory declaration has been found in the module. - InternalMemoryDeclared, - - /// Gas instrumentation failed. - /// - /// This most likely indicates the module isn't valid. - GasInstrumentation, - - /// Stack instrumentation failed. - /// - /// This most likely indicates the module isn't valid. - StackHeightInstrumentation, - - /// Error happened during invocation of the contract's entrypoint. - /// - /// Most likely because of trap. - Invoke, - - /// Error happened during instantiation. - /// - /// This might indicate that `start` function trapped, or module isn't - /// instantiable and/or unlinkable. - Instantiate, - - /// Memory creation error. - /// - /// This might happen when the memory import has invalid descriptor or - /// requested too much resources. - Memory, -} - -/// Execute the given code as a contract. -pub fn execute<'a, E: Ext>( - code: &[u8], - input_data: &[u8], - output_data: &mut Vec, - ext: &'a mut E, - schedule: &Schedule<::Gas>, - gas_meter: &mut GasMeter, -) -> Result<(), Error> { - let env = runtime::init_env(); - - let PreparedContract { - instrumented_code, - memory, - } = prepare_contract(code, &schedule, &env)?; - - let mut imports = sandbox::EnvironmentDefinitionBuilder::new(); - for (func_name, ext_func) in &env.funcs { - imports.add_host_func("env", &func_name[..], ext_func.raw_fn_ptr()); - } - imports.add_memory("env", "memory", memory.clone()); - - let mut runtime = Runtime::new(ext, input_data, output_data, &schedule, memory, gas_meter); - - // Instantiate the instance from the instrumented module code. - match sandbox::Instance::new(&instrumented_code, &imports, &mut runtime) { - // No errors or traps were generated on instantiation! That - // means we can now invoke the contract entrypoint. - Ok(mut instance) => { - let err = instance.invoke(b"call", &[], &mut runtime).err(); - to_execution_result(runtime, err) - } - // `start` function trapped. Treat it in the same manner as an execution error. - Err(err @ sandbox::Error::Execution) => to_execution_result(runtime, Some(err)), - // Other instantiation errors. - // Return without executing anything. - Err(_) => return Err(Error::Instantiate), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use gas::GasMeter; - use std::collections::HashMap; - use tests::Test; - use wabt; - - #[derive(Debug, PartialEq, Eq)] - struct CreateEntry { - code: Vec, - endowment: u64, - data: Vec, - gas_left: u64, - } - #[derive(Debug, PartialEq, Eq)] - struct TransferEntry { - to: u64, - value: u64, - data: Vec, - gas_left: u64, - } - #[derive(Default)] - pub struct MockExt { - storage: HashMap, Vec>, - creates: Vec, - transfers: Vec, - next_account_id: u64, - } - impl Ext for MockExt { - type T = Test; - - fn get_storage(&self, key: &[u8]) -> Option> { - self.storage.get(key).cloned() - } - fn set_storage(&mut self, key: &[u8], value: Option>) { - *self.storage.entry(key.to_vec()).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); - } - fn create( - &mut self, - code: &[u8], - endowment: u64, - gas_meter: &mut GasMeter, - data: &[u8], - ) -> Result, ()> { - self.creates.push(CreateEntry { - code: code.to_vec(), - endowment, - data: data.to_vec(), - gas_left: gas_meter.gas_left(), - }); - let address = self.next_account_id; - self.next_account_id += 1; - - Ok(CreateReceipt { address }) - } - fn call( - &mut self, - to: &u64, - value: u64, - gas_meter: &mut GasMeter, - data: &[u8], - _output_data: &mut Vec, - ) -> Result<(), ()> { - self.transfers.push(TransferEntry { - to: *to, - value, - data: data.to_vec(), - gas_left: gas_meter.gas_left(), - }); - // Assume for now that it was just a plain transfer. - // TODO: Add tests for different call outcomes. - Ok(()) - } - fn caller(&self) -> &u64 { - &42 - } - } - - const CODE_TRANSFER: &str = r#" -(module - ;; ext_call( - ;; callee_ptr: u32, - ;; callee_len: u32, - ;; gas: u64, - ;; value_ptr: u32, - ;; value_len: u32, - ;; input_data_ptr: u32, - ;; input_data_len: u32 - ;;) -> u32 - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_call - (i32.const 4) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 12) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 20) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - ) - ) - ) - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") - - (data (i32.const 20) "\01\02\03\04") -) -"#; - - #[test] - fn contract_transfer() { - let code_transfer = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - - let mut mock_ext = MockExt::default(); - execute( - &code_transfer, - &[], - &mut Vec::new(), - &mut mock_ext, - &Schedule::::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.transfers, - &[TransferEntry { - to: 9, - value: 6, - data: vec![ - 1, 2, 3, 4, - ], - gas_left: 49970, - }] - ); - } - - const CODE_CREATE: &str = r#" -(module - ;; ext_create( - ;; code_ptr: u32, - ;; code_len: u32, - ;; gas: u64, - ;; value_ptr: u32, - ;; value_len: u32, - ;; input_data_ptr: u32, - ;; input_data_len: u32, - ;; ) -> u32 - (import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_create - (i32.const 12) ;; Pointer to `code` - (i32.const 8) ;; Length of `code` - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 4) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 20) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - ) - ) - ) - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\03\00\00\00\00\00\00\00") - ;; Embedded wasm code. - (data (i32.const 12) "\00\61\73\6d\01\00\00\00") - ;; Input data to pass to the contract being created. - (data (i32.const 20) "\01\02\03\04") -) -"#; - - #[test] - fn contract_create() { - let code_create = wabt::wat2wasm(CODE_CREATE).unwrap(); - - let mut mock_ext = MockExt::default(); - execute( - &code_create, - &[], - &mut Vec::new(), - &mut mock_ext, - &Schedule::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.creates, - &[CreateEntry { - code: vec![0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00], - endowment: 3, - data: vec![ - 1, 2, 3, 4, - ], - gas_left: 49970, - }] - ); - } - - const CODE_MEM: &str = r#" -(module - ;; Internal memory is not allowed. - (memory 1 1) - - (func (export "call") - nop - ) -) -"#; - - #[test] - fn contract_internal_mem() { - let code_mem = wabt::wat2wasm(CODE_MEM).unwrap(); - - let mut mock_ext = MockExt::default(); - - assert_matches!( - execute( - &code_mem, - &[], - &mut Vec::new(), - &mut mock_ext, - &Schedule::default(), - &mut GasMeter::with_limit(100_000, 1) - ), - Err(_) - ); - } - - const CODE_TRANSFER_LIMITED_GAS: &str = r#" -(module - ;; ext_call( - ;; callee_ptr: u32, - ;; callee_len: u32, - ;; gas: u64, - ;; value_ptr: u32, - ;; value_len: u32, - ;; input_data_ptr: u32, - ;; input_data_len: u32 - ;;) -> u32 - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_call - (i32.const 4) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 228) ;; How much gas to devote for the execution. - (i32.const 12) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 20) ;; Pointer to input data buffer address - (i32.const 4) ;; Length of input data buffer - ) - ) - ) - ;; Destination AccountId to transfer the funds. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 4) "\09\00\00\00\00\00\00\00") - ;; Amount of value to transfer. - ;; Represented by u64 (8 bytes long) in little endian. - (data (i32.const 12) "\06\00\00\00\00\00\00\00") - - (data (i32.const 20) "\01\02\03\04") -) -"#; - - #[test] - fn contract_call_limited_gas() { - let code_transfer = wabt::wat2wasm(CODE_TRANSFER_LIMITED_GAS).unwrap(); - - let mut mock_ext = MockExt::default(); - execute( - &code_transfer, - &[], - &mut Vec::new(), - &mut mock_ext, - &Schedule::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.transfers, - &[TransferEntry { - to: 9, - value: 6, - data: vec![ - 1, 2, 3, 4, - ], - gas_left: 228, - }] - ); - } - - const CODE_GET_STORAGE: &str = r#" -(module - (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (local $buf_size i32) - - - ;; Load a storage value into the scratch buf. - (call $assert - (i32.eq - (call $ext_get_storage - (i32.const 4) ;; The pointer to the storage key to fetch - ) - - ;; Return value 0 means that the value is found and there were - ;; no errors. - (i32.const 0) - ) - ) - - ;; Find out the size of the scratch buffer - (set_local $buf_size - (call $ext_scratch_size) - ) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_copy - (i32.const 36) ;; The pointer where to store the scratch buffer contents, - ;; 36 = 4 + 32 - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local ;; Count of bytes to copy. - $buf_size - ) - ) - - ;; Return the contents of the buffer - (call $ext_return - (i32.const 36) - (get_local $buf_size) - ) - - ;; env:ext_return doesn't return, so this is effectively unreachable. - (unreachable) - ) - - (data (i32.const 4) "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11") -) -"#; - - #[test] - fn get_storage_puts_data_into_scratch_buf() { - let code_get_storage = wabt::wat2wasm(CODE_GET_STORAGE).unwrap(); - - let mut mock_ext = MockExt::default(); - mock_ext.storage.insert([0x11; 32].to_vec(), [0x22; 32].to_vec()); - - let mut return_buf = Vec::new(); - execute( - &code_get_storage, - &[], - &mut return_buf, - &mut mock_ext, - &Schedule::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - return_buf, - [0x22; 32].to_vec(), - ); - } - - - /// calls `ext_caller`, loads the address from the scratch buffer and - /// compares it with the constant 42. - const CODE_CALLER: &'static str = -r#" -(module - (import "env" "ext_caller" (func $ext_caller)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; fill the scratch buffer with the caller. - (call $ext_caller) - - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_copy - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 42. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 42) - ) - ) - ) -) -"#; - - #[test] - fn caller() { - let code_caller = wabt::wat2wasm(CODE_CALLER).unwrap(); - - let mut mock_ext = MockExt::default(); - execute( - &code_caller, - &[], - &mut Vec::new(), - &mut mock_ext, - &Schedule::::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - } -} diff --git a/srml/contract/src/vm/prepare.rs b/srml/contract/src/vm/prepare.rs deleted file mode 100644 index 8ec056dfc71b5d48635b02d5862bf78f10c5b1f7..0000000000000000000000000000000000000000 --- a/srml/contract/src/vm/prepare.rs +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Module that takes care of loading, checking and preprocessing of a -//! wasm module before execution. - -use super::env_def::HostFunctionSet; -use super::{Error, Ext}; -use rstd::prelude::*; -use parity_wasm::elements::{self, External, MemoryType, Type}; -use pwasm_utils; -use pwasm_utils::rules; -use runtime_primitives::traits::As; -use sandbox; -use {Trait, Schedule}; - -struct ContractModule<'a, Gas: 'a> { - // An `Option` is used here for loaning (`take()`-ing) the module. - // Invariant: Can't be `None` (i.e. on enter and on exit from the function - // the value *must* be `Some`). - module: Option, - schedule: &'a Schedule, -} - -impl<'a, Gas: 'a + As + Clone> ContractModule<'a, Gas> { - fn new(original_code: &[u8], schedule: &'a Schedule) -> Result, Error> { - let module = - elements::deserialize_buffer(original_code).map_err(|_| Error::Deserialization)?; - Ok(ContractModule { - module: Some(module), - schedule, - }) - } - - /// Ensures that module doesn't declare internal memories. - /// - /// In this runtime we only allow wasm module to import memory from the environment. - /// Memory section contains declarations of internal linear memories, so if we find one - /// we reject such a module. - fn ensure_no_internal_memory(&self) -> Result<(), Error> { - let module = self - .module - .as_ref() - .expect("On entry to the function `module` can't be None; qed"); - if module - .memory_section() - .map_or(false, |ms| ms.entries().len() > 0) - { - return Err(Error::InternalMemoryDeclared); - } - Ok(()) - } - - fn inject_gas_metering(&mut self) -> Result<(), Error> { - let gas_rules = rules::Set::new(self.schedule.regular_op_cost.clone().as_(), Default::default()) - .with_grow_cost(self.schedule.grow_mem_cost.clone().as_()) - .with_forbidden_floats(); - - let module = self - .module - .take() - .expect("On entry to the function `module` can't be `None`; qed"); - - let contract_module = pwasm_utils::inject_gas_counter(module, &gas_rules) - .map_err(|_| Error::GasInstrumentation)?; - - self.module = Some(contract_module); - Ok(()) - } - - fn inject_stack_height_metering(&mut self) -> Result<(), Error> { - let module = self - .module - .take() - .expect("On entry to the function `module` can't be `None`; qed"); - - let contract_module = - pwasm_utils::stack_height::inject_limiter(module, self.schedule.max_stack_height) - .map_err(|_| Error::StackHeightInstrumentation)?; - - self.module = Some(contract_module); - Ok(()) - } - - /// Scan an import section if any. - /// - /// This accomplishes two tasks: - /// - /// - checks any imported function against defined host functions set, incl. - /// their signatures. - /// - if there is a memory import, returns it's descriptor - fn scan_imports(&self, env: &HostFunctionSet) -> Result, Error> { - let module = self - .module - .as_ref() - .expect("On entry to the function `module` can't be `None`; qed"); - - let types = module.type_section().map(|ts| ts.types()).unwrap_or(&[]); - let import_entries = module - .import_section() - .map(|is| is.entries()) - .unwrap_or(&[]); - - let mut imported_mem_type = None; - - for import in import_entries { - if import.module() != "env" { - // This import tries to import something from non-"env" module, - // but all imports are located in "env" at the moment. - return Err(Error::Instantiate); - } - - let type_idx = match import.external() { - &External::Function(ref type_idx) => type_idx, - &External::Memory(ref memory_type) => { - imported_mem_type = Some(memory_type); - continue; - } - _ => continue, - }; - - let Type::Function(ref func_ty) = types - .get(*type_idx as usize) - .ok_or_else(|| Error::Instantiate)?; - - let ext_func = env - .funcs - .get(import.field().as_bytes()) - .ok_or_else(|| Error::Instantiate)?; - if !ext_func.func_type_matches(func_ty) { - return Err(Error::Instantiate); - } - } - Ok(imported_mem_type) - } - - fn into_wasm_code(mut self) -> Result, Error> { - elements::serialize( - self.module - .take() - .expect("On entry to the function `module` can't be `None`; qed"), - ).map_err(|_| Error::Serialization) - } -} - -pub(super) struct PreparedContract { - pub instrumented_code: Vec, - pub memory: sandbox::Memory, -} - -/// Loads the given module given in `original_code`, performs some checks on it and -/// does some preprocessing. -/// -/// The checks are: -/// -/// - module doesn't define an internal memory instance, -/// - imported memory (if any) doesn't reserve more memory than permitted by the `schedule`, -/// - all imported functions from the external environment matches defined by `env` module, -/// -/// The preprocessing includes injecting code for gas metering and metering the height of stack. -pub(super) fn prepare_contract( - original_code: &[u8], - schedule: &Schedule<::Gas>, - env: &HostFunctionSet, -) -> Result { - let mut contract_module = ContractModule::new(original_code, schedule)?; - contract_module.ensure_no_internal_memory()?; - contract_module.inject_gas_metering()?; - contract_module.inject_stack_height_metering()?; - - let memory = if let Some(memory_type) = contract_module.scan_imports(env)? { - // Inspect the module to extract the initial and maximum page count. - let limits = memory_type.limits(); - match (limits.initial(), limits.maximum()) { - (initial, Some(maximum)) if initial > maximum => { - // Requested initial number of pages should not exceed the requested maximum. - return Err(Error::Memory); - } - (_, Some(maximum)) if maximum > schedule.max_memory_pages => { - // Maximum number of pages should not exceed the configured maximum. - return Err(Error::Memory); - } - (_, None) => { - // Maximum number of pages should be always declared. - // This isn't a hard requirement and can be treated as a maxiumum set - // to configured maximum. - return Err(Error::Memory); - } - (initial, maximum) => sandbox::Memory::new(initial, maximum), - } - } else { - // If none memory imported then just crate an empty placeholder. - // Any access to it will lead to out of bounds trap. - sandbox::Memory::new(0, Some(0)) - }; - let memory = memory.map_err(|_| Error::Memory)?; - - Ok(PreparedContract { - instrumented_code: contract_module.into_wasm_code()?, - memory, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::fmt; - use vm::tests::MockExt; - use wabt; - - impl fmt::Debug for PreparedContract { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "PreparedContract {{ .. }}") - } - } - - fn parse_and_prepare_wat(wat: &str) -> Result { - let wasm = wabt::Wat2Wasm::new().validate(false).convert(wat).unwrap(); - let schedule = Schedule::::default(); - let env = ::vm::runtime::init_env(); - prepare_contract::(wasm.as_ref(), &schedule, &env) - } - - #[test] - fn internal_memory_declaration() { - let r = parse_and_prepare_wat(r#"(module (memory 1 1))"#); - assert_matches!(r, Err(Error::InternalMemoryDeclared)); - } - - #[test] - fn memory() { - // This test assumes that maximum page number is configured to a certain number. - assert_eq!(Schedule::::default().max_memory_pages, 16); - - let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1 1)))"#); - assert_matches!(r, Ok(_)); - - // No memory import - let r = parse_and_prepare_wat(r#"(module)"#); - assert_matches!(r, Ok(_)); - - // initial exceed maximum - let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 16 1)))"#); - assert_matches!(r, Err(Error::Memory)); - - // no maximum - let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1)))"#); - assert_matches!(r, Err(Error::Memory)); - - // requested maximum exceed configured maximum - let r = parse_and_prepare_wat(r#"(module (import "env" "memory" (memory 1 17)))"#); - assert_matches!(r, Err(Error::Memory)); - } - - #[test] - fn imports() { - // nothing can be imported from non-"env" module for now. - let r = parse_and_prepare_wat(r#"(module (import "another_module" "memory" (memory 1 1)))"#); - assert_matches!(r, Err(Error::Instantiate)); - - let r = parse_and_prepare_wat(r#"(module (import "env" "gas" (func (param i32))))"#); - assert_matches!(r, Ok(_)); - - // wrong signature - let r = parse_and_prepare_wat(r#"(module (import "env" "gas" (func (param i64))))"#); - assert_matches!(r, Err(Error::Instantiate)); - - // unknown function name - let r = parse_and_prepare_wat(r#"(module (import "env" "unknown_func" (func)))"#); - assert_matches!(r, Err(Error::Instantiate)); - } -} diff --git a/srml/contract/src/wasm/code_cache.rs b/srml/contract/src/wasm/code_cache.rs new file mode 100644 index 0000000000000000000000000000000000000000..dab8c4bfa4b04a7ab931688affb74ff807e24af2 --- /dev/null +++ b/srml/contract/src/wasm/code_cache.rs @@ -0,0 +1,106 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A module that implements instrumented code cache. +//! +//! - In order to run contract code we need to instrument it with gas metering. +//! To do that we need to provide the schedule which will supply exact gas costs values. +//! We cache this code in the storage saving the schedule version. +//! - Before running contract code we check if the cached code has the schedule version that is equal to the current saved schedule. +//! If it is equal then run the code, if it isn't reinstrument with the current schedule. +//! - When we update the schedule we want it to have strictly greater version than the current saved one: +//! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one. +//! Thus, before executing a contract it should be reinstrument with new schedule. + +use crate::gas::{GasMeter, Token}; +use crate::wasm::{prepare, runtime::Env, PrefabWasmModule}; +use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait}; +use rstd::prelude::*; +use runtime_primitives::traits::{As, CheckedMul, Hash, Bounded}; +use srml_support::StorageMap; + +/// Gas metering token that used for charging storing code into the code storage. +/// +/// Specifies the code length in bytes. +#[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub struct PutCodeToken(u64); + +impl Token for PutCodeToken { + type Metadata = Schedule; + + fn calculate_amount(&self, metadata: &Schedule) -> T::Gas { + let code_len_in_gas = >::sa(self.0); + metadata + .put_code_per_byte_cost + .checked_mul(&code_len_in_gas) + .unwrap_or_else(|| Bounded::max_value()) + } +} + +/// Put code in the storage. The hash of code is used as a key and is returned +/// as a result of this function. +/// +/// This function instruments the given code and caches it in the storage. +pub fn save( + original_code: Vec, + gas_meter: &mut GasMeter, + schedule: &Schedule, +) -> Result, &'static str> { + // The first time instrumentation is on the user. However, consequent reinstrumentation + // due to the schedule changes is on governance system. + if gas_meter + .charge(schedule, PutCodeToken(original_code.len() as u64)) + .is_out_of_gas() + { + return Err("there is not enough gas for storing the code"); + } + + let prefab_module = prepare::prepare_contract::(&original_code, schedule)?; + let code_hash = T::Hashing::hash(&original_code); + + // TODO: #1416 validate the code. If the code is not valid, then don't store it. + + >::insert(code_hash, prefab_module); + >::insert(code_hash, original_code); + + Ok(code_hash) +} + +/// Load code with the given code hash. +/// +/// If the module was instrumented with a lower version of schedule than +/// the current one given as an argument, then this function will perform +/// re-instrumentation and update the cache in the storage. +pub fn load( + code_hash: &CodeHash, + schedule: &Schedule, +) -> Result { + let mut prefab_module = + >::get(code_hash).ok_or_else(|| "code is not found")?; + + if prefab_module.schedule_version < schedule.version { + // The current schedule version is greater than the version of the one cached + // in the storage. + // + // We need to re-instrument the code with the latest schedule here. + let original_code = + >::get(code_hash).ok_or_else(|| "pristine code is not found")?; + prefab_module = prepare::prepare_contract::(&original_code, schedule)?; + >::insert(code_hash, prefab_module.clone()); + } + Ok(prefab_module) +} diff --git a/srml/contract/src/vm/env_def/macros.rs b/srml/contract/src/wasm/env_def/macros.rs similarity index 67% rename from srml/contract/src/vm/env_def/macros.rs rename to srml/contract/src/wasm/env_def/macros.rs index c751bd0c127283282081e04117f3f837ac9c4849..0b112a825858d06b45760ec6c60c67821486fdc5 100644 --- a/srml/contract/src/vm/env_def/macros.rs +++ b/srml/contract/src/wasm/env_def/macros.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,38 +17,58 @@ //! Definition of macros that hides boilerplate of defining external environment //! for a wasm module. //! -//! Typically you should use `define_env` macro. +//! Most likely you should use `define_env` macro. #[macro_export] macro_rules! convert_args { () => (vec![]); - ( $( $t:ty ),* ) => ( vec![ $( { use $crate::vm::env_def::ConvertibleToWasm; <$t>::VALUE_TYPE }, )* ] ); + ( $( $t:ty ),* ) => ( vec![ $( { use $crate::wasm::env_def::ConvertibleToWasm; <$t>::VALUE_TYPE }, )* ] ); } #[macro_export] macro_rules! gen_signature { ( ( $( $params: ty ),* ) ) => ( { - $crate::parity_wasm::elements::FunctionType::new(convert_args!($($params),*), None) + parity_wasm::elements::FunctionType::new(convert_args!($($params),*), None) } ); ( ( $( $params: ty ),* ) -> $returns: ty ) => ( { - $crate::parity_wasm::elements::FunctionType::new(convert_args!($($params),*), Some({ - use $crate::vm::env_def::ConvertibleToWasm; <$returns>::VALUE_TYPE + parity_wasm::elements::FunctionType::new(convert_args!($($params),*), Some({ + use $crate::wasm::env_def::ConvertibleToWasm; <$returns>::VALUE_TYPE })) } ); } +#[macro_export] +macro_rules! gen_signature_dispatch { + ( + $needle_name:ident, + $needle_sig:ident ; + $name:ident + ( $ctx:ident $( , $names:ident : $params:ty )* ) $( -> $returns:ty )* , $($rest:tt)* ) => { + if stringify!($name).as_bytes() == $needle_name { + let signature = gen_signature!( ( $( $params ),* ) $( -> $returns )* ); + if $needle_sig == &signature { + return true; + } + } else { + gen_signature_dispatch!($needle_name, $needle_sig ; $($rest)*); + } + }; + ( $needle_name:ident, $needle_sig:ident ; ) => { + }; +} + /// Unmarshall arguments and then execute `body` expression and return its result. macro_rules! unmarshall_then_body { ( $body:tt, $ctx:ident, $args_iter:ident, $( $names:ident : $params:ty ),* ) => ({ $( - let $names : <$params as $crate::vm::env_def::ConvertibleToWasm>::NativeType = + let $names : <$params as $crate::wasm::env_def::ConvertibleToWasm>::NativeType = $args_iter.next() - .and_then(|v| <$params as $crate::vm::env_def::ConvertibleToWasm> + .and_then(|v| <$params as $crate::wasm::env_def::ConvertibleToWasm> ::from_typed_value(v.clone())) .expect( "precondition: all imports should be checked against the signatures of corresponding @@ -76,7 +96,7 @@ macro_rules! unmarshall_then_body { #[inline(always)] pub fn constrain_closure(f: F) -> F where - F: FnOnce() -> Result, + F: FnOnce() -> Result, { f } @@ -84,20 +104,20 @@ where #[macro_export] macro_rules! unmarshall_then_body_then_marshall { ( $args_iter:ident, $ctx:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({ - let body = $crate::vm::env_def::macros::constrain_closure::< - <$returns as $crate::vm::env_def::ConvertibleToWasm>::NativeType, _ + let body = $crate::wasm::env_def::macros::constrain_closure::< + <$returns as $crate::wasm::env_def::ConvertibleToWasm>::NativeType, _ >(|| { unmarshall_then_body!($body, $ctx, $args_iter, $( $names : $params ),*) }); let r = body()?; - return Ok($crate::sandbox::ReturnValue::Value({ use $crate::vm::env_def::ConvertibleToWasm; r.to_typed_value() })) + return Ok(sandbox::ReturnValue::Value({ use $crate::wasm::env_def::ConvertibleToWasm; r.to_typed_value() })) }); ( $args_iter:ident, $ctx:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({ - let body = $crate::vm::env_def::macros::constrain_closure::<(), _>(|| { + let body = $crate::wasm::env_def::macros::constrain_closure::<(), _>(|| { unmarshall_then_body!($body, $ctx, $args_iter, $( $names : $params ),*) }); body()?; - return Ok($crate::sandbox::ReturnValue::Unit) + return Ok(sandbox::ReturnValue::Unit) }) } @@ -105,8 +125,8 @@ macro_rules! unmarshall_then_body_then_marshall { macro_rules! define_func { ( < E: $ext_ty:tt > $name:ident ( $ctx: ident $(, $names:ident : $params:ty)*) $(-> $returns:ty)* => $body:tt ) => { fn $name< E: $ext_ty >( - $ctx: &mut $crate::vm::Runtime, - args: &[$crate::sandbox::TypedValue], + $ctx: &mut $crate::wasm::Runtime, + args: &[sandbox::TypedValue], ) -> Result { #[allow(unused)] let mut args = args.iter(); @@ -120,6 +140,27 @@ macro_rules! define_func { }; } +#[macro_export] +macro_rules! register_func { + ( $reg_cb:ident, < E: $ext_ty:tt > ; ) => {}; + + ( $reg_cb:ident, < E: $ext_ty:tt > ; + $name:ident ( $ctx:ident $( , $names:ident : $params:ty )* ) + $( -> $returns:ty )* => $body:tt $($rest:tt)* + ) => { + $reg_cb( + stringify!($name).as_bytes(), + { + define_func!( + < E: $ext_ty > $name ( $ctx $(, $names : $params )* ) $( -> $returns )* => $body + ); + $name:: + } + ); + register_func!( $reg_cb, < E: $ext_ty > ; $($rest)* ); + }; +} + /// Define a function set that can be imported by executing wasm code. /// /// **NB**: Be advised that all functions defined by this macro @@ -132,25 +173,20 @@ macro_rules! define_env { $( $name:ident ( $ctx:ident $( , $names:ident : $params:ty )* ) $( -> $returns:ty )* => $body:tt , )* ) => { - pub(crate) fn $init_name() -> $crate::vm::env_def::HostFunctionSet { - let mut env = $crate::vm::env_def::HostFunctionSet::new(); - - $( - env.funcs.insert( - stringify!( $name ).into(), - $crate::vm::env_def::HostFunction::new( - gen_signature!( ( $( $params ),* ) $( -> $returns )* ), - { - define_func!( - < E: $ext_ty > $name ( $ctx $(, $names : $params )* ) $( -> $returns )* => $body - ); - $name:: - }, - ), - ); - )* + pub struct $init_name; - env + impl $crate::wasm::env_def::ImportSatisfyCheck for $init_name { + fn can_satisfy(name: &[u8], func_type: &parity_wasm::elements::FunctionType) -> bool { + gen_signature_dispatch!( name, func_type ; $( $name ( $ctx $(, $names : $params )* ) $( -> $returns )* , )* ); + + return false; + } + } + + impl $crate::wasm::env_def::FunctionImplProvider for $init_name { + fn impls)>(f: &mut F) { + register_func!(f, < E: $ext_ty > ; $( $name ( $ctx $( , $names : $params )* ) $( -> $returns)* => $body )* ); + } } }; } @@ -161,9 +197,10 @@ mod tests { use parity_wasm::elements::ValueType; use runtime_primitives::traits::{As, Zero}; use sandbox::{self, ReturnValue, TypedValue}; - use vm::tests::MockExt; - use vm::{Ext, Runtime}; - use Trait; + use crate::wasm::tests::MockExt; + use crate::wasm::Runtime; + use crate::exec::Ext; + use crate::Trait; #[test] fn macro_unmarshall_then_body_then_marshall_value_or_trap() { @@ -267,7 +304,9 @@ mod tests { #[test] fn macro_define_env() { - define_env!(init_env, , + use crate::wasm::env_def::ImportSatisfyCheck; + + define_env!(Env, , ext_gas( _ctx, amount: u32 ) => { let amount = <::Gas as As>::sa(amount); if !amount.is_zero() { @@ -278,7 +317,7 @@ mod tests { }, ); - let env = init_env::(); - assert!(env.funcs.get(&b"ext_gas"[..]).is_some()); + assert!(Env::can_satisfy(b"ext_gas", &FunctionType::new(vec![ValueType::I32], None))); + assert!(!Env::can_satisfy(b"not_exists", &FunctionType::new(vec![], None))); } } diff --git a/srml/contract/src/vm/env_def/mod.rs b/srml/contract/src/wasm/env_def/mod.rs similarity index 55% rename from srml/contract/src/vm/env_def/mod.rs rename to srml/contract/src/wasm/env_def/mod.rs index d66e1b8961ac8edeed5c8d7ce58d95a784893447..d51a157910d5c2c46470913ada843d0dd19f881c 100644 --- a/srml/contract/src/vm/env_def/mod.rs +++ b/srml/contract/src/wasm/env_def/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use super::{Ext, Runtime}; -use parity_wasm::elements::{FunctionType, ValueType}; -use rstd::prelude::*; -use rstd::collections::btree_map::BTreeMap; +use super::Runtime; +use crate::exec::Ext; + use sandbox::{self, TypedValue}; +use parity_wasm::elements::{FunctionType, ValueType}; #[macro_use] pub(crate) mod macros; @@ -27,7 +27,7 @@ pub trait ConvertibleToWasm: Sized { const VALUE_TYPE: ValueType; type NativeType; fn to_typed_value(self) -> TypedValue; - fn from_typed_value(TypedValue) -> Option; + fn from_typed_value(_: TypedValue) -> Option; } impl ConvertibleToWasm for i32 { type NativeType = i32; @@ -66,45 +66,21 @@ impl ConvertibleToWasm for u64 { } } -/// Represents a set of function that defined in this particular environment and -/// which can be imported and called by the module. -pub(crate) struct HostFunctionSet { - /// Functions which defined in the environment. - pub funcs: BTreeMap, HostFunction>, -} -impl HostFunctionSet { - pub fn new() -> Self { - HostFunctionSet { - funcs: BTreeMap::new(), - } - } -} +pub(crate) type HostFunc = + fn( + &mut Runtime, + &[sandbox::TypedValue] + ) -> Result; -pub(crate) struct HostFunction { - pub(crate) f: fn(&mut Runtime, &[sandbox::TypedValue]) - -> Result, - func_type: FunctionType, +pub(crate) trait FunctionImplProvider { + fn impls)>(f: &mut F); } -impl HostFunction { - /// Create a new instance of a host function. - pub fn new( - func_type: FunctionType, - f: fn(&mut Runtime, &[sandbox::TypedValue]) - -> Result, - ) -> Self { - HostFunction { func_type, f } - } - /// Returns a function pointer of this host function. - pub fn raw_fn_ptr( - &self, - ) -> fn(&mut Runtime, &[sandbox::TypedValue]) - -> Result { - self.f - } - - /// Check if the this function could be invoked with the given function signature. - pub fn func_type_matches(&self, func_type: &FunctionType) -> bool { - &self.func_type == func_type - } +/// This trait can be used to check whether the host environment can satisfy +/// a requested function import. +pub trait ImportSatisfyCheck { + /// Returns `true` if the host environment contains a function with + /// the specified name and its type matches to the given type, or `false` + /// otherwise. + fn can_satisfy(name: &[u8], func_type: &FunctionType) -> bool; } diff --git a/srml/contract/src/wasm/mod.rs b/srml/contract/src/wasm/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..04428280d05bb3f3f4af9068b79d52190f5aa396 --- /dev/null +++ b/srml/contract/src/wasm/mod.rs @@ -0,0 +1,1169 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This module provides a means for executing contracts +//! represented in wasm. + +use crate::{CodeHash, Schedule, Trait}; +use crate::wasm::env_def::FunctionImplProvider; +use crate::exec::{Ext, EmptyOutputBuf, VmExecResult}; +use crate::gas::GasMeter; + +use rstd::prelude::*; +use parity_codec::{Encode, Decode}; +use sandbox; + +#[macro_use] +mod env_def; +mod code_cache; +mod prepare; +mod runtime; + +use self::runtime::{to_execution_result, Runtime}; +use self::code_cache::load as load_code; + +pub use self::code_cache::save as save_code; + +/// A prepared wasm module ready for execution. +#[derive(Clone, Encode, Decode)] +pub struct PrefabWasmModule { + /// Version of the schedule with which the code was instrumented. + #[codec(compact)] + schedule_version: u32, + #[codec(compact)] + initial: u32, + #[codec(compact)] + maximum: u32, + /// This field is reserved for future evolution of format. + /// + /// Basically, for now this field will be serialized as `None`. In the future + /// we would be able to extend this structure with. + _reserved: Option<()>, + /// Code instrumented with the latest schedule. + code: Vec, +} + +/// Wasm executable loaded by `WasmLoader` and executed by `WasmVm`. +pub struct WasmExecutable { + entrypoint_name: &'static [u8], + prefab_module: PrefabWasmModule, +} + +/// Loader which fetches `WasmExecutable` from the code cache. +pub struct WasmLoader<'a, T: Trait> { + schedule: &'a Schedule, +} + +impl<'a, T: Trait> WasmLoader<'a, T> { + pub fn new(schedule: &'a Schedule) -> Self { + WasmLoader { schedule } + } +} + +impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a, T> { + type Executable = WasmExecutable; + + fn load_init(&self, code_hash: &CodeHash) -> Result { + let prefab_module = load_code::(code_hash, self.schedule)?; + Ok(WasmExecutable { + entrypoint_name: b"deploy", + prefab_module, + }) + } + fn load_main(&self, code_hash: &CodeHash) -> Result { + let prefab_module = load_code::(code_hash, self.schedule)?; + Ok(WasmExecutable { + entrypoint_name: b"call", + prefab_module, + }) + } +} + +/// Implementation of `Vm` that takes `WasmExecutable` and executes it. +pub struct WasmVm<'a, T: Trait> { + schedule: &'a Schedule, +} + +impl<'a, T: Trait> WasmVm<'a, T> { + pub fn new(schedule: &'a Schedule) -> Self { + WasmVm { schedule } + } +} + +impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a, T> { + type Executable = WasmExecutable; + + fn execute>( + &self, + exec: &WasmExecutable, + ext: &mut E, + input_data: &[u8], + empty_output_buf: EmptyOutputBuf, + gas_meter: &mut GasMeter, + ) -> VmExecResult { + let memory = + sandbox::Memory::new(exec.prefab_module.initial, Some(exec.prefab_module.maximum)) + .unwrap_or_else(|_| { + // unlike `.expect`, explicit panic preserves the source location. + // Needed as we can't use `RUST_BACKTRACE` in here. + panic!( + "exec.prefab_module.initial can't be greater than exec.prefab_module.maximum; + thus Memory::new must not fail; + qed" + ) + }); + + let mut imports = sandbox::EnvironmentDefinitionBuilder::new(); + imports.add_memory("env", "memory", memory.clone()); + runtime::Env::impls(&mut |name, func_ptr| { + imports.add_host_func("env", name, func_ptr); + }); + + let mut runtime = Runtime::new( + ext, + input_data, + empty_output_buf, + &self.schedule, + memory, + gas_meter, + ); + + // Instantiate the instance from the instrumented module code. + match sandbox::Instance::new(&exec.prefab_module.code, &imports, &mut runtime) { + // No errors or traps were generated on instantiation! That + // means we can now invoke the contract entrypoint. + Ok(mut instance) => { + let err = instance + .invoke(exec.entrypoint_name, &[], &mut runtime) + .err(); + to_execution_result(runtime, err) + } + // `start` function trapped. Treat it in the same manner as an execution error. + Err(err @ sandbox::Error::Execution) => to_execution_result(runtime, Some(err)), + Err(_err @ sandbox::Error::Module) => { + // `Error::Module` is returned only if instantiation or linking failed (i.e. + // wasm bianry tried to import a function that is not provided by the host). + // This shouldn't happen because validation proccess ought to reject such binaries. + // + // Because panics are really undesirable in the runtime code, we treat this as + // a trap for now. Eventually, we might want to revisit this. + return VmExecResult::Trap("validation error"); + } + // Other instantiation errors. + // Return without executing anything. + Err(_) => return VmExecResult::Trap("during start function"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use substrate_primitives::H256; + use crate::exec::{CallReceipt, Ext, InstantiateReceipt, EmptyOutputBuf}; + use crate::gas::GasMeter; + use crate::tests::{Test, Call}; + use wabt; + use crate::wasm::prepare::prepare_contract; + use crate::CodeHash; + + #[derive(Debug, PartialEq, Eq)] + struct DispatchEntry(Call); + #[derive(Debug, PartialEq, Eq)] + struct CreateEntry { + code_hash: H256, + endowment: u64, + data: Vec, + gas_left: u64, + } + #[derive(Debug, PartialEq, Eq)] + struct TransferEntry { + to: u64, + value: u64, + data: Vec, + gas_left: u64, + } + #[derive(Default)] + pub struct MockExt { + storage: HashMap, Vec>, + creates: Vec, + transfers: Vec, + dispatches: Vec, + next_account_id: u64, + random_seed: H256, + } + impl Ext for MockExt { + type T = Test; + + fn get_storage(&self, key: &[u8]) -> Option> { + self.storage.get(key).cloned() + } + fn set_storage(&mut self, key: &[u8], value: Option>) { + *self.storage.entry(key.to_vec()).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); + } + fn instantiate( + &mut self, + code_hash: &CodeHash, + endowment: u64, + gas_meter: &mut GasMeter, + data: &[u8], + ) -> Result, &'static str> { + self.creates.push(CreateEntry { + code_hash: code_hash.clone(), + endowment, + data: data.to_vec(), + gas_left: gas_meter.gas_left(), + }); + let address = self.next_account_id; + self.next_account_id += 1; + + Ok(InstantiateReceipt { address }) + } + fn call( + &mut self, + to: &u64, + value: u64, + gas_meter: &mut GasMeter, + data: &[u8], + _output_data: EmptyOutputBuf, + ) -> Result { + self.transfers.push(TransferEntry { + to: *to, + value, + data: data.to_vec(), + gas_left: gas_meter.gas_left(), + }); + // Assume for now that it was just a plain transfer. + // TODO: Add tests for different call outcomes. + Ok(CallReceipt { + output_data: Vec::new(), + }) + } + fn note_dispatch_call(&mut self, call: Call) { + self.dispatches.push(DispatchEntry(call)); + } + fn caller(&self) -> &u64 { + &42 + } + fn address(&self) -> &u64 { + &69 + } + fn balance(&self) -> u64 { + 228 + } + fn value_transferred(&self) -> u64 { + 1337 + } + + fn now(&self) -> &u64 { + &1111 + } + + fn random_seed(&self) -> &H256{ + &self.random_seed + } + } + + fn execute( + wat: &str, + input_data: &[u8], + output_data: &mut Vec, + ext: &mut E, + gas_meter: &mut GasMeter, + ) -> Result<(), &'static str> { + use crate::exec::Vm; + + let wasm = wabt::wat2wasm(wat).unwrap(); + let schedule = crate::Schedule::::default(); + let prefab_module = + prepare_contract::(&wasm, &schedule).unwrap(); + + let exec = WasmExecutable { + // Use a "call" convention. + entrypoint_name: b"call", + prefab_module, + }; + + let cfg = Default::default(); + let vm = WasmVm::new(&cfg); + + *output_data = vm + .execute(&exec, ext, input_data, EmptyOutputBuf::new(), gas_meter) + .into_result()?; + + Ok(()) + } + + const CODE_TRANSFER: &str = r#" +(module + ;; ext_call( + ;; callee_ptr: u32, + ;; callee_len: u32, + ;; gas: u64, + ;; value_ptr: u32, + ;; value_len: u32, + ;; input_data_ptr: u32, + ;; input_data_len: u32 + ;;) -> u32 + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (drop + (call $ext_call + (i32.const 4) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 20) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer + ) + ) + ) + (func (export "deploy")) + + ;; Destination AccountId to transfer the funds. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\09\00\00\00\00\00\00\00") + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 12) "\06\00\00\00\00\00\00\00") + + (data (i32.const 20) "\01\02\03\04") +) +"#; + + #[test] + fn contract_transfer() { + let mut mock_ext = MockExt::default(); + execute( + CODE_TRANSFER, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!( + &mock_ext.transfers, + &[TransferEntry { + to: 9, + value: 6, + data: vec![1, 2, 3, 4], + gas_left: 49970, + }] + ); + } + + const CODE_CREATE: &str = r#" +(module + ;; ext_create( + ;; code_ptr: u32, + ;; code_len: u32, + ;; gas: u64, + ;; value_ptr: u32, + ;; value_len: u32, + ;; input_data_ptr: u32, + ;; input_data_len: u32, + ;; ) -> u32 + (import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (drop + (call $ext_create + (i32.const 16) ;; Pointer to `code_hash` + (i32.const 32) ;; Length of `code_hash` + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 4) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 12) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer + ) + ) + ) + (func (export "deploy")) + + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\03\00\00\00\00\00\00\00") + ;; Input data to pass to the contract being created. + (data (i32.const 12) "\01\02\03\04") + ;; Hash of code. + (data (i32.const 16) "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11") +) +"#; + + #[test] + fn contract_create() { + let mut mock_ext = MockExt::default(); + execute( + CODE_CREATE, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!( + &mock_ext.creates, + &[CreateEntry { + code_hash: [0x11; 32].into(), + endowment: 3, + data: vec![1, 2, 3, 4], + gas_left: 49946, + }] + ); + } + + const CODE_TRANSFER_LIMITED_GAS: &str = r#" +(module + ;; ext_call( + ;; callee_ptr: u32, + ;; callee_len: u32, + ;; gas: u64, + ;; value_ptr: u32, + ;; value_len: u32, + ;; input_data_ptr: u32, + ;; input_data_len: u32 + ;;) -> u32 + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (drop + (call $ext_call + (i32.const 4) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 228) ;; How much gas to devote for the execution. + (i32.const 12) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 20) ;; Pointer to input data buffer address + (i32.const 4) ;; Length of input data buffer + ) + ) + ) + (func (export "deploy")) + + ;; Destination AccountId to transfer the funds. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 4) "\09\00\00\00\00\00\00\00") + ;; Amount of value to transfer. + ;; Represented by u64 (8 bytes long) in little endian. + (data (i32.const 12) "\06\00\00\00\00\00\00\00") + + (data (i32.const 20) "\01\02\03\04") +) +"#; + + #[test] + fn contract_call_limited_gas() { + let mut mock_ext = MockExt::default(); + execute( + &CODE_TRANSFER_LIMITED_GAS, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!( + &mock_ext.transfers, + &[TransferEntry { + to: 9, + value: 6, + data: vec![1, 2, 3, 4], + gas_left: 228, + }] + ); + } + + const CODE_GET_STORAGE: &str = r#" +(module + (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (local $buf_size i32) + + + ;; Load a storage value into the scratch buf. + (call $assert + (i32.eq + (call $ext_get_storage + (i32.const 4) ;; The pointer to the storage key to fetch + ) + + ;; Return value 0 means that the value is found and there were + ;; no errors. + (i32.const 0) + ) + ) + + ;; Find out the size of the scratch buffer + (set_local $buf_size + (call $ext_scratch_size) + ) + + ;; Copy scratch buffer into this contract memory. + (call $ext_scratch_copy + (i32.const 36) ;; The pointer where to store the scratch buffer contents, + ;; 36 = 4 + 32 + (i32.const 0) ;; Offset from the start of the scratch buffer. + (get_local ;; Count of bytes to copy. + $buf_size + ) + ) + + ;; Return the contents of the buffer + (call $ext_return + (i32.const 36) + (get_local $buf_size) + ) + + ;; env:ext_return doesn't return, so this is effectively unreachable. + (unreachable) + ) + + (func (export "deploy")) + + (data (i32.const 4) "\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11\11") +) +"#; + + #[test] + fn get_storage_puts_data_into_scratch_buf() { + let mut mock_ext = MockExt::default(); + mock_ext + .storage + .insert([0x11; 32].to_vec(), [0x22; 32].to_vec()); + + let mut return_buf = Vec::new(); + execute( + CODE_GET_STORAGE, + &[], + &mut return_buf, + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!(return_buf, [0x22; 32].to_vec()); + } + + /// calls `ext_caller`, loads the address from the scratch buffer and + /// compares it with the constant 42. + const CODE_CALLER: &str = r#" +(module + (import "env" "ext_caller" (func $ext_caller)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; fill the scratch buffer with the caller. + (call $ext_caller) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 42. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 42) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + #[test] + fn caller() { + let mut mock_ext = MockExt::default(); + execute( + CODE_CALLER, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + } + + /// calls `ext_address`, loads the address from the scratch buffer and + /// compares it with the constant 69. + const CODE_ADDRESS: &str = r#" +(module + (import "env" "ext_address" (func $ext_address)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; fill the scratch buffer with the self address. + (call $ext_address) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 69. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 69) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + #[test] + fn address() { + let mut mock_ext = MockExt::default(); + execute( + CODE_ADDRESS, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + } + + const CODE_BALANCE: &str = r#" +(module + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the balance in the scratch buffer + (call $ext_balance) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 228. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 228) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn balance() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1); + execute( + CODE_BALANCE, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + + const CODE_GAS_PRICE: &str = r#" +(module + (import "env" "ext_gas_price" (func $ext_gas_price)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the gas price in the scratch buffer + (call $ext_gas_price) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1312. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1312) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn gas_price() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1312); + execute( + CODE_GAS_PRICE, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + + const CODE_GAS_LEFT: &str = r#" +(module + (import "env" "ext_gas_left" (func $ext_gas_left)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the gas left in the scratch buffer + (call $ext_gas_left) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + (call $ext_return + (i32.const 8) + (i32.const 8) + ) + + (unreachable) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn gas_left() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1312); + execute( + CODE_GAS_LEFT, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + + const CODE_VALUE_TRANSFERRED: &str = r#" +(module + (import "env" "ext_value_transferred" (func $ext_value_transferred)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the value transferred in the scratch buffer + (call $ext_value_transferred) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1337. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1337) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn value_transferred() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1); + execute( + CODE_VALUE_TRANSFERRED, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + + const CODE_DISPATCH_CALL: &str = r#" +(module + (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_dispatch_call + (i32.const 8) ;; Pointer to the start of encoded call buffer + (i32.const 13) ;; Length of the buffer + ) + ) + (func (export "deploy")) + + (data (i32.const 8) "\00\01\2A\00\00\00\00\00\00\00\E5\14\00") +) +"#; + + #[test] + fn dispatch_call() { + // This test can fail due to the encoding changes. In case it becomes too annoying + // let's rewrite so as we use this module controlled call or we serialize it in runtime. + + let mut mock_ext = MockExt::default(); + execute( + CODE_DISPATCH_CALL, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!( + &mock_ext.dispatches, + &[DispatchEntry( + Call::Balances(balances::Call::set_balance(42, 1337, 0)), + )] + ); + } + + const CODE_RETURN_FROM_START_FN: &str = r#" +(module + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (start $start) + (func $start + (call $ext_return + (i32.const 8) + (i32.const 4) + ) + (unreachable) + ) + + (func (export "call") + (unreachable) + ) + (func (export "deploy")) + + (data (i32.const 8) "\01\02\03\04") +) +"#; + + #[test] + fn return_from_start_fn() { + let mut mock_ext = MockExt::default(); + let mut output_data = Vec::new(); + execute( + CODE_RETURN_FROM_START_FN, + &[], + &mut output_data, + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ) + .unwrap(); + + assert_eq!(output_data, vec![1, 2, 3, 4]); + } + + const CODE_TIMESTAMP_NOW: &str = r#" +(module + (import "env" "ext_now" (func $ext_now)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the block timestamp in the scratch buffer + (call $ext_now) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1111. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1111) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn now() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1); + execute( + CODE_TIMESTAMP_NOW, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + + const CODE_RANDOM_SEED: &str = r#" +(module + (import "env" "ext_random_seed" (func $ext_random_seed)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the block random seed in the scratch buffer + (call $ext_random_seed) + + ;; assert $ext_scratch_size == 32 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 32) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 32) ;; Count of bytes to copy. + ) + + ;; assert the contents of the buffer in 4 x i64 parts matches 1,2,3,4. + (call $assert (i64.eq (i64.load (i32.const 8)) (i64.const 1))) + (call $assert (i64.eq (i64.load (i32.const 16)) (i64.const 2))) + (call $assert (i64.eq (i64.load (i32.const 24)) (i64.const 3))) + (call $assert (i64.eq (i64.load (i32.const 32)) (i64.const 4))) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn random_seed() { + let mut mock_ext = MockExt::default(); + let seed: [u8; 32] = [ + 1,0,0,0,0,0,0,0, + 2,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0, + 4,0,0,0,0,0,0,0, + ]; + mock_ext.random_seed = H256::from_slice(&seed); + let mut gas_meter = GasMeter::with_limit(50_000, 1); + execute( + CODE_RANDOM_SEED, + &[], + &mut Vec::new(), + &mut mock_ext, + &mut gas_meter, + ) + .unwrap(); + } + +} diff --git a/srml/contract/src/wasm/prepare.rs b/srml/contract/src/wasm/prepare.rs new file mode 100644 index 0000000000000000000000000000000000000000..52f1580aa9fecb4c71c13a37d017f20e71e46f05 --- /dev/null +++ b/srml/contract/src/wasm/prepare.rs @@ -0,0 +1,586 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This module takes care of loading, checking and preprocessing of a +//! wasm module before execution. It also extracts some essential information +//! from a module. + +use crate::wasm::env_def::ImportSatisfyCheck; +use crate::wasm::PrefabWasmModule; +use crate::{Schedule, Trait}; + +use parity_wasm::elements::{self, Internal, External, MemoryType, Type}; +use pwasm_utils; +use pwasm_utils::rules; +use rstd::prelude::*; +use runtime_primitives::traits::As; + +struct ContractModule<'a, Gas: 'a> { + // An `Option` is used here for loaning (`take()`-ing) the module. + // Invariant: Can't be `None` (i.e. on enter and on exit from the function + // the value *must* be `Some`). + module: Option, + schedule: &'a Schedule, +} + +impl<'a, Gas: 'a + As + Clone> ContractModule<'a, Gas> { + fn new( + original_code: &[u8], + schedule: &'a Schedule, + ) -> Result, &'static str> { + let module = + elements::deserialize_buffer(original_code).map_err(|_| "can't decode wasm code")?; + Ok(ContractModule { + module: Some(module), + schedule, + }) + } + + /// Ensures that module doesn't declare internal memories. + /// + /// In this runtime we only allow wasm module to import memory from the environment. + /// Memory section contains declarations of internal linear memories, so if we find one + /// we reject such a module. + fn ensure_no_internal_memory(&self) -> Result<(), &'static str> { + let module = self + .module + .as_ref() + .expect("On entry to the function `module` can't be None; qed"); + if module + .memory_section() + .map_or(false, |ms| ms.entries().len() > 0) + { + return Err("module declares internal memory"); + } + Ok(()) + } + + fn inject_gas_metering(&mut self) -> Result<(), &'static str> { + let gas_rules = + rules::Set::new( + self.schedule.regular_op_cost.clone().as_(), + Default::default(), + ) + .with_grow_cost(self.schedule.grow_mem_cost.clone().as_()) + .with_forbidden_floats(); + + let module = self + .module + .take() + .expect("On entry to the function `module` can't be `None`; qed"); + + let contract_module = pwasm_utils::inject_gas_counter(module, &gas_rules) + .map_err(|_| "gas instrumentation failed")?; + + self.module = Some(contract_module); + Ok(()) + } + + fn inject_stack_height_metering(&mut self) -> Result<(), &'static str> { + let module = self + .module + .take() + .expect("On entry to the function `module` can't be `None`; qed"); + + let contract_module = + pwasm_utils::stack_height::inject_limiter(module, self.schedule.max_stack_height) + .map_err(|_| "stack height instrumentation failed")?; + + self.module = Some(contract_module); + Ok(()) + } + + /// Check that the module has required exported functions. For now + /// these are just entrypoints: + /// + /// - 'call' + /// - 'deploy' + fn scan_exports(&self) -> Result<(), &'static str> { + let mut deploy_found = false; + let mut call_found = false; + + let module = self + .module + .as_ref() + .expect("On entry to the function `module` can't be `None`; qed"); + + let types = module.type_section().map(|ts| ts.types()).unwrap_or(&[]); + let export_entries = module + .export_section() + .map(|is| is.entries()) + .unwrap_or(&[]); + let func_entries = module + .function_section() + .map(|fs| fs.entries()) + .unwrap_or(&[]); + + // Function index space consists of imported function following by + // declared functions. Calculate the total number of imported functions so + // we can use it to convert indexes from function space to declared function space. + let fn_space_offset = module + .import_section() + .map(|is| is.entries()) + .unwrap_or(&[]) + .iter() + .filter(|entry| { + match *entry.external() { + External::Function(_) => true, + _ => false, + } + }) + .count(); + + for export in export_entries { + match export.field() { + "call" => call_found = true, + "deploy" => deploy_found = true, + _ => continue, + } + + // Then check the export kind. "call" and "deploy" are + // functions. + let fn_idx = match export.internal() { + Internal::Function(ref fn_idx) => *fn_idx, + _ => return Err("expected a function"), + }; + + // convert index from function index space to declared index space. + let fn_idx = match fn_idx.checked_sub(fn_space_offset as u32) { + Some(fn_idx) => fn_idx, + None => { + // Underflow here means fn_idx points to imported function which we don't allow! + return Err("entry point points to an imported function"); + } + }; + + // Then check the signature. + // Both "call" and "deploy" has a () -> () function type. + let func_ty_idx = func_entries.get(fn_idx as usize) + .ok_or_else(|| "export refers to non-existent function")? + .type_ref(); + let Type::Function(ref func_ty) = types + .get(func_ty_idx as usize) + .ok_or_else(|| "function has a non-existent type")?; + if !(func_ty.params().is_empty() && func_ty.return_type().is_none()) { + return Err("entry point has wrong signature"); + } + } + + if !deploy_found { + return Err("deploy function isn't exported"); + } + if !call_found { + return Err("call function isn't exported"); + } + + Ok(()) + } + + /// Scan an import section if any. + /// + /// This accomplishes two tasks: + /// + /// - checks any imported function against defined host functions set, incl. + /// their signatures. + /// - if there is a memory import, returns it's descriptor + fn scan_imports(&self) -> Result, &'static str> { + let module = self + .module + .as_ref() + .expect("On entry to the function `module` can't be `None`; qed"); + + let types = module.type_section().map(|ts| ts.types()).unwrap_or(&[]); + let import_entries = module + .import_section() + .map(|is| is.entries()) + .unwrap_or(&[]); + + let mut imported_mem_type = None; + + for import in import_entries { + if import.module() != "env" { + // This import tries to import something from non-"env" module, + // but all imports are located in "env" at the moment. + return Err("module has imports from a non-'env' namespace"); + } + + let type_idx = match import.external() { + &External::Function(ref type_idx) => type_idx, + &External::Memory(ref memory_type) => { + imported_mem_type = Some(memory_type); + continue; + } + _ => continue, + }; + + let Type::Function(ref func_ty) = types + .get(*type_idx as usize) + .ok_or_else(|| "validation: import entry points to a non-existent type")?; + + // We disallow importing `gas` function here since it is treated as implementation detail. + if import.field().as_bytes() == b"gas" + || !C::can_satisfy(import.field().as_bytes(), func_ty) + { + return Err("module imports a non-existent function"); + } + } + Ok(imported_mem_type) + } + + fn into_wasm_code(mut self) -> Result, &'static str> { + elements::serialize( + self.module + .take() + .expect("On entry to the function `module` can't be `None`; qed"), + ) + .map_err(|_| "error serializing instrumented module") + } +} + +/// Loads the given module given in `original_code`, performs some checks on it and +/// does some preprocessing. +/// +/// The checks are: +/// +/// - module doesn't define an internal memory instance, +/// - imported memory (if any) doesn't reserve more memory than permitted by the `schedule`, +/// - all imported functions from the external environment matches defined by `env` module, +/// +/// The preprocessing includes injecting code for gas metering and metering the height of stack. +pub fn prepare_contract( + original_code: &[u8], + schedule: &Schedule, +) -> Result { + let mut contract_module = ContractModule::new(original_code, schedule)?; + contract_module.scan_exports()?; + contract_module.ensure_no_internal_memory()?; + + struct MemoryDefinition { + initial: u32, + maximum: u32, + } + + let memory_def = if let Some(memory_type) = contract_module.scan_imports::()? { + // Inspect the module to extract the initial and maximum page count. + let limits = memory_type.limits(); + match (limits.initial(), limits.maximum()) { + (initial, Some(maximum)) if initial > maximum => { + return Err( + "Requested initial number of pages should not exceed the requested maximum", + ); + } + (_, Some(maximum)) if maximum > schedule.max_memory_pages => { + return Err("Maximum number of pages should not exceed the configured maximum."); + } + (initial, Some(maximum)) => MemoryDefinition { initial, maximum }, + (_, None) => { + // Maximum number of pages should be always declared. + // This isn't a hard requirement and can be treated as a maxiumum set + // to configured maximum. + return Err("Maximum number of pages should be always declared."); + } + } + } else { + // If none memory imported then just crate an empty placeholder. + // Any access to it will lead to out of bounds trap. + MemoryDefinition { + initial: 0, + maximum: 0, + } + }; + + contract_module.inject_gas_metering()?; + contract_module.inject_stack_height_metering()?; + + Ok(PrefabWasmModule { + schedule_version: schedule.version, + initial: memory_def.initial, + maximum: memory_def.maximum, + _reserved: None, + code: contract_module.into_wasm_code()?, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::Test; + use crate::exec::Ext; + use std::fmt; + use wabt; + use assert_matches::assert_matches; + + impl fmt::Debug for PrefabWasmModule { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "PreparedContract {{ .. }}") + } + } + + // Define test environment for tests. We need ImportSatisfyCheck + // implementation from it. So actual implementations doesn't matter. + define_env!(TestEnv, , + panic(_ctx) => { unreachable!(); }, + + // gas is an implementation defined function and a contract can't import it. + gas(_ctx, _amount: u32) => { unreachable!(); }, + + nop(_ctx, _unused: u64) => { unreachable!(); }, + ); + + macro_rules! prepare_test { + ($name:ident, $wat:expr, $($expected:tt)*) => { + #[test] + fn $name() { + let wasm = wabt::Wat2Wasm::new().validate(false).convert($wat).unwrap(); + let schedule = Schedule::::default(); + let r = prepare_contract::(wasm.as_ref(), &schedule); + assert_matches!(r, $($expected)*); + } + }; + } + + prepare_test!(no_floats, + r#" + (module + (func (export "call") + (drop + (f32.add + (f32.const 0) + (f32.const 1) + ) + ) + ) + (func (export "deploy")) + )"#, + Err("gas instrumentation failed") + ); + + mod memories { + use super::*; + + // Tests below assumes that maximum page number is configured to a certain number. + #[test] + fn assume_memory_size() { + assert_eq!(Schedule::::default().max_memory_pages, 16); + } + + prepare_test!(memory_with_one_page, + r#" + (module + (import "env" "memory" (memory 1 1)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Ok(_) + ); + + prepare_test!(internal_memory_declaration, + r#" + (module + (memory 1 1) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("module declares internal memory") + ); + + prepare_test!(no_memory_import, + r#" + (module + ;; no memory imported + + (func (export "call")) + (func (export "deploy")) + )"#, + Ok(_) + ); + + prepare_test!(initial_exceeds_maximum, + r#" + (module + (import "env" "memory" (memory 16 1)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("Requested initial number of pages should not exceed the requested maximum") + ); + + prepare_test!(no_maximum, + r#" + (module + (import "env" "memory" (memory 1)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("Maximum number of pages should be always declared.") + ); + + prepare_test!(requested_maximum_exceeds_configured_maximum, + r#" + (module + (import "env" "memory" (memory 1 17)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("Maximum number of pages should not exceed the configured maximum.") + ); + } + + mod imports { + use super::*; + + prepare_test!(can_import_legit_function, + r#" + (module + (import "env" "nop" (func (param i64))) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Ok(_) + ); + + // even though gas is defined the contract can't import it since + // it is an implementation defined. + prepare_test!(can_not_import_gas_function, + r#" + (module + (import "env" "gas" (func (param i32))) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("module imports a non-existent function") + ); + + // nothing can be imported from non-"env" module for now. + prepare_test!(non_env_import, + r#" + (module + (import "another_module" "memory" (memory 1 1)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("module has imports from a non-'env' namespace") + ); + + // wrong signature + prepare_test!(wrong_signature, + r#" + (module + (import "env" "gas" (func (param i64))) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("module imports a non-existent function") + ); + + prepare_test!(unknown_func_name, + r#" + (module + (import "env" "unknown_func" (func)) + + (func (export "call")) + (func (export "deploy")) + ) + "#, + Err("module imports a non-existent function") + ); + } + + mod entrypoints { + use super::*; + + prepare_test!(it_works, + r#" + (module + (func (export "call")) + (func (export "deploy")) + ) + "#, + Ok(_) + ); + + prepare_test!(omit_deploy, + r#" + (module + (func (export "call")) + ) + "#, + Err("deploy function isn't exported") + ); + + prepare_test!(omit_call, + r#" + (module + (func (export "deploy")) + ) + "#, + Err("call function isn't exported") + ); + + // Try to use imported function as an entry point. + prepare_test!(try_sneak_export_as_entrypoint, + r#" + (module + (import "env" "panic" (func)) + + (func (export "deploy")) + + (export "call" (func 0)) + ) + "#, + Err("entry point points to an imported function") + ); + + // Try to use imported function as an entry point. + prepare_test!(try_sneak_export_as_global, + r#" + (module + (func (export "deploy")) + (global (export "call") i32 (i32.const 0)) + ) + "#, + Err("expected a function") + ); + + prepare_test!(wrong_signature, + r#" + (module + (func (export "deploy")) + (func (export "call") (param i32)) + ) + "#, + Err("entry point has wrong signature") + ); + } +} diff --git a/srml/contract/src/vm/runtime.rs b/srml/contract/src/wasm/runtime.rs similarity index 61% rename from srml/contract/src/vm/runtime.rs rename to srml/contract/src/wasm/runtime.rs index d32808635957bf306d1c97de8faafa14995598b2..83f14cdfd7a83531db805cc3e499cbeefc004923 100644 --- a/srml/contract/src/vm/runtime.rs +++ b/srml/contract/src/wasm/runtime.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,16 +16,15 @@ //! Environment definition of the wasm smart-contract runtime. -use super::{BalanceOf, Schedule, CreateReceipt, Error, Ext}; -use rstd::prelude::*; -use codec::{Decode, Encode}; -use gas::{GasMeter, GasMeterResult}; -use runtime_primitives::traits::{As, CheckedMul}; +use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee}; +use crate::exec::{Ext, BalanceOf, VmExecResult, OutputBuf, EmptyOutputBuf, CallReceipt, InstantiateReceipt}; +use crate::gas::{GasMeter, Token, GasMeterResult, approx_gas_for_balance}; use sandbox; use system; -use Trait; - -type GasOf = <::T as Trait>::Gas; +use rstd::prelude::*; +use rstd::mem; +use parity_codec::{Decode, Encode}; +use runtime_primitives::traits::{As, CheckedMul, Bounded}; /// Enumerates all possible *special* trap conditions. /// @@ -33,13 +32,16 @@ type GasOf = <::T as Trait>::Gas; /// to just terminate quickly in some cases. enum SpecialTrap { /// Signals that trap was generated in response to call `ext_return` host function. - Return, + Return(OutputBuf), } +/// Can only be used for one call. pub(crate) struct Runtime<'a, 'data, E: Ext + 'a> { ext: &'a mut E, input_data: &'data [u8], - output_data: &'data mut Vec, + // A VM can return a result only once and only by value. So + // we wrap output buffer to make it possible to take the buffer out. + empty_output_buf: Option, scratch_buf: Vec, schedule: &'a Schedule<::Gas>, memory: sandbox::Memory, @@ -50,7 +52,7 @@ impl<'a, 'data, E: Ext + 'a> Runtime<'a, 'data, E> { pub(crate) fn new( ext: &'a mut E, input_data: &'data [u8], - output_data: &'data mut Vec, + empty_output_buf: EmptyOutputBuf, schedule: &'a Schedule<::Gas>, memory: sandbox::Memory, gas_meter: &'a mut GasMeter, @@ -58,7 +60,7 @@ impl<'a, 'data, E: Ext + 'a> Runtime<'a, 'data, E> { Runtime { ext, input_data, - output_data, + empty_output_buf: Some(empty_output_buf), scratch_buf: Vec::new(), schedule, memory, @@ -75,30 +77,71 @@ impl<'a, 'data, E: Ext + 'a> Runtime<'a, 'data, E> { pub(crate) fn to_execution_result( runtime: Runtime, sandbox_err: Option, -) -> Result<(), Error> { +) -> VmExecResult { // Check the exact type of the error. It could be plain trap or // special runtime trap the we must recognize. match (sandbox_err, runtime.special_trap) { // No traps were generated. Proceed normally. - (None, None) => Ok(()), + (None, None) => VmExecResult::Ok, // Special case. The trap was the result of the execution `return` host function. - (Some(sandbox::Error::Execution), Some(SpecialTrap::Return)) => Ok(()), + (Some(sandbox::Error::Execution), Some(SpecialTrap::Return(buf))) => VmExecResult::Returned(buf), // Any other kind of a trap should result in a failure. - (Some(_), _) => Err(Error::Invoke), + (Some(_), _) => VmExecResult::Trap("during execution"), // Any other case (such as special trap flag without actual trap) signifies // a logic error. _ => unreachable!(), } } -/// Charge the specified amount of gas. +#[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub enum RuntimeToken { + /// Explicit call to the `gas` function. Charge the gas meter + /// with the value provided. + Explicit(u32), + /// The given number of bytes is read from the sandbox memory. + ReadMemory(u32), + /// The given number of bytes is written to the sandbox memory. + WriteMemory(u32), + /// The given number of bytes is read from the sandbox memory and + /// is returned as the return data buffer of the call. + ReturnData(u32), + /// Dispatch fee calculated by `T::ComputeDispatchFee`. + ComputedDispatchFee(Gas), +} + +impl Token for RuntimeToken { + type Metadata = Schedule; + + fn calculate_amount(&self, metadata: &Schedule) -> T::Gas { + use self::RuntimeToken::*; + let value = match *self { + Explicit(amount) => Some(>::sa(amount)), + ReadMemory(byte_count) => metadata + .sandbox_data_read_cost + .checked_mul(&>::sa(byte_count)), + WriteMemory(byte_count) => metadata + .sandbox_data_write_cost + .checked_mul(&>::sa(byte_count)), + ReturnData(byte_count) => metadata + .return_data_per_byte_cost + .checked_mul(&>::sa(byte_count)), + ComputedDispatchFee(gas) => Some(gas), + }; + + value.unwrap_or_else(|| Bounded::max_value()) + } +} + +/// Charge the gas meter with the specified token. /// -/// Returns `Err` if there is not enough gas. -fn charge_gas( +/// Returns `Err(HostError)` if there is not enough gas. +fn charge_gas>( gas_meter: &mut GasMeter, - amount: T::Gas, + metadata: &Tok::Metadata, + token: Tok, ) -> Result<(), sandbox::HostError> { - match gas_meter.charge(amount) { + match gas_meter.charge(metadata, token) { GasMeterResult::Proceed => Ok(()), GasMeterResult::OutOfGas => Err(sandbox::HostError), } @@ -117,10 +160,7 @@ fn read_sandbox_memory( ptr: u32, len: u32, ) -> Result, sandbox::HostError> { - let price = (ctx.schedule.sandbox_data_read_cost) - .checked_mul(& as As>::sa(len)) - .ok_or(sandbox::HostError)?; - charge_gas(ctx.gas_meter, price)?; + charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(len))?; let mut buf = Vec::new(); buf.resize(len as usize, 0); @@ -139,16 +179,13 @@ fn read_sandbox_memory( /// - out of gas /// - designated area is not within the bounds of the sandbox memory. fn write_sandbox_memory( - per_byte_cost: T::Gas, + schedule: &Schedule, gas_meter: &mut GasMeter, memory: &sandbox::Memory, ptr: u32, buf: &[u8], ) -> Result<(), sandbox::HostError> { - let price = per_byte_cost - .checked_mul(&>::sa(buf.len() as u32)) - .ok_or(sandbox::HostError)?; - charge_gas(gas_meter, price)?; + charge_gas(gas_meter, schedule, RuntimeToken::WriteMemory(buf.len() as u32))?; memory.set(ptr, buf)?; @@ -159,19 +196,18 @@ fn write_sandbox_memory( // * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD * // *********************************************************** -// TODO: ext_balance, ext_address, ext_callvalue, etc. - // Define a function `fn init_env() -> HostFunctionSet` that returns // a function set which can be imported by an executed contract. -define_env!(init_env, , +define_env!(Env, , // Account for used gas. Traps if gas used is greater than gas limit. // + // NOTE: This is a implementation defined call and is NOT a part of the public API. + // This call is supposed to be called only by instrumentation injected code. + // // - amount: How much gas is used. gas(ctx, amount: u32) => { - let amount = <::Gas as As>::sa(amount); - charge_gas(&mut ctx.gas_meter, amount)?; - + charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::Explicit(amount))?; Ok(()) }, @@ -251,8 +287,10 @@ define_env!(init_env, , }; let input_data = read_sandbox_memory(ctx, input_data_ptr, input_data_len)?; - // Clear the scratch buffer in any case. - ctx.scratch_buf.clear(); + // Grab the scratch buffer and put in its' place an empty one. + // We will use it for creating `EmptyOutputBuf` container for the call. + let scratch_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); + let empty_output_buf = EmptyOutputBuf::from_spare_vec(scratch_buf); let nested_gas_limit = if gas == 0 { ctx.gas_meter.gas_left() @@ -260,22 +298,33 @@ define_env!(init_env, , <::Gas as As>::sa(gas) }; let ext = &mut ctx.ext; - let scratch_buf = &mut ctx.scratch_buf; let call_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| { match nested_meter { - Some(nested_meter) => ext.call(&callee, value, nested_meter, &input_data, scratch_buf), + Some(nested_meter) => { + ext.call( + &callee, + value, + nested_meter, + &input_data, + empty_output_buf + ) + .map_err(|_| ()) + } // there is not enough gas to allocate for the nested call. None => Err(()), } }); match call_outcome { - Ok(()) => Ok(0), + Ok(CallReceipt { output_data }) => { + ctx.scratch_buf = output_data; + Ok(0) + }, Err(_) => Ok(1), } }, - // Create a contract with code returned by the specified initializer code. + // Instantiate a contract with code returned by the specified initializer code. // // This function creates an account and executes initializer code. After the execution, // the returned buffer is saved as the code of the created account. @@ -302,7 +351,10 @@ define_env!(init_env, , input_data_ptr: u32, input_data_len: u32 ) -> u32 => { - let init_code = read_sandbox_memory(ctx, init_code_ptr, init_code_len)?; + let code_hash = { + let code_hash_buf = read_sandbox_memory(ctx, init_code_ptr, init_code_len)?; + ::T>>::decode(&mut &code_hash_buf[..]).ok_or_else(|| sandbox::HostError)? + }; let value = { let value_buf = read_sandbox_memory(ctx, value_ptr, value_len)?; BalanceOf::<::T>::decode(&mut &value_buf[..]) @@ -319,15 +371,23 @@ define_env!(init_env, , <::Gas as As>::sa(gas) }; let ext = &mut ctx.ext; - let create_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| { + let instantiate_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| { match nested_meter { - Some(nested_meter) => ext.create(&init_code, value, nested_meter, &input_data), + Some(nested_meter) => { + ext.instantiate( + &code_hash, + value, + nested_meter, + &input_data + ) + .map_err(|_| ()) + } // there is not enough gas to allocate for the nested call. None => Err(()), } }); - match create_outcome { - Ok(CreateReceipt { address }) => { + match instantiate_outcome { + Ok(InstantiateReceipt { address }) => { // Write the address to the scratch buffer. address.encode_to(&mut ctx.scratch_buf); Ok(0) @@ -339,20 +399,34 @@ define_env!(init_env, , // Save a data buffer as a result of the execution, terminate the execution and return a // successful result to the caller. ext_return(ctx, data_ptr: u32, data_len: u32) => { - let data_len_in_gas = <::Gas as As>::sa(data_len as u64); - let price = (ctx.schedule.return_data_per_byte_cost) - .checked_mul(&data_len_in_gas) - .ok_or(sandbox::HostError)?; - - match ctx.gas_meter.charge(price) { + match ctx + .gas_meter + .charge( + ctx.schedule, + RuntimeToken::ReturnData(data_len) + ) + { GasMeterResult::Proceed => (), GasMeterResult::OutOfGas => return Err(sandbox::HostError), } - ctx.output_data.resize(data_len as usize, 0); - ctx.memory.get(data_ptr, &mut ctx.output_data)?; - - ctx.special_trap = Some(SpecialTrap::Return); + let empty_output_buf = ctx + .empty_output_buf + .take() + .expect( + "`empty_output_buf` is taken only here; + `ext_return` traps; + `Runtime` can only be used only for one execution; + qed" + ); + let output_buf = empty_output_buf.fill( + data_len as usize, + |slice_mut| { + // Read the memory at the specified pointer to the provided slice. + ctx.memory.get(data_ptr, slice_mut) + } + )?; + ctx.special_trap = Some(SpecialTrap::Return(output_buf)); // The trap mechanism is used to immediately terminate the execution. // This trap should be handled appropriately before returning the result @@ -370,6 +444,81 @@ define_env!(init_env, , Ok(()) }, + // Stores the address of the current contract into the scratch buffer. + ext_address(ctx) => { + ctx.scratch_buf = ctx.ext.address().encode(); + Ok(()) + }, + + // Stores the gas price for the current transaction into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. + ext_gas_price(ctx) => { + ctx.scratch_buf = ctx.gas_meter.gas_price().encode(); + Ok(()) + }, + + // Stores the amount of gas left into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. + ext_gas_left(ctx) => { + ctx.scratch_buf = ctx.gas_meter.gas_left().encode(); + Ok(()) + }, + + // Stores the balance of the current account into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. + ext_balance(ctx) => { + ctx.scratch_buf = ctx.ext.balance().encode(); + Ok(()) + }, + + // Stores the value transferred along with this call or as endowment into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. + ext_value_transferred(ctx) => { + ctx.scratch_buf = ctx.ext.value_transferred().encode(); + Ok(()) + }, + + // Load the latest block RNG seed into the scratch buffer + ext_random_seed(ctx) => { + ctx.scratch_buf = ctx.ext.random_seed().encode(); + Ok(()) + }, + + // Load the latest block timestamp into the scratch buffer + ext_now(ctx) => { + let now: u64 = As::as_(ctx.ext.now().clone()); + ctx.scratch_buf = now.encode(); + Ok(()) + }, + + // Decodes the given buffer as a `T::Call` and adds it to the list + // of to-be-dispatched calls. + // + // All calls made it to the top-level context will be dispatched before + // finishing the execution of the calling extrinsic. + ext_dispatch_call(ctx, call_ptr: u32, call_len: u32) => { + let call = { + let call_buf = read_sandbox_memory(ctx, call_ptr, call_len)?; + <<::T as Trait>::Call>::decode(&mut &call_buf[..]) + .ok_or_else(|| sandbox::HostError)? + }; + + // Charge gas for dispatching this call. + let fee = { + let balance_fee = <::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call); + approx_gas_for_balance::<::T>(ctx.gas_meter.gas_price(), balance_fee) + }; + charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::ComputedDispatchFee(fee))?; + + ctx.ext.note_dispatch_call(call); + + Ok(()) + }, + // Returns the size of the input buffer. ext_input_size(ctx) -> u32 => { Ok(ctx.input_data.len() as u32) @@ -392,7 +541,7 @@ define_env!(init_env, , // Finally, perform the write. write_sandbox_memory( - ctx.schedule.sandbox_data_write_cost, + ctx.schedule, ctx.gas_meter, &ctx.memory, dest_ptr, @@ -424,7 +573,7 @@ define_env!(init_env, , // Finally, perform the write. write_sandbox_memory( - ctx.schedule.sandbox_data_write_cost, + ctx.schedule, ctx.gas_meter, &ctx.memory, dest_ptr, diff --git a/srml/council/Cargo.toml b/srml/council/Cargo.toml index e2bad6b3c8b08bd5ea33a4c62c9893b8b4daffb9..e26003a73e4f13c62e9c9ab85891cb1d22a2fd79 100644 --- a/srml/council/Cargo.toml +++ b/srml/council/Cargo.toml @@ -2,35 +2,37 @@ name = "srml-council" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-balances = { path = "../balances", default-features = false } -srml-democracy = { path = "../democracy", default-features = false } -srml-system = { path = "../system", default-features = false } +democracy = { package = "srml-democracy", path = "../democracy", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +hex-literal = "0.1.0" +balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", "safe-mix/std", "parity-codec/std", "parity-codec-derive/std", "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", + "serde", + "runtime_io/std", "srml-support/std", - "sr-primitives/std", - "srml-balances/std", - "srml-democracy/std", - "srml-system/std", + "primitives/std", + "democracy/std", + "system/std", ] diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 9d5044589106bb20d55d6d8e177f5b79cded1e7c..de64b8c55c507f4a76333d10129af6635561d57d 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,39 +18,21 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(feature = "std")] -extern crate serde; - -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - -extern crate parity_codec as codec; -#[macro_use] extern crate parity_codec_derive; -extern crate substrate_primitives; -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; -extern crate sr_io as runtime_io; -#[macro_use] extern crate srml_support; -extern crate sr_primitives as primitives; -extern crate srml_balances as balances; -extern crate srml_democracy as democracy; -extern crate srml_system as system; - pub mod voting; pub mod motions; pub mod seats; -pub use seats::{Trait, Module, RawEvent, Event, VoteIndex}; +pub use crate::seats::{Trait, Module, RawEvent, Event, VoteIndex}; #[cfg(test)] mod tests { // These re-exports are here for a reason, edit with care pub use super::*; pub use runtime_io::with_externalities; + use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch}; pub use substrate_primitives::H256; pub use primitives::BuildStorage; - pub use primitives::traits::{BlakeTwo256}; + pub use primitives::traits::{BlakeTwo256, IdentityLookup}; pub use primitives::testing::{Digest, DigestItem, Header}; pub use substrate_primitives::{Blake2Hasher}; pub use {seats, motions, voting}; @@ -85,18 +67,19 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = Event; type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); + type OnNewAccount = (); type Event = Event; } impl democracy::Trait for Test { + type Currency = balances::Module; type Proposal = Call; type Event = Event; } @@ -116,12 +99,10 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], - transaction_base_fee: 0, - transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - reclaim_rebate: 0, + vesting: vec![], }.build_storage().unwrap().0); t.extend(democracy::GenesisConfig::{ launch_period: 1, diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index 5316d5c68127d223647a0641a083b52651d7785b..7d9783fd33bb5433e6a3f47d0a498edbb4ac2ec5 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,11 +18,10 @@ use rstd::prelude::*; use rstd::result; -use codec::Compact; use substrate_primitives::u32_trait::Value as U32; use primitives::traits::{Hash, EnsureOrigin}; use srml_support::dispatch::{Dispatchable, Parameter}; -use srml_support::{StorageValue, StorageMap}; +use srml_support::{StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure}; use super::{Trait as CouncilTrait, Module as Council}; use system::{self, ensure_signed}; @@ -67,10 +66,9 @@ decl_event!( decl_module! { pub struct Module for enum Call where origin: ::Origin { - fn deposit_event() = default; - fn propose(origin, threshold: Compact, proposal: Box<::Proposal>) { + fn deposit_event() = default; + fn propose(origin, #[compact] threshold: u32, proposal: Box<::Proposal>) { let who = ensure_signed(origin)?; - let threshold = threshold.into(); ensure!(Self::is_councillor(&who), "proposer not on council"); @@ -92,9 +90,8 @@ decl_module! { } } - fn vote(origin, proposal: T::Hash, index: Compact, approve: bool) { + fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { let who = ensure_signed(origin)?; - let index = index.into(); ensure!(Self::is_councillor(&who), "voter not on council"); @@ -205,10 +202,11 @@ impl EnsureOrigin for EnsureMembers mod tests { use super::*; use super::RawEvent; - use ::tests::*; - use ::tests::{Call, Origin, Event as OuterEvent}; - use srml_support::Hashable; + use crate::tests::*; + use crate::tests::{Call, Origin, Event as OuterEvent}; + use srml_support::{Hashable, assert_ok, assert_noop}; use system::{EventRecord, Phase}; + use hex_literal::{hex, hex_impl}; #[test] fn motions_basic_environment_works() { @@ -220,7 +218,7 @@ mod tests { } fn set_balance_proposal(value: u64) -> Call { - Call::Balances(balances::Call::set_balance(balances::address::Address::Id(42), value.into(), 0.into())) + Call::Balances(balances::Call::set_balance(42, value.into(), 0)) } #[test] @@ -229,7 +227,7 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 3.into(), Box::new(proposal.clone()))); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); assert_eq!(CouncilMotions::proposals(), vec![hash]); assert_eq!(CouncilMotions::proposal_of(&hash), Some(proposal)); assert_eq!(CouncilMotions::voting(&hash), Some((0, 3, vec![1], Vec::::new()))); @@ -237,7 +235,7 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), 3)) + event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)) } ]); }); @@ -248,7 +246,7 @@ mod tests { with_externalities(&mut new_test_ext(true), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_noop!(CouncilMotions::propose(Origin::signed(42), 3.into(), Box::new(proposal.clone())), "proposer not on council"); + assert_noop!(CouncilMotions::propose(Origin::signed(42), 3, Box::new(proposal.clone())), "proposer not on council"); }); } @@ -258,8 +256,8 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 3.into(), Box::new(proposal.clone()))); - assert_noop!(CouncilMotions::vote(Origin::signed(42), hash.clone(), 0.into(), true), "voter not on council"); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_noop!(CouncilMotions::vote(Origin::signed(42), hash.clone(), 0, true), "voter not on council"); }); } @@ -269,8 +267,8 @@ mod tests { System::set_block_number(3); let proposal = set_balance_proposal(42); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 3.into(), Box::new(proposal.clone()))); - assert_noop!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 1.into(), true), "mismatched index"); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_noop!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 1, true), "mismatched index"); }); } @@ -280,21 +278,21 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 2.into(), Box::new(proposal.clone()))); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); assert_eq!(CouncilMotions::voting(&hash), Some((0, 2, vec![1], Vec::::new()))); - assert_noop!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0.into(), true), "duplicate vote ignored"); - assert_ok!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0.into(), false)); + assert_noop!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0, true), "duplicate vote ignored"); + assert_ok!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0, false)); assert_eq!(CouncilMotions::voting(&hash), Some((0, 2, Vec::::new(), vec![1]))); - assert_noop!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0.into(), false), "duplicate vote ignored"); + assert_noop!(CouncilMotions::vote(Origin::signed(1), hash.clone(), 0, false), "duplicate vote ignored"); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), 2)) + event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(1, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), false, 0, 1)) + event: OuterEvent::motions(RawEvent::Voted(1, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 0, 1)) } ]); }); @@ -306,21 +304,21 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 3.into(), Box::new(proposal.clone()))); - assert_ok!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 0.into(), false)); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 0, false)); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), 3)) + event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(2, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), false, 1, 1)) + event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 1, 1)) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Disapproved(hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into())) + event: OuterEvent::motions(RawEvent::Disapproved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())) } ]); }); @@ -332,25 +330,25 @@ mod tests { System::set_block_number(1); let proposal = set_balance_proposal(42); let hash: H256 = proposal.blake2_256().into(); - assert_ok!(CouncilMotions::propose(Origin::signed(1), 2.into(), Box::new(proposal.clone()))); - assert_ok!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 0.into(), true)); + assert_ok!(CouncilMotions::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(CouncilMotions::vote(Origin::signed(2), hash.clone(), 0, true)); assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), 2)) + event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(2, hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), true, 2, 0)) + event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), true, 2, 0)) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Approved(hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into())) + event: OuterEvent::motions(RawEvent::Approved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())) }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Executed(hex!["35282aeb9f95795dc1be91b748cec2d210338f2c9c1a85d98e7a3619b6187d22"].into(), false)) + event: OuterEvent::motions(RawEvent::Executed(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false)) } ]); }); diff --git a/srml/council/src/seats.rs b/srml/council/src/seats.rs index 7fef771d38b8445f34a6e2ad1ee8c7fc4f79957d..c3ce3ad1b13eb54d4c514ca2127b49cd3517eb4d 100644 --- a/srml/council/src/seats.rs +++ b/srml/council/src/seats.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,12 +17,10 @@ //! Council system: Handles the voting in and maintenance of council members. use rstd::prelude::*; -use codec::{Compact, HasCompact}; -use primitives::traits::{Zero, One, As}; +use primitives::traits::{Zero, One, As, StaticLookup}; use runtime_io::print; -use srml_support::{StorageValue, StorageMap, dispatch::Result}; +use srml_support::{StorageValue, StorageMap, dispatch::Result, traits::Currency, decl_storage, decl_event, ensure}; use democracy; -use balances::{self, address::Address}; use system::{self, ensure_signed}; // no polynomial attacks: @@ -79,28 +77,38 @@ use system::{self, ensure_signed}; // after each vote as all but K entries are cleared. newly registering candidates must use cleared // entries before they increase the capacity. +use srml_support::{decl_module, traits::ArithmeticType}; + pub type VoteIndex = u32; +type BalanceOf = <::Currency as ArithmeticType>::Type; + pub trait Trait: democracy::Trait { type Event: From> + Into<::Event>; } decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots /// are registered. - fn set_approvals(origin, votes: Vec, index: Compact) { + fn set_approvals(origin, votes: Vec, #[compact] index: VoteIndex) { let who = ensure_signed(origin)?; - let index: VoteIndex = index.into(); + let candidates = Self::candidates(); ensure!(!Self::presentation_active(), "no approval changes during presentation period"); ensure!(index == Self::vote_index(), "incorrect vote index"); + ensure!(!candidates.len().is_zero(), "amount of candidates to receive approval votes should be non-zero"); + // Prevent a vote from voters that provide a list of votes that exceeds the candidates length + // since otherise an attacker may be able to submit a very long list of `votes` that far exceeds + // the amount of candidates and waste more computation than a reasonable voting bond would cover. + ensure!(candidates.len() >= votes.len(), "amount of candidate approval votes cannot exceed amount of candidates"); + if !>::exists(&who) { // not yet a voter - deduct bond. // NOTE: this must be the last potential bailer, since it changes state. - >::reserve(&who, Self::voting_bond())?; + T::Currency::reserve(&who, Self::voting_bond())?; >::put({ let mut v = Self::voters(); @@ -119,24 +127,21 @@ decl_module! { /// May be called by anyone. Returns the voter deposit to `signed`. fn reap_inactive_voter( origin, - reporter_index: Compact, - who: Address, - who_index: Compact, - assumed_vote_index: Compact + #[compact] reporter_index: u32, + who: ::Source, + #[compact] who_index: u32, + #[compact] assumed_vote_index: VoteIndex ) { let reporter = ensure_signed(origin)?; - let assumed_vote_index: VoteIndex = assumed_vote_index.into(); - let who = >::lookup(who)?; + let who = T::Lookup::lookup(who)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_last_active(&reporter).is_some(), "reporter must be a voter"); let last_active = Self::voter_last_active(&who).ok_or("target for inactivity cleanup must be active")?; ensure!(assumed_vote_index == Self::vote_index(), "vote index not current"); - ensure!(last_active < assumed_vote_index - Self::inactivity_grace_period(), "cannot reap during grace perid"); + ensure!(assumed_vote_index > last_active + Self::inactivity_grace_period(), "cannot reap during grace period"); let voters = Self::voters(); - let reporter_index: u32 = reporter_index.into(); let reporter_index = reporter_index as usize; - let who_index: u32 = who_index.into(); let who_index = who_index as usize; ensure!(reporter_index < voters.len() && voters[reporter_index] == reporter, "bad reporter index"); ensure!(who_index < voters.len() && voters[who_index] == who, "bad target index"); @@ -157,40 +162,38 @@ decl_module! { voters ); if valid { - // This only fails if `who` doesn't exist, which it clearly must do since its the origin. + // This only fails if `reporter` doesn't exist, which it clearly must do since its the origin. // Still, it's no more harmful to propagate any error at this point. - >::repatriate_reserved(&who, &reporter, Self::voting_bond())?; + T::Currency::repatriate_reserved(&who, &reporter, Self::voting_bond())?; Self::deposit_event(RawEvent::VoterReaped(who, reporter)); } else { - >::slash_reserved(&reporter, Self::voting_bond()); + T::Currency::slash_reserved(&reporter, Self::voting_bond()); Self::deposit_event(RawEvent::BadReaperSlashed(reporter)); } } /// Remove a voter. All votes are cancelled and the voter deposit is returned. - fn retract_voter(origin, index: Compact) { + fn retract_voter(origin, #[compact] index: u32) { let who = ensure_signed(origin)?; ensure!(!Self::presentation_active(), "cannot retract when presenting"); ensure!(>::exists(&who), "cannot retract non-voter"); let voters = Self::voters(); - let index: u32 = index.into(); let index = index as usize; ensure!(index < voters.len(), "retraction index invalid"); ensure!(voters[index] == who, "retraction index mismatch"); Self::remove_voter(&who, index, voters); - >::unreserve(&who, Self::voting_bond()); + T::Currency::unreserve(&who, Self::voting_bond()); } /// Submit oneself for candidacy. /// /// Account must have enough transferrable funds in it to pay the bond. - fn submit_candidacy(origin, slot: Compact) { + fn submit_candidacy(origin, #[compact] slot: u32) { let who = ensure_signed(origin)?; ensure!(!Self::is_a_candidate(&who), "duplicate candidate submission"); - let slot: u32 = slot.into(); let slot = slot as usize; let count = Self::candidate_count() as usize; let candidates = Self::candidates(); @@ -200,7 +203,7 @@ decl_module! { "invalid candidate slot" ); // NOTE: This must be last as it has side-effects. - >::reserve(&who, Self::candidacy_bond()) + T::Currency::reserve(&who, Self::candidacy_bond()) .map_err(|_| "candidate has not enough funds")?; >::insert(&who, (Self::vote_index(), slot as u32)); @@ -219,21 +222,20 @@ decl_module! { /// `signed` should have at least fn present_winner( origin, - candidate: Address, - total: ::Type, - index: Compact + candidate: ::Source, + #[compact] total: BalanceOf, + #[compact] index: VoteIndex ) -> Result { let who = ensure_signed(origin)?; - let total = total.into(); - let index: VoteIndex = index.into(); + ensure!(!total.is_zero(), "stake deposited to present winner and be added to leaderboard should be non-zero"); - let candidate = >::lookup(candidate)?; + let candidate = T::Lookup::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalise().ok_or("cannot present outside of presentation period")?; let stakes = Self::snapshoted_stakes(); let voters = Self::voters(); - let bad_presentation_punishment = Self::present_slash_per_voter() * T::Balance::sa(voters.len() as u64); - ensure!(>::can_slash(&who, bad_presentation_punishment), "presenter must have sufficient slashable funds"); + let bad_presentation_punishment = Self::present_slash_per_voter() * BalanceOf::::sa(voters.len() as u64); + ensure!(T::Currency::can_slash(&who, bad_presentation_punishment), "presenter must have sufficient slashable funds"); let mut leaderboard = Self::leaderboard().ok_or("leaderboard must exist while present phase active")?; ensure!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); @@ -264,7 +266,7 @@ decl_module! { } else { // we can rest assured it will be Ok since we checked `can_slash` earlier; still // better safe than sorry. - let _ = >::slash(&who, bad_presentation_punishment); + let _ = T::Currency::slash(&who, bad_presentation_punishment); Err(if dupe { "duplicate presentation" } else { "incorrect total" }) } } @@ -272,16 +274,15 @@ decl_module! { /// Set the desired member count; if lower than the current count, then seats will not be up /// election when they expire. If more, then a new vote will be started if one is not already /// in progress. - fn set_desired_seats(count: Compact) { - let count: u32 = count.into(); + fn set_desired_seats(#[compact] count: u32) { >::put(count); } /// Remove a particular member. A tally will happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. /// This is effective immediately. - fn remove_member(who: Address) { - let who = >::lookup(who)?; + fn remove_member(who: ::Source) { + let who = T::Lookup::lookup(who)?; let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() .into_iter() .filter(|i| i.0 != who) @@ -291,14 +292,14 @@ decl_module! { /// Set the presentation duration. If there is currently a vote being presented for, will /// invoke `finalise_vote`. - fn set_presentation_duration(count: ::Type) { - >::put(count.into()); + fn set_presentation_duration(#[compact] count: T::BlockNumber) { + >::put(count); } /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalise_vote`. - fn set_term_duration(count: ::Type) { - >::put(count.into()); + fn set_term_duration(#[compact] count: T::BlockNumber) { + >::put(count); } fn on_finalise(n: T::BlockNumber) { @@ -315,16 +316,16 @@ decl_storage! { // parameters /// How much should be locked up in order to submit one's candidacy. - pub CandidacyBond get(candidacy_bond) config(): T::Balance = T::Balance::sa(9); + pub CandidacyBond get(candidacy_bond) config(): BalanceOf = BalanceOf::::sa(9); /// How much should be locked up in order to be able to submit votes. - pub VotingBond get(voting_bond) config(voter_bond): T::Balance; + pub VotingBond get(voting_bond) config(voter_bond): BalanceOf; /// The punishment, per voter, if you provide an invalid presentation. - pub PresentSlashPerVoter get(present_slash_per_voter) config(): T::Balance = T::Balance::sa(1); + pub PresentSlashPerVoter get(present_slash_per_voter) config(): BalanceOf = BalanceOf::::sa(1); /// How many runners-up should have their approvals persist until the next vote. pub CarryCount get(carry_count) config(): u32 = 2; /// How long to give each top candidate to present themselves after the vote ends. pub PresentationDuration get(presentation_duration) config(): T::BlockNumber = T::BlockNumber::sa(1000); - /// How many votes need to go by after a voter's last vote before they can be reaped if their + /// How many vote indexes need to go by after a target voter's last vote before they can be reaped if their /// approvals are moot. pub InactiveGracePeriod get(inactivity_grace_period) config(inactive_grace_period): VoteIndex = 1; /// How often (in blocks) to check for new votes. @@ -336,13 +337,16 @@ decl_storage! { // permanent state (always relevant, changes only at the finalisation of voting) /// The current council. When there's a vote going on, this should still be used for executive - /// matters. + /// matters. The block number (second element in the tuple) is the block that their position is + /// active until (calculated by the sum of the block number when the council member was elected + /// and their term duration). pub ActiveCouncil get(active_council) config(): Vec<(T::AccountId, T::BlockNumber)>; /// The total number of votes that have happened or are in progress. pub VoteCount get(vote_index): VoteIndex; // persistent state (always relevant, changes constantly) - /// The last cleared vote index that this voter was last active at. + /// A list of votes for each voter, respecting the last cleared vote index that this voter was + /// last active at. pub ApprovalsOf get(approvals_of): map T::AccountId => Vec; /// The vote index and list slot that the candidate `who` was registered or `None` if they are not /// currently registered. @@ -359,9 +363,9 @@ decl_storage! { /// The accounts holding the seats that will become free on the next tally. pub NextFinalise get(next_finalise): Option<(T::BlockNumber, u32, Vec)>; /// The stakes as they were at the point that the vote ended. - pub SnapshotedStakes get(snapshoted_stakes): Vec; + pub SnapshotedStakes get(snapshoted_stakes): Vec>; /// Get the leaderboard if we;re in the presentation phase. - pub Leaderboard get(leaderboard): Option >; // ORDERED low -> high + pub Leaderboard get(leaderboard): Option, T::AccountId)> >; // ORDERED low -> high } } @@ -459,17 +463,18 @@ impl Module { let desired_seats = Self::desired_seats() as usize; let number = >::block_number(); let expiring = active_council.iter().take_while(|i| i.1 == number).map(|i| i.0.clone()).collect::>(); - if active_council.len() - expiring.len() < desired_seats { - let empty_seats = desired_seats - (active_council.len() - expiring.len()); + let retaining_seats = active_council.len() - expiring.len(); + if retaining_seats < desired_seats { + let empty_seats = desired_seats - retaining_seats; >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); let voters = Self::voters(); - let votes = voters.iter().map(>::total_balance).collect::>(); + let votes = voters.iter().map(T::Currency::total_balance).collect::>(); >::put(votes); // initialise leaderboard. let leaderboard_size = empty_seats + Self::carry_count() as usize; - >::put(vec![(T::Balance::zero(), T::AccountId::default()); leaderboard_size]); + >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); } @@ -483,7 +488,7 @@ impl Module { >::kill(); let (_, coming, expiring): (T::BlockNumber, u32, Vec) = >::take().ok_or("finalise can only be called after a tally is started.")?; - let leaderboard: Vec<(T::Balance, T::AccountId)> = >::take().unwrap_or_default(); + let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take().unwrap_or_default(); let new_expiry = >::block_number() + Self::term_duration(); // return bond to winners. @@ -494,7 +499,7 @@ impl Module { .take(coming as usize) .map(|(_, a)| a) .cloned() - .inspect(|a| {>::unreserve(a, candidacy_bond);}) + .inspect(|a| {T::Currency::unreserve(a, candidacy_bond);}) .collect(); let active_council = Self::active_council(); let outgoing = active_council.iter().take(expiring.len()).map(|a| a.0.clone()).collect(); @@ -544,7 +549,8 @@ impl Module { #[cfg(test)] mod tests { use super::*; - use ::tests::*; + use crate::tests::*; + use srml_support::{assert_ok, assert_noop, assert_err}; #[test] fn params_should_work() { @@ -558,6 +564,7 @@ mod tests { assert_eq!(Council::voting_bond(), 3); assert_eq!(Council::present_slash_per_voter(), 1); assert_eq!(Council::presentation_duration(), 2); + assert_eq!(Council::inactivity_grace_period(), 1); assert_eq!(Council::voting_period(), 4); assert_eq!(Council::term_duration(), 5); assert_eq!(Council::desired_seats(), 2); @@ -588,14 +595,14 @@ mod tests { assert_eq!(Council::is_a_candidate(&1), false); assert_eq!(Council::is_a_candidate(&2), false); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); assert_eq!(Council::candidate_reg_info(2), None); assert_eq!(Council::is_a_candidate(&1), true); assert_eq!(Council::is_a_candidate(&2), false); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); assert_eq!(Council::candidates(), vec![1, 2]); assert_eq!(Council::candidate_reg_info(1), Some((0, 0))); assert_eq!(Council::candidate_reg_info(2), Some((0, 1))); @@ -622,10 +629,10 @@ mod tests { System::set_block_number(1); assert_eq!(Council::candidates(), vec![0, 0, 1]); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); assert_eq!(Council::candidates(), vec![0, 2, 1]); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); assert_eq!(Council::candidates(), vec![3, 2, 1]); }); } @@ -638,10 +645,10 @@ mod tests { System::set_block_number(1); assert_eq!(Council::candidates(), vec![0, 0, 1]); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); assert_eq!(Council::candidates(), vec![2, 0, 1]); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 1)); assert_eq!(Council::candidates(), vec![2, 3, 1]); }); } @@ -650,7 +657,7 @@ mod tests { fn candidate_submission_not_using_free_slot_should_not_work() { with_externalities(&mut new_test_ext_with_candidate_holes(), || { System::set_block_number(1); - assert_noop!(Council::submit_candidacy(Origin::signed(4), 3.into()), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(4), 3), "invalid candidate slot"); }); } @@ -659,7 +666,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_noop!(Council::submit_candidacy(Origin::signed(1), 1.into()), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(1), 1), "invalid candidate slot"); }); } @@ -668,9 +675,9 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); - assert_noop!(Council::submit_candidacy(Origin::signed(2), 0.into()), "invalid candidate slot"); + assert_noop!(Council::submit_candidacy(Origin::signed(2), 0), "invalid candidate slot"); }); } @@ -679,9 +686,9 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_eq!(Council::candidates(), vec![1]); - assert_noop!(Council::submit_candidacy(Origin::signed(1), 1.into()), "duplicate candidate submission"); + assert_noop!(Council::submit_candidacy(Origin::signed(1), 1), "duplicate candidate submission"); }); } @@ -690,7 +697,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); assert_eq!(Council::candidates(), Vec::::new()); - assert_noop!(Council::submit_candidacy(Origin::signed(7), 0.into()), "candidate has not enough funds"); + assert_noop!(Council::submit_candidacy(Origin::signed(7), 0), "candidate has not enough funds"); }); } @@ -699,20 +706,20 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0.into())); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0)); assert_eq!(Council::approvals_of(1), vec![true]); assert_eq!(Council::approvals_of(4), vec![true]); assert_eq!(Council::voters(), vec![1, 4]); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0.into())); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0)); assert_eq!(Council::approvals_of(1), vec![true]); assert_eq!(Council::approvals_of(4), vec![true]); @@ -723,19 +730,43 @@ mod tests { }); } + #[test] + fn setting_any_approval_vote_count_without_any_candidate_count_should_not_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + assert_eq!(Council::candidates().len(), 0); + + assert_noop!(Council::set_approvals(Origin::signed(4), vec![], 0), "amount of candidates to receive approval votes should be non-zero"); + }); + } + + #[test] + fn setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(1); + + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_eq!(Council::candidates().len(), 1); + + assert_noop!(Council::set_approvals(Origin::signed(4), vec![true, true], 0), "amount of candidate approval votes cannot exceed amount of candidates"); + }); + } + #[test] fn resubmitting_voting_should_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true], 0)); assert_eq!(Council::approvals_of(4), vec![true]); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_eq!(Council::candidates().len(), 3); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0)); assert_eq!(Council::approvals_of(4), vec![true, false, true]); }); @@ -746,14 +777,15 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_eq!(Council::candidates().len(), 3); - assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0.into())); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![true, false, true], 0)); assert_eq!(Council::voters(), vec![1, 2, 3, 4]); assert_eq!(Council::approvals_of(1), vec![true]); @@ -761,7 +793,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(Origin::signed(1), 0.into())); + assert_ok!(Council::retract_voter(Origin::signed(1), 0)); assert_eq!(Council::voters(), vec![4, 2, 3]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -769,7 +801,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(Origin::signed(2), 1.into())); + assert_ok!(Council::retract_voter(Origin::signed(2), 1)); assert_eq!(Council::voters(), vec![4, 3]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -777,7 +809,7 @@ mod tests { assert_eq!(Council::approvals_of(3), vec![false, true, true]); assert_eq!(Council::approvals_of(4), vec![true, false, true]); - assert_ok!(Council::retract_voter(Origin::signed(3), 1.into())); + assert_ok!(Council::retract_voter(Origin::signed(3), 1)); assert_eq!(Council::voters(), vec![4]); assert_eq!(Council::approvals_of(1), Vec::::new()); @@ -791,11 +823,11 @@ mod tests { fn invalid_retraction_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_eq!(Council::voters(), vec![1, 2]); - assert_noop!(Council::retract_voter(Origin::signed(1), 1.into()), "retraction index mismatch"); + assert_noop!(Council::retract_voter(Origin::signed(1), 1), "retraction index mismatch"); }); } @@ -803,9 +835,9 @@ mod tests { fn overflow_retraction_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0.into())); - assert_noop!(Council::retract_voter(Origin::signed(1), 1.into()), "retraction index invalid"); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_noop!(Council::retract_voter(Origin::signed(1), 1), "retraction index invalid"); }); } @@ -813,9 +845,9 @@ mod tests { fn non_voter_retraction_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(1); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0.into())); - assert_noop!(Council::retract_voter(Origin::signed(2), 0.into()), "cannot retract non-voter"); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 0)); + assert_ok!(Council::set_approvals(Origin::signed(1), vec![true], 0)); + assert_noop!(Council::retract_voter(Origin::signed(2), 0), "cannot retract non-voter"); }); } @@ -825,10 +857,10 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_eq!(Council::voters(), vec![2, 5]); assert_eq!(Council::approvals_of(2), vec![true, false]); assert_eq!(Council::approvals_of(5), vec![false, true]); @@ -836,8 +868,8 @@ mod tests { System::set_block_number(6); assert!(Council::presentation_active()); - assert_eq!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into()), Ok(())); - assert_eq!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into()), Ok(())); + assert_eq!(Council::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); + assert_eq!(Council::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); assert_eq!(Council::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); assert_ok!(Council::end_block(System::block_number())); @@ -853,22 +885,35 @@ mod tests { }); } + #[test] + fn presentations_with_zero_staked_deposit_should_not_work() { + with_externalities(&mut new_test_ext(false), || { + System::set_block_number(4); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); + assert_ok!(Council::end_block(System::block_number())); + + System::set_block_number(6); + assert_noop!(Council::present_winner(Origin::signed(4), 2, 0, 0), "stake deposited to present winner and be added to leaderboard should be non-zero"); + }); + } + #[test] fn double_presentations_should_be_punished() { with_externalities(&mut new_test_ext(false), || { assert!(Balances::can_slash(&4, 10)); System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); - assert_eq!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into()), Err("duplicate presentation")); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); + assert_eq!(Council::present_winner(Origin::signed(4), 5, 50, 0), Err("duplicate presentation")); assert_ok!(Council::end_block(System::block_number())); assert_eq!(Council::active_council(), vec![(5, 11), (2, 11)]); @@ -880,27 +925,27 @@ mod tests { fn retracting_inactive_voter_should_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 1)); assert_ok!(Council::end_block(System::block_number())); assert_ok!(Council::reap_inactive_voter(Origin::signed(5), (Council::voters().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2.into(), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into() + 2, (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 )); assert_eq!(Council::voters(), vec![5]); @@ -914,21 +959,21 @@ mod tests { fn presenting_for_double_election_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_eq!(Council::submit_candidacy(Origin::signed(2), 0.into()), Ok(())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_eq!(Council::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_eq!(Council::submit_candidacy(Origin::signed(2), 0.into()), Ok(())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 1.into())); + assert_eq!(Council::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 1.into()), "candidate must not form a duplicated member if elected"); + assert_noop!(Council::present_winner(Origin::signed(4), 2, 20, 1), "candidate must not form a duplicated member if elected"); }); } @@ -936,30 +981,30 @@ mod tests { fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(11); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); assert_ok!(Council::reap_inactive_voter(Origin::signed(5), (Council::voters().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2.into(), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into() + 2, (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 )); assert_eq!(Council::voters(), vec![5]); @@ -973,27 +1018,27 @@ mod tests { fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 1)); assert_ok!(Council::end_block(System::block_number())); assert_noop!(Council::reap_inactive_voter(Origin::signed(2), - 42.into(), - 2.into(), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into() + 42, + 2, (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 ), "bad reporter index"); }); } @@ -1002,27 +1047,27 @@ mod tests { fn retracting_inactive_voter_with_bad_target_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 1)); assert_ok!(Council::end_block(System::block_number())); assert_noop!(Council::reap_inactive_voter(Origin::signed(2), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into(), 42.into(), - 2.into() + 2, 42, + 2 ), "bad target index"); }); } @@ -1031,36 +1076,42 @@ mod tests { fn attempting_to_retract_active_voter_should_slash_reporter() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 1.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(4), 2.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 3.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false, false, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, false, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 1)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 2)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 3)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false, false, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, true, false, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::set_desired_seats(3.into())); + assert_ok!(Council::set_desired_seats(3)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 1.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 1)); assert_ok!(Council::end_block(System::block_number())); + assert_eq!(Council::vote_index(), 2); + assert_eq!(Council::inactivity_grace_period(), 1); + assert_eq!(Council::voting_period(), 4); + assert_eq!(Council::voter_last_active(4), Some(0)); + assert_ok!(Council::reap_inactive_voter(Origin::signed(4), (Council::voters().iter().position(|&i| i == 4).unwrap() as u32).into(), - 2.into(), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into() + 2, + (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 )); assert_eq!(Council::voters(), vec![2, 3, 5]); @@ -1073,27 +1124,27 @@ mod tests { fn attempting_to_retract_inactive_voter_by_nonvoter_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![true], 1)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 1)); assert_ok!(Council::end_block(System::block_number())); assert_noop!(Council::reap_inactive_voter(Origin::signed(4), - 0.into(), - 2.into(), (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2.into() + 0, + 2, (Council::voters().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 ), "reporter must be a voter"); }); } @@ -1102,24 +1153,32 @@ mod tests { fn presenting_loser_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(4), 3.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 4.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); - assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into()), "candidate not worthy of leaderboard"); + assert_ok!(Council::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); + + assert_eq!(Council::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + + assert_noop!(Council::present_winner(Origin::signed(4), 2, 20, 0), "candidate not worthy of leaderboard"); }); } @@ -1127,24 +1186,24 @@ mod tests { fn presenting_loser_first_should_not_matter() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(4), 3.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 4.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); assert_eq!(Council::leaderboard(), Some(vec![ (30, 3), @@ -1160,7 +1219,7 @@ mod tests { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_noop!(Council::present_winner(Origin::signed(5), 5.into(), 1.into(), 0.into()), "cannot present outside of presentation period"); + assert_noop!(Council::present_winner(Origin::signed(5), 5, 1, 0), "cannot present outside of presentation period"); }); } @@ -1168,14 +1227,14 @@ mod tests { fn present_with_invalid_vote_index_should_not_work() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_noop!(Council::present_winner(Origin::signed(4), 2.into(), 20.into(), 1.into()), "index not current"); + assert_noop!(Council::present_winner(Origin::signed(4), 2, 20, 1), "index not current"); }); } @@ -1185,16 +1244,16 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); assert_eq!(Balances::free_balance(&1), 1); assert_eq!(Balances::reserved_balance(&1), 9); - assert_noop!(Council::present_winner(Origin::signed(1), 1.into(), 20.into(), 0.into()), "presenter must have sufficient slashable funds"); + assert_noop!(Council::present_winner(Origin::signed(1), 1, 20, 0), "presenter must have sufficient slashable funds"); }); } @@ -1205,14 +1264,14 @@ mod tests { assert!(!Council::presentation_active()); assert_eq!(Balances::total_balance(&4), 40); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![true, false], 0)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_err!(Council::present_winner(Origin::signed(4), 2.into(), 80.into(), 0.into()), "incorrect total"); + assert_err!(Council::present_winner(Origin::signed(4), 2, 80, 0), "incorrect total"); assert_eq!(Balances::total_balance(&4), 38); }); @@ -1224,31 +1283,33 @@ mod tests { System::set_block_number(4); assert!(!Council::presentation_active()); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(4), 3.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 4.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); assert!(Council::presentation_active()); - assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 1, 60, 0)); + // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those + // to be carried are the lowest and stored in lowest indexes assert_eq!(Council::leaderboard(), Some(vec![ (0, 0), (0, 0), (0, 0), (60, 1) ])); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); assert_eq!(Council::leaderboard(), Some(vec![ (30, 3), (40, 4), @@ -1281,33 +1342,33 @@ mod tests { fn second_tally_should_use_runners_up() { with_externalities(&mut new_test_ext(false), || { System::set_block_number(4); - assert_ok!(Council::submit_candidacy(Origin::signed(1), 0.into())); - assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(2), 1.into())); - assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(3), 2.into())); - assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(4), 3.into())); - assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0.into())); - assert_ok!(Council::submit_candidacy(Origin::signed(5), 4.into())); - assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0.into())); + assert_ok!(Council::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Council::set_approvals(Origin::signed(2), vec![false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Council::set_approvals(Origin::signed(3), vec![false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Council::set_approvals(Origin::signed(4), vec![false, false, false, true], 0)); + assert_ok!(Council::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Council::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(6); - assert_ok!(Council::present_winner(Origin::signed(4), 1.into(), 60.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 30.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 0.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 5.into(), 50.into(), 0.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Council::present_winner(Origin::signed(4), 5, 50, 0)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(8); - assert_ok!(Council::set_approvals(Origin::signed(6), vec![false, false, true, false], 1.into())); - assert_ok!(Council::set_desired_seats(3.into())); + assert_ok!(Council::set_approvals(Origin::signed(6), vec![false, false, true, false], 1)); + assert_ok!(Council::set_desired_seats(3)); assert_ok!(Council::end_block(System::block_number())); System::set_block_number(10); - assert_ok!(Council::present_winner(Origin::signed(4), 3.into(), 90.into(), 1.into())); - assert_ok!(Council::present_winner(Origin::signed(4), 4.into(), 40.into(), 1.into())); + assert_ok!(Council::present_winner(Origin::signed(4), 3, 90, 1)); + assert_ok!(Council::present_winner(Origin::signed(4), 4, 40, 1)); assert_ok!(Council::end_block(System::block_number())); assert!(!Council::presentation_active()); diff --git a/srml/council/src/voting.rs b/srml/council/src/voting.rs index 9536fe5d35029bc7c83ac11e99838f4b570ca282..c365ea8021d7dda974272e51e651e03011345cb6 100644 --- a/srml/council/src/voting.rs +++ b/srml/council/src/voting.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,11 +18,10 @@ use rstd::prelude::*; use rstd::borrow::Borrow; -use codec::HasCompact; use primitives::traits::{Hash, As, Zero}; use runtime_io::print; use srml_support::dispatch::Result; -use srml_support::{StorageValue, StorageMap, IsSubType}; +use srml_support::{StorageValue, StorageMap, IsSubType, decl_module, decl_storage, decl_event, ensure}; use {system, democracy}; use super::{Trait as CouncilTrait, Module as Council}; use system::ensure_signed; @@ -33,7 +32,7 @@ pub trait Trait: CouncilTrait { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; fn propose(origin, proposal: Box) { let who = ensure_signed(origin)?; @@ -95,12 +94,12 @@ decl_module! { } } - fn set_cooloff_period(blocks: ::Type) { - >::put(blocks.into()); + fn set_cooloff_period(#[compact] blocks: T::BlockNumber) { + >::put(blocks); } - fn set_voting_period(blocks: ::Type) { - >::put(blocks.into()); + fn set_voting_period(#[compact] blocks: T::BlockNumber) { + >::put(blocks); } fn on_finalise(n: T::BlockNumber) { @@ -118,7 +117,7 @@ decl_storage! { pub VotingPeriod get(voting_period) config(): T::BlockNumber = T::BlockNumber::sa(3); /// Number of blocks by which to delay enactment of successful, non-unanimous-council-instigated referendum proposals. pub EnactDelayPeriod get(enact_delay_period) config(): T::BlockNumber = T::BlockNumber::sa(0); - pub Proposals get(proposals) build(|_| vec![0u8; 0]): Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry. + pub Proposals get(proposals) build(|_| vec![]): Vec<(T::BlockNumber, T::Hash)>; // ordered by expiry. pub ProposalOf get(proposal_of): map T::Hash => Option; pub ProposalVoters get(proposal_voters): map T::Hash => Vec; pub CouncilVoteOf get(vote_of): map (T::Hash, T::AccountId) => Option; @@ -233,9 +232,9 @@ impl Module { #[cfg(test)] mod tests { use super::*; - use ::tests::*; - use ::tests::{Call, Origin}; - use srml_support::Hashable; + use crate::tests::*; + use crate::tests::{Call, Origin}; + use srml_support::{Hashable, assert_ok, assert_noop}; use democracy::{ReferendumInfo, VoteThreshold}; #[test] @@ -259,7 +258,7 @@ mod tests { } fn set_balance_proposal(value: u64) -> Call { - Call::Balances(balances::Call::set_balance(balances::address::Address::Id(42), value.into(), 0.into())) + Call::Balances(balances::Call::set_balance(42, value.into(), 0)) } fn cancel_referendum_proposal(id: u32) -> Call { diff --git a/srml/democracy/Cargo.toml b/srml/democracy/Cargo.toml index ea8b63920f7b349a767276cdb8e40cf06d256bcf..890882c485a1022ac0bb76920a3c85c45fd0b8c0 100644 --- a/srml/democracy/Cargo.toml +++ b/srml/democracy/Cargo.toml @@ -2,32 +2,34 @@ name = "srml-democracy" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-balances = { path = "../balances", default-features = false } -srml-system = { path = "../system", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../core/primitives" } +balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", + "serde", + "serde_derive", "safe-mix/std", "parity-codec/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", + "runtime_io/std", "srml-support/std", - "sr-primitives/std", - "srml-balances/std", - "srml-system/std", + "primitives/std", + "system/std", ] diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 2bf9e21ae74f46cddfe551032be352eba92d2474..fb2ee276681d538715de9b1f7ffe954efc6cb7d7 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,33 +18,21 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(test)] -extern crate substrate_primitives; - -#[macro_use] -extern crate parity_codec_derive; -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; -#[macro_use] -extern crate srml_support; - -extern crate parity_codec as codec; -extern crate sr_io as runtime_io; -extern crate sr_primitives as primitives; -extern crate srml_balances as balances; -extern crate srml_system as system; - use rstd::prelude::*; use rstd::result; -use codec::{HasCompact, Compact}; -use primitives::traits::{Zero, As}; +use primitives::traits::{Zero, As, Bounded}; +use parity_codec::{Encode, Decode}; use srml_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType}; +use srml_support::{decl_module, decl_storage, decl_event, ensure}; +use srml_support::traits::{Currency, LockableCurrency, WithdrawReason, ArithmeticType, LockIdentifier}; use srml_support::dispatch::Result; use system::ensure_signed; mod vote_threshold; pub use vote_threshold::{Approved, VoteThreshold}; +const DEMOCRACY_ID: LockIdentifier = *b"democrac"; + /// A proposal index. pub type PropIndex = u32; /// A referendum index. @@ -79,7 +67,11 @@ impl Vote { } } -pub trait Trait: balances::Trait + Sized { +type BalanceOf = <::Currency as ArithmeticType>::Type; + +pub trait Trait: system::Trait + Sized { + type Currency: ArithmeticType + LockableCurrency<::AccountId, Moment=Self::BlockNumber, Balance=BalanceOf>; + type Proposal: Parameter + Dispatchable + IsSubType>; type Event: From> + Into<::Event>; @@ -87,19 +79,18 @@ pub trait Trait: balances::Trait + Sized { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Propose a sensitive action to be taken. fn propose( origin, proposal: Box, - value: ::Type + #[compact] value: BalanceOf ) { let who = ensure_signed(origin)?; - let value = value.into(); ensure!(value >= Self::minimum_deposit(), "value too low"); - >::reserve(&who, value) + T::Currency::reserve(&who, value) .map_err(|_| "proposer's balance too low")?; let index = Self::public_prop_count(); @@ -109,15 +100,16 @@ decl_module! { let mut props = Self::public_props(); props.push((index, (*proposal).clone(), who)); >::put(props); + + Self::deposit_event(RawEvent::Proposed(index, value)); } /// Propose a sensitive action to be taken. - fn second(origin, proposal: Compact) { + fn second(origin, #[compact] proposal: PropIndex) { let who = ensure_signed(origin)?; - let proposal: PropIndex = proposal.into(); let mut deposit = Self::deposit_of(proposal) .ok_or("can only second an existing proposal")?; - >::reserve(&who, deposit.0) + T::Currency::reserve(&who, deposit.0) .map_err(|_| "seconder's balance too low")?; deposit.1.push(who); >::insert(proposal, deposit); @@ -125,12 +117,11 @@ decl_module! { /// Vote in a referendum. If `vote.is_aye()`, the vote is to enact the proposal; /// otherwise it is a vote to keep the status quo. - fn vote(origin, ref_index: Compact, vote: Vote) { + fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote) { let who = ensure_signed(origin)?; - let ref_index = ref_index.into(); ensure!(vote.multiplier() <= Self::max_lock_periods(), "vote has too great a strength"); ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - ensure!(!>::total_balance(&who).is_zero(), + ensure!(!T::Currency::total_balance(&who).is_zero(), "transactor must have balance to signal approval."); if !>::exists(&(ref_index, who.clone())) { >::mutate(ref_index, |voters| voters.push(who.clone())); @@ -149,12 +140,12 @@ decl_module! { } /// Remove a referendum. - fn cancel_referendum(ref_index: Compact) { - Self::clear_referendum(ref_index.into()); + fn cancel_referendum(#[compact] ref_index: ReferendumIndex) { + Self::clear_referendum(ref_index); } /// Cancel a proposal queued for enactment. - pub fn cancel_queued(when: T::BlockNumber, which: u32) -> Result { + pub fn cancel_queued(#[compact] when: T::BlockNumber, #[compact] which: u32) -> Result { let which = which as usize; >::mutate(when, |items| if items.len() > which { items[which] = None }); Ok(()) @@ -197,11 +188,11 @@ decl_storage! { /// The public proposals. Unsorted. pub PublicProps get(public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>; /// Those who have locked a deposit. - pub DepositOf get(deposit_of): map PropIndex => Option<(T::Balance, Vec)>; + pub DepositOf get(deposit_of): map PropIndex => Option<(BalanceOf, Vec)>; /// How often (in blocks) new public referenda are launched. pub LaunchPeriod get(launch_period) config(): T::BlockNumber = T::BlockNumber::sa(1000); /// The minimum amount to be used as a deposit for a public referendum proposal. - pub MinimumDeposit get(minimum_deposit) config(): T::Balance; + pub MinimumDeposit get(minimum_deposit) config(): BalanceOf; /// The delay before enactment for all public referenda. pub PublicDelay get(public_delay) config(): T::BlockNumber; /// The maximum number of additional lock periods a voter may offer to strengthen their vote. Multiples of `PublicDelay`. @@ -219,9 +210,6 @@ decl_storage! { /// Queue of successful referenda to be dispatched. pub DispatchQueue get(dispatch_queue): map T::BlockNumber => Vec>; - /// The block at which the `who`'s funds become liquid. - pub Bondage get(bondage): map T::AccountId => T::BlockNumber; - /// Get the voters for the current proposal. pub VotersFor get(voters_for): map ReferendumIndex => Vec; @@ -234,7 +222,8 @@ decl_storage! { decl_event!( /// An event in this module. - pub enum Event where ::Balance, ::AccountId { + pub enum Event where Balance = BalanceOf, ::AccountId { + Proposed(PropIndex, Balance), Tabled(PropIndex, Balance, Vec), Started(ReferendumIndex, VoteThreshold), Passed(ReferendumIndex), @@ -249,8 +238,8 @@ impl Module { /// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal /// index. - pub fn locked_for(proposal: PropIndex) -> Option { - Self::deposit_of(proposal).map(|(d, l)| d * T::Balance::sa(l.len() as u64)) + pub fn locked_for(proposal: PropIndex) -> Option> { + Self::deposit_of(proposal).map(|(d, l)| d * BalanceOf::::sa(l.len() as u64)) } /// Return true if `ref_index` is an on-going referendum. @@ -278,17 +267,17 @@ impl Module { } /// Get the voters for the current proposal. - pub fn tally(ref_index: ReferendumIndex) -> (T::Balance, T::Balance, T::Balance) { + pub fn tally(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { Self::voters_for(ref_index).iter() .map(|voter| ( - >::total_balance(voter), + T::Currency::total_balance(voter), Self::vote_of((ref_index, voter.clone())), )) .map(|(bal, vote)| if vote.is_aye() { - (bal * T::Balance::sa(vote.multiplier() as u64), Zero::zero(), bal) + (bal * BalanceOf::::sa(vote.multiplier() as u64), Zero::zero(), bal) } else { - (Zero::zero(), bal * T::Balance::sa(vote.multiplier() as u64), bal) + (Zero::zero(), bal * BalanceOf::::sa(vote.multiplier() as u64), bal) } ).fold((Zero::zero(), Zero::zero(), Zero::zero()), |(a, b, c), (d, e, f)| (a + d, b + e, c + f)) } @@ -350,10 +339,10 @@ impl Module { let (prop_index, proposal, _) = public_props.swap_remove(winner_index); >::put(public_props); - if let Some((deposit, depositors)) = >::take(prop_index) {//: (T::Balance, Vec) = + if let Some((deposit, depositors)) = >::take(prop_index) {//: (BalanceOf, Vec) = // refund depositors for d in &depositors { - >::unreserve(d, deposit); + T::Currency::unreserve(d, deposit); } Self::deposit_event(RawEvent::Tabled(prop_index, deposit, depositors)); Self::inject_referendum(now + Self::voting_period(), proposal, VoteThreshold::SuperMajorityApprove, Self::public_delay())?; @@ -365,7 +354,7 @@ impl Module { fn bake_referendum(now: T::BlockNumber, index: ReferendumIndex, info: ReferendumInfo) -> Result { let (approve, against, capital) = Self::tally(index); - let total_issuance = >::total_issuance(); + let total_issuance = T::Currency::total_issuance(); let approved = info.threshold.approved(approve, against, capital, total_issuance); let lock_period = Self::public_delay(); @@ -376,12 +365,12 @@ impl Module { .map(|a| (a.clone(), Self::vote_of((index, a)))) // ^^^ defensive only: all items come from `voters`; for an item to be in `voters` there must be a vote registered; qed .filter(|&(_, vote)| vote.is_aye() == approved) // Just the winning coins - { + { // now plus: the base lock period multiplied by the number of periods this voter offered to // lock should they win... let locked_until = now + lock_period * T::BlockNumber::sa((vote.multiplier()) as u64); // ...extend their bondage until at least then. - >::mutate(a, |b| if *b < locked_until { *b = locked_until }); + T::Currency::extend_lock(DEMOCRACY_ID, &a, Bounded::max_value(), locked_until, WithdrawReason::Transfer.into()); } Self::clear_referendum(index); @@ -419,30 +408,16 @@ impl Module { } } -impl balances::OnFreeBalanceZero for Module { - fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who); - } -} - -impl balances::EnsureAccountLiquid for Module { - fn ensure_account_liquid(who: &T::AccountId) -> Result { - if Self::bondage(who) <= >::block_number() { - Ok(()) - } else { - Err("cannot transfer illiquid funds") - } - } -} - #[cfg(test)] mod tests { use super::*; use runtime_io::with_externalities; + use srml_support::{impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok}; use substrate_primitives::{H256, Blake2Hasher}; use primitives::BuildStorage; - use primitives::traits::{BlakeTwo256}; + use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, DigestItem, Header}; + use balances::BalanceLock; const AYE: Vote = Vote(-1); const NAY: Vote = Vote(0); @@ -469,18 +444,19 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); + type OnNewAccount = (); type Event = (); } impl Trait for Test { + type Currency = balances::Module; type Proposal = Call; type Event = (); } @@ -493,12 +469,10 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], - transaction_base_fee: 0, - transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - reclaim_rebate: 0, + vesting: vec![], }.build_storage().unwrap().0); t.extend(GenesisConfig::{ launch_period: 1, @@ -549,13 +523,13 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_noop!(Democracy::vote(Origin::signed(1), r.into(), Vote::new(true, 7)), "vote has too great a strength"); - assert_noop!(Democracy::vote(Origin::signed(1), r.into(), Vote::new(false, 7)), "vote has too great a strength"); + assert_noop!(Democracy::vote(Origin::signed(1), r, Vote::new(true, 7)), "vote has too great a strength"); + assert_noop!(Democracy::vote(Origin::signed(1), r, Vote::new(false, 7)), "vote has too great a strength"); }); } fn set_balance_proposal(value: u64) -> Call { - Call::Balances(balances::Call::set_balance(balances::address::Address::Id(42), value.into(), 0.into())) + Call::Balances(balances::Call::set_balance(42, value.into(), 0)) } fn propose_set_balance(who: u64, value: u64, locked: u64) -> super::Result { @@ -584,7 +558,7 @@ mod tests { System::set_block_number(2); let r = 0; - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); assert_eq!(Democracy::referendum_count(), 1); assert_eq!(Democracy::voters_for(r), vec![1]); @@ -602,10 +576,10 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); assert_eq!(Balances::free_balance(&1), 5); assert_eq!(Balances::free_balance(&2), 15); assert_eq!(Balances::free_balance(&5), 35); @@ -617,10 +591,10 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); - assert_ok!(Democracy::second(Origin::signed(5), 0.into())); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&1), 10); assert_eq!(Balances::free_balance(&2), 20); @@ -649,7 +623,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); assert_ok!(propose_set_balance(2, 2, 11)); - assert_noop!(Democracy::second(Origin::signed(1), 0.into()), "seconder\'s balance too low"); + assert_noop!(Democracy::second(Origin::signed(1), 0), "seconder\'s balance too low"); }); } @@ -663,17 +637,17 @@ mod tests { assert_eq!(Democracy::end_block(System::block_number()), Ok(())); System::set_block_number(1); - assert_ok!(Democracy::vote(Origin::signed(1), 0.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&42), 4); System::set_block_number(2); - assert_ok!(Democracy::vote(Origin::signed(1), 1.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), 1, AYE)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); assert_eq!(Balances::free_balance(&42), 3); System::set_block_number(3); - assert_ok!(Democracy::vote(Origin::signed(1), 2.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), 2, AYE)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); }); } @@ -683,7 +657,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); assert_eq!(Democracy::voters_for(r), vec![1]); assert_eq!(Democracy::vote_of((r, 1)), AYE); @@ -700,7 +674,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); assert_ok!(Democracy::cancel_referendum(r.into())); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); @@ -714,7 +688,7 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), NAY)); + assert_ok!(Democracy::vote(Origin::signed(1), r, NAY)); assert_eq!(Democracy::voters_for(r), vec![1]); assert_eq!(Democracy::vote_of((r, 1)), NAY); @@ -731,12 +705,12 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(2), r.into(), NAY)); - assert_ok!(Democracy::vote(Origin::signed(3), r.into(), NAY)); - assert_ok!(Democracy::vote(Origin::signed(4), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(5), r.into(), NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(2), r, NAY)); + assert_ok!(Democracy::vote(Origin::signed(3), r, NAY)); + assert_ok!(Democracy::vote(Origin::signed(4), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, AYE)); assert_eq!(Democracy::tally(r), (110, 100, 210)); @@ -751,12 +725,12 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 1).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(2), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(3), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(4), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(5), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(6), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(3), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(4), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(6), r, AYE)); assert_eq!(Democracy::tally(r), (210, 0, 210)); @@ -775,23 +749,23 @@ mod tests { with_externalities(&mut new_test_ext_with_public_delay(1), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r.into(), Vote::new(false, 6))); - assert_ok!(Democracy::vote(Origin::signed(2), r.into(), Vote::new(true, 5))); - assert_ok!(Democracy::vote(Origin::signed(3), r.into(), Vote::new(true, 4))); - assert_ok!(Democracy::vote(Origin::signed(4), r.into(), Vote::new(true, 3))); - assert_ok!(Democracy::vote(Origin::signed(5), r.into(), Vote::new(true, 2))); - assert_ok!(Democracy::vote(Origin::signed(6), r.into(), Vote::new(false, 1))); + assert_ok!(Democracy::vote(Origin::signed(1), r, Vote::new(false, 6))); + assert_ok!(Democracy::vote(Origin::signed(2), r, Vote::new(true, 5))); + assert_ok!(Democracy::vote(Origin::signed(3), r, Vote::new(true, 4))); + assert_ok!(Democracy::vote(Origin::signed(4), r, Vote::new(true, 3))); + assert_ok!(Democracy::vote(Origin::signed(5), r, Vote::new(true, 2))); + assert_ok!(Democracy::vote(Origin::signed(6), r, Vote::new(false, 1))); assert_eq!(Democracy::tally(r), (440, 120, 210)); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - assert_eq!(Democracy::bondage(1), 0); - assert_eq!(Democracy::bondage(2), 6); - assert_eq!(Democracy::bondage(3), 5); - assert_eq!(Democracy::bondage(4), 4); - assert_eq!(Democracy::bondage(5), 3); - assert_eq!(Democracy::bondage(6), 0); + assert_eq!(Balances::locks(1), vec![]); + assert_eq!(Balances::locks(2), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 6, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(3), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 5, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(4), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 4, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(5), vec![BalanceLock { id: DEMOCRACY_ID, amount: u64::max_value(), until: 3, reasons: WithdrawReason::Transfer.into() }]); + assert_eq!(Balances::locks(6), vec![]); System::set_block_number(2); assert_eq!(Democracy::end_block(System::block_number()), Ok(())); @@ -805,8 +779,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(5), r.into(), NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, AYE)); assert_eq!(Democracy::tally(r), (60, 50, 110)); @@ -824,9 +798,9 @@ mod tests { System::set_block_number(1); let r = Democracy::inject_referendum(1, set_balance_proposal(2), VoteThreshold::SuperMajorityApprove, 0).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(4), r.into(), AYE)); - assert_ok!(Democracy::vote(Origin::signed(5), r.into(), NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r.into(), AYE)); + assert_ok!(Democracy::vote(Origin::signed(4), r, AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, AYE)); assert_eq!(Democracy::tally(r), (100, 50, 150)); diff --git a/srml/democracy/src/vote_threshold.rs b/srml/democracy/src/vote_threshold.rs index ab5e1ddee7eb47660b626acd376d13fee6dcccd8..d436757539d47e8dad3294964a80a7aa214440c0 100644 --- a/srml/democracy/src/vote_threshold.rs +++ b/srml/democracy/src/vote_threshold.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,6 +16,9 @@ //! Voting thresholds. +#[cfg(feature = "std")] +use serde_derive::{Serialize, Deserialize}; +use parity_codec::{Encode, Decode}; use primitives::traits::{Zero, IntegerSquareRoot}; use rstd::ops::{Add, Mul, Div, Rem}; diff --git a/srml/example/Cargo.toml b/srml/example/Cargo.toml index 8fe76d9bf08d599e06a5908e2e109b96675105ed..57abe374c9b131887c6dc420a562a5d8481d4d5b 100644 --- a/srml/example/Cargo.toml +++ b/srml/example/Cargo.toml @@ -2,31 +2,28 @@ name = "srml-example" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-balances = { path = "../balances", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +balances = { package = "srml-balances", path = "../balances", default-features = false } + +[dev-dependencies] +sr-io = { path = "../../core/sr-io" } +substrate-primitives = { path = "../../core/primitives" } +sr-primitives = { path = "../../core/sr-primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", - "parity-codec-derive/std", - "sr-std/std", - "sr-io/std", "sr-primitives/std", - "substrate-primitives/std", "srml-support/std", - "srml-system/std", - "srml-balances/std", + "system/std", + "balances/std", ] diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 31baac20f72e5ecbe23be07c894fd4d2de7ae9fe..e6f3cf9264d4b36c533163af164dc08b3192d930 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,37 +20,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -// Assert macros used in tests. -extern crate sr_std; - -// Needed for tests (`with_externalities`). -#[cfg(test)] -extern crate sr_io; - -// Needed for the set of mock primitives used in our tests. -#[cfg(test)] -extern crate substrate_primitives; - -// Needed for various traits. In our case, `OnFinalise`. -extern crate sr_primitives; - -// Needed for deriving `Encode` and `Decode` for `RawEvent`. -#[macro_use] -extern crate parity_codec_derive; -extern crate parity_codec as codec; - -// Needed for type-safe access to storage DB. -#[macro_use] -extern crate srml_support as support; -// `system` module provides us with all sorts of useful stuff and macros -// depend on it being around. -extern crate srml_system as system; -// `balances` module is needed for our little example. It's not required in -// general (though if you want your module to be able to work with tokens, then you -// might find it useful). -extern crate srml_balances as balances; - -use support::{StorageValue, dispatch::Result}; +use srml_support::{StorageValue, dispatch::Result, decl_module, decl_storage, decl_event}; use system::ensure_signed; /// Our module's configuration trait. All our types and consts go in here. If the @@ -63,6 +33,56 @@ pub trait Trait: balances::Trait { type Event: From> + Into<::Event>; } +decl_storage! { + // A macro for the Storage trait, and its implementation, for this module. + // This allows for type-safe usage of the Substrate storage database, so you can + // keep things around between blocks. + trait Store for Module as Example { + // Any storage declarations of the form: + // `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` + // where `` is either: + // - `Type` (a basic value item); or + // - `map KeyType => ValueType` (a map item). + // + // Note that there are two optional modifiers for the storage type declaration. + // - `Foo: Option`: + // - `Foo::put(1); Foo::get()` returns `Some(1)`; + // - `Foo::kill(); Foo::get()` returns `None`. + // - `Foo: u32`: + // - `Foo::put(1); Foo::get()` returns `1`; + // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). + // e.g. Foo: u32; + // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; + // + // For basic value items, you'll get a type which implements + // `support::StorageValue`. For map items, you'll get a type which + // implements `support::StorageMap`. + // + // If they have a getter (`get(getter_name)`), then your module will come + // equipped with `fn getter_name() -> Type` for basic value items or + // `fn getter_name(key: KeyType) -> ValueType` for map items. + Dummy get(dummy) config(): Option; + + // A map that has enumerable entries. + Bar get(bar) config(): linked_map T::AccountId => T::Balance; + + + // this one uses the default, we'll demonstrate the usage of 'mutate' API. + Foo get(foo) config(): T::Balance; + } +} + +/// An event in this module. Events are simple means of reporting specific conditions and +/// circumstances that have happened that users, Dapps and/or chain explorers would find +/// interesting and otherwise difficult to detect. +decl_event!( + pub enum Event where B = ::Balance { + // Just a normal `enum`, here's a dummy event to ensure it compiles. + /// Dummy event, just here so there's a generic type that's used. + Dummy(B), + } +); + // The module declaration. This states the entry points that we handle. The // macro takes care of the marshalling of arguments and dispatch. // @@ -98,7 +118,9 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Deposit one of this module's events by using the default implementation. /// It is also possible to provide a custom implementation. - fn deposit_event() = default; + /// For non-generic events, the generic parameter just needs to be dropped, so that it + /// looks like: `fn deposit_event() = default;`. + fn deposit_event() = default; /// This is your public interface. Be extremely careful. /// This is just a simple example of how to interact with the module from the external /// world. @@ -175,11 +197,17 @@ decl_module! { // without worrying about gameability or attack scenarios. // If you not specify `Result` explicitly as return value, it will be added automatically // for you and `Ok(())` will be returned. - fn set_dummy(new_value: T::Balance) { + fn set_dummy(#[compact] new_value: T::Balance) { // Put the new value into storage. >::put(new_value); } + // The signature could also look like: `fn on_initialise()` + fn on_initialise(_n: T::BlockNumber) { + // Anything that needs to be done at the start of the block. + // We don't do anything here. + } + // The signature could also look like: `fn on_finalise()` fn on_finalise(_n: T::BlockNumber) { // Anything that needs to be done at the end of the block. @@ -189,52 +217,6 @@ decl_module! { } } -/// An event in this module. Events are simple means of reporting specific conditions and -/// circumstances that have happened that users, Dapps and/or chain explorers would find -/// interesting and otherwise difficult to detect. -decl_event!( - pub enum Event where B = ::Balance { - // Just a normal `enum`, here's a dummy event to ensure it compiles. - /// Dummy event, just here so there's a generic type that's used. - Dummy(B), - } -); - -decl_storage! { - // A macro for the Storage trait, and its implementation, for this module. - // This allows for type-safe usage of the Substrate storage database, so you can - // keep things around between blocks. - trait Store for Module as Example { - // Any storage declarations of the form: - // `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` - // where `` is either: - // - `Type` (a basic value item); or - // - `map KeyType => ValueType` (a map item). - // - // Note that there are two optional modifiers for the storage type declaration. - // - `Foo: Option`: - // - `Foo::put(1); Foo::get()` returns `Some(1)`; - // - `Foo::kill(); Foo::get()` returns `None`. - // - `Foo: u32`: - // - `Foo::put(1); Foo::get()` returns `1`; - // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). - // e.g. Foo: u32; - // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; - // - // For basic value items, you'll get a type which implements - // `support::StorageValue`. For map items, you'll get a type which - // implements `support::StorageMap`. - // - // If they have a getter (`get(getter_name)`), then your module will come - // equipped with `fn getter_name() -> Type` for basic value items or - // `fn getter_name(key: KeyType) -> ValueType` for map items. - Dummy get(dummy) config(): Option; - - // this one uses the default, we'll demonstrate the usage of 'mutate' API. - Foo get(foo) config(): T::Balance; - } -} - // The main implementation block for the module. Functions here fall into three broad // categories: // - Public interface. These are functions that are `pub` and generally fall into inspector @@ -262,12 +244,14 @@ impl Module { mod tests { use super::*; + use srml_support::{impl_outer_origin, assert_ok}; use sr_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. use sr_primitives::{ - BuildStorage, traits::{BlakeTwo256, OnFinalise}, testing::{Digest, DigestItem, Header} + BuildStorage, traits::{BlakeTwo256, OnInitialise, OnFinalise, IdentityLookup}, + testing::{Digest, DigestItem, Header} }; impl_outer_origin! { @@ -287,15 +271,15 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); + type OnNewAccount = (); type Event = (); } impl Trait for Test { @@ -311,6 +295,8 @@ mod tests { t.extend(balances::GenesisConfig::::default().build_storage().unwrap().0); t.extend(GenesisConfig::{ dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], foo: 24, }.build_storage().unwrap().0); t.into() @@ -331,6 +317,7 @@ mod tests { assert_eq!(Example::dummy(), None); // Check that accumulate works when we Dummy has None in it. + >::on_initialise(2); assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); assert_eq!(Example::dummy(), Some(42)); }); diff --git a/srml/executive/Cargo.toml b/srml/executive/Cargo.toml index ee956e939972d7572ff19006de1b8d54594658ab..0165a37bb230eb64ca5ab8ce35efcf350280b761 100644 --- a/srml/executive/Cargo.toml +++ b/srml/executive/Cargo.toml @@ -2,31 +2,33 @@ name = "srml-executive" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] +hex-literal = "0.1.0" substrate-primitives = { path = "../../core/primitives" } -srml-balances = { path = "../balances" } +srml-indices = { path = "../indices" } +balances = { package = "srml-balances", path = "../balances" } +fees = { package = "srml-fees", path = "../fees" } +parity-codec-derive = { version = "3.1" } [features] default = ["std"] std = [ - "sr-std/std", + "rstd/std", "srml-support/std", - "serde/std", + "serde", "parity-codec/std", - "parity-codec-derive/std", - "sr-primitives/std", - "sr-io/std", - "srml-system/std", + "primitives/std", + "runtime_io/std", + "system/std", ] diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 005b8508db992388cbff8fefe5d0de6c9524861b..b6cc498f79dac29897a971681fe1a1b6943e0395 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,47 +18,28 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(test)] -#[macro_use] -extern crate parity_codec_derive; - -#[cfg_attr(test, macro_use)] -extern crate srml_support as runtime_support; - -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; -extern crate sr_io as runtime_io; -extern crate parity_codec as codec; -extern crate sr_primitives as primitives; -extern crate srml_system as system; - -#[cfg(test)] -#[macro_use] -extern crate hex_literal; - -#[cfg(test)] -extern crate substrate_primitives; - -#[cfg(test)] -extern crate srml_balances as balances; - use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::result; -use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise, - MakePayment, Hash, As, Digest}; -use runtime_support::Dispatchable; -use codec::{Codec, Encode}; +use primitives::traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise, + OnInitialise, Hash, As, Digest, NumberFor, Block as BlockT +}; +use srml_support::{Dispatchable, traits::ChargeBytesFee}; +use parity_codec::{Codec, Encode}; use system::extrinsics_root; use primitives::{ApplyOutcome, ApplyError}; use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity}; mod internal { + pub const MAX_TRANSACTIONS_SIZE: u32 = 4 * 1024 * 1024; + pub enum ApplyError { BadSignature(&'static str), Stale, Future, CantPay, + FullBlock, } pub enum ApplyOutcome { @@ -67,21 +48,46 @@ mod internal { } } -pub struct Executive< - System, - Block, - Context, - Payment, - Finalisation, ->(PhantomData<(System, Block, Context, Payment, Finalisation)>); +/// Something that can be used to execute a block. +pub trait ExecuteBlock { + /// Actually execute all transitioning for `block`. + fn execute_block(block: Block); + /// Execute all extrinsics like when executing a `block`, but with dropping intial and final checks. + fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec); +} + +pub struct Executive( + PhantomData<(System, Block, Context, Payment, AllModules)> +); impl< + System: system::Trait, + Block: traits::Block, Context: Default, + Payment: ChargeBytesFee, + AllModules: OnInitialise + OnFinalise, +> ExecuteBlock for Executive where + Block::Extrinsic: Checkable + Codec, + >::Checked: Applyable, + <>::Checked as Applyable>::Call: Dispatchable, + <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> +{ + fn execute_block(block: Block) { + Self::execute_block(block); + } + + fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec) { + Self::execute_extrinsics_without_checks(block_number, extrinsics); + } +} + +impl< System: system::Trait, Block: traits::Block, - Payment: MakePayment, - Finalisation: OnFinalise, -> Executive where + Context: Default, + Payment: ChargeBytesFee, + AllModules: OnInitialise + OnFinalise, +> Executive where Block::Extrinsic: Checkable + Codec, >::Checked: Applyable, <>::Checked as Applyable>::Call: Dispatchable, @@ -89,7 +95,12 @@ impl< { /// Start the execution of a particular block. pub fn initialise_block(header: &System::Header) { - >::initialise(header.number(), header.parent_hash(), header.extrinsics_root()); + Self::initialise_block_impl(header.number(), header.parent_hash(), header.extrinsics_root()); + } + + fn initialise_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash) { + >::initialise(block_number, parent_hash, extrinsics_root); + >::on_initialise(*block_number); } fn initial_checks(block: &Block) { @@ -115,23 +126,40 @@ impl< // any initial checks Self::initial_checks(&block); - // execute transactions + // execute extrinsics let (header, extrinsics) = block.deconstruct(); - extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note); - - // post-transactional book-keeping. - >::note_finished_extrinsics(); - Finalisation::on_finalise(*header.number()); + Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); // any final checks Self::final_checks(&header); } + /// Execute all extrinsics like when executing a `block`, but with dropping intial and final checks. + pub fn execute_extrinsics_without_checks(block_number: NumberFor, extrinsics: Vec) { + // Make the api happy, but maybe we should not set them at all. + let parent_hash = ::Hashing::hash(b"parent_hash"); + let extrinsics_root = ::Hashing::hash(b"extrinsics_root"); + + Self::initialise_block_impl(&block_number, &parent_hash, &extrinsics_root); + + // execute extrinsics + Self::execute_extrinsics_with_book_keeping(extrinsics, block_number); + } + + /// Execute given extrinsics and take care of post-extrinsics book-keeping + fn execute_extrinsics_with_book_keeping(extrinsics: Vec, block_number: NumberFor) { + extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note); + + // post-extrinsics book-keeping. + >::note_finished_extrinsics(); + >::on_finalise(block_number); + } + /// Finalise the block - it is up the caller to ensure that all header fields are valid /// except state-root. pub fn finalise_block() -> System::Header { >::note_finished_extrinsics(); - Finalisation::on_finalise(>::block_number()); + >::on_finalise(>::block_number()); // setup extrinsics >::derive_extrinsics(); @@ -144,34 +172,40 @@ impl< pub fn apply_extrinsic(uxt: Block::Extrinsic) -> result::Result { let encoded = uxt.encode(); let encoded_len = encoded.len(); - >::note_extrinsic(encoded); - match Self::apply_extrinsic_no_note_with_len(uxt, encoded_len) { + match Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) { Ok(internal::ApplyOutcome::Success) => Ok(ApplyOutcome::Success), Ok(internal::ApplyOutcome::Fail(_)) => Ok(ApplyOutcome::Fail), Err(internal::ApplyError::CantPay) => Err(ApplyError::CantPay), Err(internal::ApplyError::BadSignature(_)) => Err(ApplyError::BadSignature), Err(internal::ApplyError::Stale) => Err(ApplyError::Stale), Err(internal::ApplyError::Future) => Err(ApplyError::Future), + Err(internal::ApplyError::FullBlock) => Err(ApplyError::FullBlock), } } /// Apply an extrinsic inside the block execution function. fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { let l = uxt.encode().len(); - match Self::apply_extrinsic_no_note_with_len(uxt, l) { + match Self::apply_extrinsic_with_len(uxt, l, None) { Ok(internal::ApplyOutcome::Success) => (), Ok(internal::ApplyOutcome::Fail(e)) => runtime_io::print(e), Err(internal::ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), Err(internal::ApplyError::BadSignature(_)) => panic!("All extrinsics should be properly signed"), Err(internal::ApplyError::Stale) | Err(internal::ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), + Err(internal::ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), } } /// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash. - fn apply_extrinsic_no_note_with_len(uxt: Block::Extrinsic, encoded_len: usize) -> result::Result { + fn apply_extrinsic_with_len(uxt: Block::Extrinsic, encoded_len: usize, to_note: Option>) -> result::Result { // Verify the signature is good. let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?; + // Check the size of the block if that extrinsic is applied. + if >::all_extrinsics_len() + encoded_len as u32 > internal::MAX_TRANSACTIONS_SIZE { + return Err(internal::ApplyError::FullBlock); + } + if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // check index let expected_index = >::account_nonce(sender); @@ -180,7 +214,7 @@ impl< ) } // pay any fees. - Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; + Payment::charge_base_bytes_fee(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; // AUDIT: Under no circumstances may this function panic from here onwards. @@ -188,12 +222,21 @@ impl< >::inc_account_nonce(sender); } + // make sure to `note_extrinsic` only after we know it's going to be executed + // to prevent it from leaking in storage. + if let Some(encoded) = to_note { + >::note_extrinsic(encoded); + } + // decode parameters and dispatch let (f, s) = xt.deconstruct(); let r = f.dispatch(s.into()); - >::note_applied_extrinsic(&r); + >::note_applied_extrinsic(&r, encoded_len as u32); - r.map(|_| internal::ApplyOutcome::Success).or_else(|e| Ok(internal::ApplyOutcome::Fail(e))) + r.map(|_| internal::ApplyOutcome::Success).or_else(|e| match e { + primitives::BLOCK_FULL => Err(internal::ApplyError::FullBlock), + e => Ok(internal::ApplyOutcome::Fail(e)) + }) } fn final_checks(header: &System::Header) { @@ -223,31 +266,37 @@ impl< /// /// Changes made to the storage should be discarded. pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { + // Note errors > 0 are from ApplyError + const UNKNOWN_ERROR: i8 = -127; + const MISSING_SENDER: i8 = -20; + const INVALID_INDEX: i8 = -10; + let encoded_len = uxt.encode().len(); let xt = match uxt.check(&Default::default()) { // Checks out. Carry on. Ok(xt) => xt, // An unknown account index implies that the transaction may yet become valid. - Err("invalid account index") => return TransactionValidity::Unknown, + Err("invalid account index") => return TransactionValidity::Unknown(INVALID_INDEX), // Technically a bad signature could also imply an out-of-date account index, but // that's more of an edge case. - Err(_) => return TransactionValidity::Invalid, + Err(primitives::BAD_SIGNATURE) => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), + Err(_) => return TransactionValidity::Invalid(UNKNOWN_ERROR), }; if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // pay any fees. - if Payment::make_payment(sender, encoded_len).is_err() { - return TransactionValidity::Invalid + if Payment::charge_base_bytes_fee(sender, encoded_len).is_err() { + return TransactionValidity::Invalid(ApplyError::CantPay as i8) } // check index let mut expected_index = >::account_nonce(sender); if index < &expected_index { - return TransactionValidity::Invalid + return TransactionValidity::Invalid(ApplyError::Stale as i8) } if *index > expected_index + As::sa(256) { - return TransactionValidity::Unknown + return TransactionValidity::Unknown(ApplyError::Future as i8) } let mut deps = Vec::new(); @@ -263,7 +312,11 @@ impl< longevity: TransactionLongevity::max_value(), } } else { - return TransactionValidity::Invalid + return TransactionValidity::Invalid(if xt.sender().is_none() { + MISSING_SENDER + } else { + INVALID_INDEX + }) } } } @@ -275,9 +328,12 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::BuildStorage; - use primitives::traits::{Header as HeaderT, BlakeTwo256}; + use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, DigestItem, Header, Block}; + use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event}; use system; + use fees; + use hex_literal::{hex, hex_impl}; impl_outer_origin! { pub enum Origin for Runtime { @@ -286,7 +342,7 @@ mod tests { impl_outer_event!{ pub enum MetaEvent for Runtime { - balances, + balances, fees, } } @@ -301,34 +357,40 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; type Log = DigestItem; } impl balances::Trait for Runtime { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); + type OnNewAccount = (); + type Event = MetaEvent; + } + impl fees::Trait for Runtime { type Event = MetaEvent; + type TransferAsset = balances::Module; } type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, balances::ChainContext, balances::Module, ()>; + type Executive = super::Executive, system::ChainContext, fees::Module, ()>; #[test] fn balance_transfer_dispatch_works() { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig:: { balances: vec![(1, 111)], - transaction_base_fee: 10, - transaction_byte_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, - reclaim_rebate: 0, + vesting: vec![], }.build_storage().unwrap().0); - let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2.into(), 69.into())); + t.extend(fees::GenesisConfig:: { + transaction_base_fee: 10, + transaction_byte_fee: 0, + }.build_storage().unwrap().0); + let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2, 69)); let mut t = runtime_io::TestExternalities::::new(t); with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), @@ -352,7 +414,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("d9e26179ed13b3df01e71ad0bf622d56f2066a63e04762a83c0ae9deeb4da1d0").into(), + state_root: hex!("6651861f40a8f42c033b3e937cb3513e6dbaf4be6bafb1561a19f884be3f58dd").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -386,7 +448,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("d9e26179ed13b3df01e71ad0bf622d56f2066a63e04762a83c0ae9deeb4da1d0").into(), + state_root: hex!("6651861f40a8f42c033b3e937cb3513e6dbaf4be6bafb1561a19f884be3f58dd").into(), extrinsics_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }, @@ -398,11 +460,42 @@ mod tests { #[test] fn bad_extrinsic_not_inserted() { let mut t = new_test_ext(); - let xt = primitives::testing::TestXt(Some(1), 42, Call::transfer(33.into(), 69.into())); + let xt = primitives::testing::TestXt(Some(1), 42, Call::transfer(33, 69)); with_externalities(&mut t, || { Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); assert!(Executive::apply_extrinsic(xt).is_err()); assert_eq!(>::extrinsic_index(), Some(0)); }); } + + #[test] + fn block_size_limit_enforced() { + let run_test = |should_fail: bool| { + let mut t = new_test_ext(); + let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(33, 69)); + let xt2 = primitives::testing::TestXt(Some(1), 1, Call::transfer(33, 69)); + let encoded = xt2.encode(); + let len = if should_fail { (internal::MAX_TRANSACTIONS_SIZE - 1) as usize } else { encoded.len() }; + with_externalities(&mut t, || { + Executive::initialise_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default())); + assert_eq!(>::all_extrinsics_len(), 0); + + Executive::apply_extrinsic(xt).unwrap(); + let res = Executive::apply_extrinsic_with_len(xt2, len, Some(encoded)); + + if should_fail { + assert!(res.is_err()); + assert_eq!(>::all_extrinsics_len(), 28); + assert_eq!(>::extrinsic_index(), Some(1)); + } else { + assert!(res.is_ok()); + assert_eq!(>::all_extrinsics_len(), 56); + assert_eq!(>::extrinsic_index(), Some(2)); + } + }); + }; + + run_test(false); + run_test(true); + } } diff --git a/srml/fees/Cargo.toml b/srml/fees/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..2bb4474ce6e8d55f687e7c1ec6647f93d0ba02a6 --- /dev/null +++ b/srml/fees/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "srml-fees" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +srml-support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[features] +default = ["std"] +std = [ + "serde", + "parity-codec/std", + "parity-codec-derive/std", + "primitives/std", + "rstd/std", + "runtime_io/std", + "runtime_primitives/std", + "srml-support/std", + "system/std", +] diff --git a/srml/fees/src/lib.rs b/srml/fees/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..09e32db9b0d4b4c10a0de68792af265e17dce731 --- /dev/null +++ b/srml/fees/src/lib.rs @@ -0,0 +1,117 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Handles all transaction fee related operations + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use srml_support::{ + dispatch::Result, StorageMap, decl_event, decl_storage, decl_module, + traits::{ArithmeticType, ChargeBytesFee, ChargeFee, TransferAsset, WithdrawReason} +}; +use runtime_primitives::traits::{ + As, CheckedAdd, CheckedSub, CheckedMul, Zero +}; +use system; + +mod mock; +mod tests; + +type AssetOf = <::TransferAsset as ArithmeticType>::Type; + +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// A function does the asset transfer between accounts + type TransferAsset: ArithmeticType + TransferAsset>; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + fn on_finalise() { + let extrinsic_count = >::extrinsic_count(); + (0..extrinsic_count).for_each(|index| { + // Deposit `Charged` event if some amount of fee charged. + let fee = >::take(index); + if !fee.is_zero() { + Self::deposit_event(RawEvent::Charged(index, fee)); + } + }); + } + } +} + +decl_event!( + pub enum Event where Amount = AssetOf { + /// Fee charged (extrinsic_index, fee_amount) + Charged(u32, Amount), + } +); + +decl_storage! { + trait Store for Module as Fees { + /// The fee to be paid for making a transaction; the base. + pub TransactionBaseFee get(transaction_base_fee) config(): AssetOf; + /// The fee to be paid for making a transaction; the per-byte portion. + pub TransactionByteFee get(transaction_byte_fee) config(): AssetOf; + + /// The `extrinsic_index => accumulated_fees` map, containing records to + /// track the overall charged fees for each transaction. + /// + /// All records should be removed at finalise stage. + CurrentTransactionFee get(current_transaction_fee): map u32 => AssetOf; + } +} + +impl ChargeBytesFee for Module { + fn charge_base_bytes_fee(transactor: &T::AccountId, encoded_len: usize) -> Result { + let bytes_fee = Self::transaction_byte_fee().checked_mul( + & as As>::sa(encoded_len as u64) + ).ok_or_else(|| "bytes fee overflow")?; + let overall = Self::transaction_base_fee().checked_add(&bytes_fee).ok_or_else(|| "bytes fee overflow")?; + Self::charge_fee(transactor, overall) + } +} + +impl ChargeFee for Module { + type Amount = AssetOf; + + fn charge_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { + let extrinsic_index = >::extrinsic_index().ok_or_else(|| "no extrinsic index found")?; + let current_fee = Self::current_transaction_fee(extrinsic_index); + let new_fee = current_fee.checked_add(&amount).ok_or_else(|| "fee got overflow after charge")?; + + T::TransferAsset::withdraw(transactor, amount, WithdrawReason::TransactionPayment)?; + + >::insert(extrinsic_index, new_fee); + Ok(()) + } + + fn refund_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { + let extrinsic_index = >::extrinsic_index().ok_or_else(|| "no extrinsic index found")?; + let current_fee = Self::current_transaction_fee(extrinsic_index); + let new_fee = current_fee.checked_sub(&amount).ok_or_else(|| "fee got underflow after refund")?; + + T::TransferAsset::deposit(transactor, amount)?; + + >::insert(extrinsic_index, new_fee); + Ok(()) + } +} diff --git a/srml/fees/src/mock.rs b/srml/fees/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..7f6c715f4b8bbeceec7e3656b5ea400c84bf8834 --- /dev/null +++ b/srml/fees/src/mock.rs @@ -0,0 +1,115 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use runtime_primitives::BuildStorage; +use runtime_primitives::{ + traits::{IdentityLookup, BlakeTwo256}, + testing::{Digest, DigestItem, Header}, +}; +use primitives::{H256, Blake2Hasher}; +use runtime_io; +use srml_support::{ + impl_outer_origin, impl_outer_event, + traits::{ArithmeticType, TransferAsset, WithdrawReason} +}; +use crate::{GenesisConfig, Module, Trait, system}; + +impl_outer_origin!{ + pub enum Origin for Test {} +} + +mod fees { + pub use crate::Event; +} + +impl_outer_event!{ + pub enum TestEvent for Test { + fees, + } +} + +pub struct TransferAssetMock; + +impl TransferAsset for TransferAssetMock { + type Amount = u64; + + fn transfer(_: &AccountId, _: &AccountId, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } + fn withdraw(_: &AccountId, _: Self::Amount, _: WithdrawReason) -> Result<(), &'static str> { Ok(()) } + fn deposit(_: &AccountId, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } +} + +impl ArithmeticType for TransferAssetMock { + type Type = u64; +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; +impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type Log = DigestItem; +} +impl Trait for Test { + type Event = TestEvent; + type TransferAsset = TransferAssetMock; +} + +pub type System = system::Module; +pub type Fees = Module; + +pub struct ExtBuilder { + transaction_base_fee: u64, + transaction_byte_fee: u64, +} +impl Default for ExtBuilder { + fn default() -> Self { + Self { + transaction_base_fee: 0, + transaction_byte_fee: 0, + } + } +} +impl ExtBuilder { + pub fn transaction_base_fee(mut self, transaction_base_fee: u64) -> Self { + self.transaction_base_fee = transaction_base_fee; + self + } + pub fn transaction_byte_fee(mut self, transaction_byte_fee: u64) -> Self { + self.transaction_byte_fee = transaction_byte_fee; + self + } + pub fn build(self) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; + t.extend(GenesisConfig:: { + transaction_base_fee: self.transaction_base_fee, + transaction_byte_fee: self.transaction_byte_fee, + }.build_storage().unwrap().0); + t.into() + } +} diff --git a/srml/fees/src/tests.rs b/srml/fees/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..a1c96570629e85d2b5c8df5a8bed4fc314792803 --- /dev/null +++ b/srml/fees/src/tests.rs @@ -0,0 +1,174 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +#![cfg(test)] + +use super::*; +use runtime_io::with_externalities; +use runtime_primitives::traits::{OnFinalise}; +use system::{EventRecord, Phase}; + +use mock::{Fees, System, ExtBuilder}; +use srml_support::{assert_ok, assert_err}; + +#[test] +fn charge_base_bytes_fee_should_work() { + with_externalities( + &mut ExtBuilder::default() + .transaction_base_fee(3) + .transaction_byte_fee(5) + .build(), + || { + System::set_extrinsic_index(0); + assert_ok!(Fees::charge_base_bytes_fee(&0, 7)); + assert_eq!(Fees::current_transaction_fee(0), 3 + 5 * 7); + + System::set_extrinsic_index(1); + assert_ok!(Fees::charge_base_bytes_fee(&0, 11)); + assert_eq!(Fees::current_transaction_fee(1), 3 + 5 * 11); + + System::set_extrinsic_index(3); + assert_ok!(Fees::charge_base_bytes_fee(&0, 13)); + assert_eq!(Fees::current_transaction_fee(3), 3 + 5 * 13); + } + ); +} + +#[test] +fn charge_base_bytes_fee_should_not_work_if_bytes_fee_overflow() { + // bytes fee overflows. + with_externalities( + &mut ExtBuilder::default() + .transaction_base_fee(0) + .transaction_byte_fee(u64::max_value()) + .build(), + || { + System::set_extrinsic_index(0); + assert_err!( + Fees::charge_base_bytes_fee(&0, 2), + "bytes fee overflow" + ); + } + ); +} + +#[test] +fn charge_base_bytes_fee_should_not_work_if_overall_fee_overflow() { + // bytes fee doesn't overflow, but overall fee (bytes_fee + base_fee) does + with_externalities( + &mut ExtBuilder::default() + .transaction_base_fee(u64::max_value()) + .transaction_byte_fee(1) + .build(), + || { + System::set_extrinsic_index(0); + assert_err!( + Fees::charge_base_bytes_fee(&0, 1), + "bytes fee overflow" + ); + } + ); +} + +#[test] +fn charge_fee_should_work() { + with_externalities(&mut ExtBuilder::default().build(), || { + System::set_extrinsic_index(0); + assert_ok!(Fees::charge_fee(&0, 2)); + assert_ok!(Fees::charge_fee(&0, 3)); + assert_eq!(Fees::current_transaction_fee(0), 2 + 3); + + System::set_extrinsic_index(2); + assert_ok!(Fees::charge_fee(&0, 5)); + assert_ok!(Fees::charge_fee(&0, 7)); + assert_eq!(Fees::current_transaction_fee(2), 5 + 7); + }); +} + +#[test] +fn charge_fee_when_overflow_should_not_work() { + with_externalities(&mut ExtBuilder::default().build(), || { + System::set_extrinsic_index(0); + assert_ok!(Fees::charge_fee(&0, u64::max_value())); + assert_err!(Fees::charge_fee(&0, 1), "fee got overflow after charge"); + }); +} + +#[test] +fn refund_fee_should_work() { + with_externalities(&mut ExtBuilder::default().build(), || { + System::set_extrinsic_index(0); + assert_ok!(Fees::charge_fee(&0, 5)); + assert_ok!(Fees::refund_fee(&0, 3)); + assert_eq!(Fees::current_transaction_fee(0), 5 - 3); + }); +} + +#[test] +fn refund_fee_when_underflow_should_not_work() { + with_externalities(&mut ExtBuilder::default().build(), || { + System::set_extrinsic_index(0); + assert_err!(Fees::refund_fee(&0, 1), "fee got underflow after refund"); + }); +} + +#[test] +fn on_finalise_should_work() { + with_externalities(&mut ExtBuilder::default().build(), || { + // charge fees in extrinsic index 3 + System::set_extrinsic_index(3); + assert_ok!(Fees::charge_fee(&0, 1)); + System::note_applied_extrinsic(&Ok(()), 1); + // charge fees in extrinsic index 5 + System::set_extrinsic_index(5); + assert_ok!(Fees::charge_fee(&0, 1)); + System::note_applied_extrinsic(&Ok(()), 1); + System::note_finished_extrinsics(); + + // `current_transaction_fee`, `extrinsic_count` should be as expected. + assert_eq!(Fees::current_transaction_fee(3), 1); + assert_eq!(Fees::current_transaction_fee(5), 1); + assert_eq!(System::extrinsic_count(), 5 + 1); + + >::on_finalise(1); + + // When finalised, `CurrentTransactionFee` records should be cleared. + assert_eq!(Fees::current_transaction_fee(3), 0); + assert_eq!(Fees::current_transaction_fee(5), 0); + + // When finalised, if any fee charged in a extrinsic, a `Charged` event should be deposited + // for it. + let fee_charged_events: Vec> = System::events() + .into_iter() + .filter(|e| match e.event { + mock::TestEvent::fees(RawEvent::Charged(_, _)) => return true, + _ => return false, + }) + .collect(); + assert_eq!(fee_charged_events, vec![ + EventRecord { + phase: Phase::Finalization, + event: RawEvent::Charged(3, 1).into(), + }, + EventRecord { + phase: Phase::Finalization, + event: RawEvent::Charged(5, 1).into(), + }, + ]); + }); +} diff --git a/srml/finality-tracker/Cargo.toml b/srml/finality-tracker/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..22691e1aa7b14f5538f749edb6261c6fd3d13bc7 --- /dev/null +++ b/srml/finality-tracker/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "srml-finality-tracker" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", default-features = false } +serde_derive = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +srml-support = { path = "../support", default-features = false } +srml-system = { path = "../system", default-features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../core/primitives", default-features = false } +sr-io = { path = "../../core/sr-io", default-features = false } +lazy_static = "1.0" +parking_lot = "0.7" + +[features] +default = ["std"] +std = [ + "serde/std", + "serde_derive", + "parity-codec/std", + "rstd/std", + "srml-support/std", + "primitives/std", + "srml-system/std", + "inherents/std", +] diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f417881f7482d337f66f5e9a931a70216c547ec --- /dev/null +++ b/srml/finality-tracker/src/lib.rs @@ -0,0 +1,385 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! SRML module that tracks the last finalized block, as perceived by block authors. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +extern crate srml_support; + +use inherents::{ + RuntimeString, InherentIdentifier, ProvideInherent, + InherentData, MakeFatalError, +}; +use srml_support::StorageValue; +use primitives::traits::{As, One, Zero}; +use rstd::{prelude::*, result, cmp, vec}; +use parity_codec::Decode; +use srml_system::{ensure_inherent, Trait as SystemTrait}; + +#[cfg(feature = "std")] +use parity_codec::Encode; + +const DEFAULT_WINDOW_SIZE: u64 = 101; +const DEFAULT_DELAY: u64 = 1000; + +/// The identifier for the `finalnum` inherent. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"finalnum"; + +/// Auxiliary trait to extract finalized inherent data. +pub trait FinalizedInherentData { + /// Get finalized inherent data. + fn finalized_number(&self) -> Result; +} + +impl FinalizedInherentData for InherentData { + fn finalized_number(&self) -> Result { + self.get_data(&INHERENT_IDENTIFIER) + .and_then(|r| r.ok_or_else(|| "Finalized number inherent data not found".into())) + } +} + +/// Provider for inherent data. +#[cfg(feature = "std")] +pub struct InherentDataProvider { + inner: F, + _marker: std::marker::PhantomData, +} + +#[cfg(feature = "std")] +impl InherentDataProvider { + pub fn new(final_oracle: F) -> Self { + InherentDataProvider { inner: final_oracle, _marker: Default::default() } + } +} + +#[cfg(feature = "std")] +impl inherents::ProvideInherentData for InherentDataProvider + where F: Fn() -> Result +{ + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { + (self.inner)() + .and_then(|n| inherent_data.put_data(INHERENT_IDENTIFIER, &n)) + } + + fn error_to_string(&self, _error: &[u8]) -> Option { + Some(format!("no further information")) + } +} + + +pub trait Trait: SystemTrait { + /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. + type OnFinalizationStalled: OnFinalizationStalled; +} + +decl_storage! { + trait Store for Module as Timestamp { + /// Recent hints. + RecentHints get(recent_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + /// Ordered recent hints. + OrderedHints get(ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + /// The median. + Median get(median) build(|_| T::BlockNumber::zero()): T::BlockNumber; + /// The number of recent samples to keep from this chain. Default is n-100 + pub WindowSize get(window_size) config(window_size): T::BlockNumber = T::BlockNumber::sa(DEFAULT_WINDOW_SIZE); + /// The delay after which point things become suspicious. + pub ReportLatency get(report_latency) config(report_latency): T::BlockNumber = T::BlockNumber::sa(DEFAULT_DELAY); + + /// Final hint to apply in the block. `None` means "same as parent". + Update: Option; + + // when initialized through config this is set in the beginning. + Initialized get(initialized) build(|_| false): bool; + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Hint that the author of this block thinks the best finalized + /// block is the given number. + fn final_hint(origin, #[compact] hint: T::BlockNumber) { + ensure_inherent(origin)?; + assert!(!::Update::exists(), "Final hint must be updated only once in the block"); + assert!( + srml_system::Module::::block_number() >= hint, + "Finalized height above block number", + ); + ::Update::put(hint); + } + + fn on_finalise() { + Self::update_hint(::Update::take()) + } + } +} + +impl Module { + fn update_hint(hint: Option) { + if !Self::initialized() { + ::RecentHints::put(vec![T::BlockNumber::zero()]); + ::OrderedHints::put(vec![T::BlockNumber::zero()]); + ::Median::put(T::BlockNumber::zero()); + + ::Initialized::put(true); + } + + let mut recent = Self::recent_hints(); + let mut ordered = Self::ordered_hints(); + let window_size = cmp::max(T::BlockNumber::one(), Self::window_size()); + + let hint = hint.unwrap_or_else(|| recent.last() + .expect("always at least one recent sample; qed").clone() + ); + + // prune off the front of the list -- typically 1 except for when + // the sample size has just been shrunk. + { + // take into account the item we haven't pushed yet. + let to_prune = (recent.len() + 1).saturating_sub(window_size.as_() as usize); + + for drained in recent.drain(..to_prune) { + let idx = ordered.binary_search(&drained) + .expect("recent and ordered contain the same items; qed"); + + ordered.remove(idx); + } + } + + // find the position in the ordered list where the new item goes. + let ordered_idx = ordered.binary_search(&hint) + .unwrap_or_else(|idx| idx); + + ordered.insert(ordered_idx, hint); + recent.push(hint); + + let two = T::BlockNumber::one() + T::BlockNumber::one(); + + let median = { + let len = ordered.len(); + assert!(len > 0, "pruning dictated by window_size which is always saturated at 1; qed"); + + if len % 2 == 0 { + let a = ordered[len / 2]; + let b = ordered[(len / 2) - 1]; + + // compute average. + (a + b) / two + } else { + ordered[len / 2] + } + }; + + let our_window_size = recent.len(); + + ::RecentHints::put(recent); + ::OrderedHints::put(ordered); + ::Median::put(median); + + if T::BlockNumber::sa(our_window_size as u64) == window_size { + let now = srml_system::Module::::block_number(); + let latency = Self::report_latency(); + + // the delay is the latency plus half the window size. + let delay = latency + (window_size / two); + // median may be at most n - delay + if median + delay <= now { + T::OnFinalizationStalled::on_stalled(window_size - T::BlockNumber::one()); + } + } + } +} + +/// Called when finalization stalled at a given number. +pub trait OnFinalizationStalled { + /// The parameter here is how many more blocks to wait before applying + /// changes triggered by finality stalling. + fn on_stalled(further_wait: N); +} + +macro_rules! impl_on_stalled { + () => ( + impl OnFinalizationStalled for () { + fn on_stalled(_: N) {} + } + ); + + ( $($t:ident)* ) => { + impl),*> OnFinalizationStalled for ($($t,)*) { + fn on_stalled(further_wait: NUM) { + $($t::on_stalled(further_wait.clone());)* + } + } + } +} + +for_each_tuple!(impl_on_stalled); + +impl ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError<()>; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + let final_num = + data.finalized_number().expect("Gets and decodes final number inherent data"); + + // make hint only when not same as last to avoid bloat. + Self::recent_hints().last().and_then(|last| if last == &final_num { + None + } else { + Some(Call::final_hint(final_num)) + }) + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sr_io::{with_externalities, TestExternalities}; + use substrate_primitives::H256; + use primitives::BuildStorage; + use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalise, Header as HeaderT}; + use primitives::testing::{Digest, DigestItem, Header}; + use srml_support::impl_outer_origin; + use srml_system as system; + use lazy_static::lazy_static; + use parking_lot::Mutex; + + #[derive(Clone, PartialEq, Debug)] + pub struct StallEvent { + at: u64, + further_wait: u64, + } + + macro_rules! make_test_context { + () => { + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type Log = DigestItem; + } + + type System = system::Module; + + lazy_static! { + static ref NOTIFICATIONS: Mutex> = Mutex::new(Vec::new()); + } + + pub struct StallTracker; + impl OnFinalizationStalled for StallTracker { + fn on_stalled(further_wait: u64) { + let now = System::block_number(); + NOTIFICATIONS.lock().push(StallEvent { at: now, further_wait }); + } + } + + impl Trait for Test { + type OnFinalizationStalled = StallTracker; + } + + type FinalityTracker = Module; + } + } + + #[test] + fn median_works() { + make_test_context!(); + let t = system::GenesisConfig::::default().build_storage().unwrap().0; + + with_externalities(&mut TestExternalities::new(t), || { + FinalityTracker::update_hint(Some(500)); + assert_eq!(FinalityTracker::median(), 250); + assert!(NOTIFICATIONS.lock().is_empty()); + }); + } + + #[test] + fn notifies_when_stalled() { + make_test_context!(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; + t.extend(GenesisConfig:: { + window_size: 11, + report_latency: 100 + }.build_storage().unwrap().0); + + with_externalities(&mut TestExternalities::new(t), || { + let mut parent_hash = System::parent_hash(); + for i in 2..106 { + System::initialise(&i, &parent_hash, &Default::default()); + FinalityTracker::on_finalise(i); + let hdr = System::finalise(); + parent_hash = hdr.hash(); + } + + assert_eq!( + NOTIFICATIONS.lock().to_vec(), + vec![StallEvent { at: 105, further_wait: 10 }] + ) + }); + } + + #[test] + fn recent_notifications_prevent_stalling() { + make_test_context!(); + let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; + t.extend(GenesisConfig:: { + window_size: 11, + report_latency: 100 + }.build_storage().unwrap().0); + + with_externalities(&mut TestExternalities::new(t), || { + let mut parent_hash = System::parent_hash(); + for i in 2..106 { + System::initialise(&i, &parent_hash, &Default::default()); + assert_ok!(FinalityTracker::dispatch( + Call::final_hint(i-1), + Origin::INHERENT, + )); + FinalityTracker::on_finalise(i); + let hdr = System::finalise(); + parent_hash = hdr.hash(); + } + + assert!(NOTIFICATIONS.lock().is_empty()); + }); + } +} diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml index 60c576895e58d8549f697546698fafce0b7fb1f0..b7cc5dc231f3d7f3075db9710644574d73b7b43c 100644 --- a/srml/grandpa/Cargo.toml +++ b/srml/grandpa/Cargo.toml @@ -2,34 +2,39 @@ name = "srml-grandpa" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +#hex-literal = "0.1.0" +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } substrate-finality-grandpa-primitives = { path = "../../core/finality-grandpa/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-session = { path = "../session", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +session = { package = "srml-session", path = "../session", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } +finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "serde_derive", "parity-codec/std", "substrate-primitives/std", "substrate-finality-grandpa-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-system/std", - "srml-session/std", + "primitives/std", + "system/std", + "consensus/std", + "session/std", + "finality-tracker/std", ] diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index de2d10b0f1b72c038ffda095014db8de4c8bb8d6..0715ce034ad7b3505f4e6fac857e59bc80606480 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,43 +27,24 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[allow(unused_imports)] -#[macro_use] -extern crate sr_std as rstd; - -#[macro_use] -extern crate srml_support as runtime_support; - -#[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; - -extern crate parity_codec; -#[macro_use] -extern crate parity_codec_derive; - -extern crate sr_primitives as primitives; -extern crate parity_codec as codec; -extern crate srml_system as system; -extern crate srml_session as session; -extern crate substrate_primitives; - -#[cfg(test)] -extern crate sr_io as runtime_io; - // re-export since this is necessary for `impl_apis` in runtime. -pub extern crate substrate_finality_grandpa_primitives as fg_primitives; +pub use substrate_finality_grandpa_primitives as fg_primitives; +#[cfg(feature = "std")] +use serde_derive::Serialize; use rstd::prelude::*; +use parity_codec as codec; +use codec::{Encode, Decode}; use fg_primitives::ScheduledChange; -use runtime_support::Parameter; -use runtime_support::dispatch::Result; -use runtime_support::storage::StorageValue; -use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::{CurrentHeight, Convert}; -use substrate_primitives::AuthorityId; +use srml_support::{Parameter, decl_event, decl_storage, decl_module}; +use srml_support::dispatch::Result; +use srml_support::storage::StorageValue; +use srml_support::storage::unhashed::StorageVec; +use primitives::traits::CurrentHeight; +use substrate_primitives::ed25519; use system::ensure_signed; use primitives::traits::MaybeSerializeDebug; +use ed25519::Public as AuthorityId; mod mock; mod tests; @@ -71,7 +52,7 @@ mod tests; struct AuthorityStorageVec(rstd::marker::PhantomData); impl StorageVec for AuthorityStorageVec { type Item = (S, u64); - const PREFIX: &'static [u8] = ::fg_primitives::well_known_keys::AUTHORITY_PREFIX; + const PREFIX: &'static [u8] = crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX; } /// The log type of this crate, projected from module trait type. @@ -84,6 +65,8 @@ pub type Log = RawLog< pub trait GrandpaChangeSignal { /// Try to cast the log entry as a contained signal. fn as_signal(&self) -> Option>; + /// Try to cast the log entry as a contained forced signal. + fn as_forced_signal(&self) -> Option<(N, ScheduledChange)>; } /// A logs in this module. @@ -91,15 +74,28 @@ pub trait GrandpaChangeSignal { #[derive(Encode, Decode, PartialEq, Eq, Clone)] pub enum RawLog { /// Authorities set change has been signalled. Contains the new set of authorities - /// and the delay in blocks before applying. + /// and the delay in blocks _to finalize_ before applying. AuthoritiesChangeSignal(N, Vec<(SessionKey, u64)>), + /// A forced authorities set change. Contains in this order: the median last + /// finalized block when the change was signaled, the delay in blocks _to import_ + /// before applying and the new set of authorities. + ForcedAuthoritiesChangeSignal(N, N, Vec<(SessionKey, u64)>), } impl RawLog { /// Try to cast the log entry as a contained signal. pub fn as_signal(&self) -> Option<(N, &[(SessionKey, u64)])> { match *self { - RawLog::AuthoritiesChangeSignal(ref n, ref signal) => Some((n.clone(), signal)), + RawLog::AuthoritiesChangeSignal(ref delay, ref signal) => Some((delay.clone(), signal)), + RawLog::ForcedAuthoritiesChangeSignal(_, _, _) => None, + } + } + + /// Try to cast the log entry as a contained forced signal. + pub fn as_forced_signal(&self) -> Option<(N, N, &[(SessionKey, u64)])> { + match *self { + RawLog::ForcedAuthoritiesChangeSignal(ref median, ref delay, ref signal) => Some((median.clone(), delay.clone(), signal)), + RawLog::AuthoritiesChangeSignal(_, _) => None, } } } @@ -116,6 +112,16 @@ impl GrandpaChangeSignal for RawLog .collect(), }) } + + fn as_forced_signal(&self) -> Option<(N, ScheduledChange)> { + RawLog::as_forced_signal(self).map(|(median, delay, next_authorities)| (median, ScheduledChange { + delay, + next_authorities: next_authorities.iter() + .cloned() + .map(|(k, w)| (k.into(), w)) + .collect(), + })) + } } pub trait Trait: system::Trait { @@ -129,8 +135,21 @@ pub trait Trait: system::Trait { type Event: From> + Into<::Event>; } -/// A stored pending change. +/// A stored pending change, old format. +// TODO: remove shim +// https://github.com/paritytech/substrate/issues/1614 #[derive(Encode, Decode)] +pub struct OldStoredPendingChange { + /// The block number this was scheduled at. + pub scheduled_at: N, + /// The delay in blocks until it will be applied. + pub delay: N, + /// The next authority set. + pub next_authorities: Vec<(SessionKey, u64)>, +} + +/// A stored pending change. +#[derive(Encode)] pub struct StoredPendingChange { /// The block number this was scheduled at. pub scheduled_at: N, @@ -138,6 +157,23 @@ pub struct StoredPendingChange { pub delay: N, /// The next authority set. pub next_authorities: Vec<(SessionKey, u64)>, + /// If defined it means the change was forced and the given block number + /// indicates the median last finalized block when the change was signaled. + pub forced: Option, +} + +impl Decode for StoredPendingChange { + fn decode(value: &mut I) -> Option { + let old = OldStoredPendingChange::decode(value)?; + let forced = >::decode(value).unwrap_or(None); + + Some(StoredPendingChange { + scheduled_at: old.scheduled_at, + delay: old.delay, + next_authorities: old.next_authorities, + forced, + }) + } } /// GRANDPA events. @@ -152,22 +188,24 @@ decl_storage! { trait Store for Module as GrandpaFinality { // Pending change: (signalled at, scheduled change). PendingChange get(pending_change): Option>; + // next block number where we can force a change. + NextForced get(next_forced): Option; } add_extra_genesis { config(authorities): Vec<(T::SessionKey, u64)>; - build(|storage: &mut primitives::StorageMap, _: &mut primitives::ChildrenStorageMap, config: &GenesisConfig| { + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { use codec::{Encode, KeyedVec}; let auth_count = config.authorities.len() as u32; config.authorities.iter().enumerate().for_each(|(i, v)| { storage.insert((i as u32).to_keyed_vec( - ::fg_primitives::well_known_keys::AUTHORITY_PREFIX), + crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX), v.encode() ); }); storage.insert( - ::fg_primitives::well_known_keys::AUTHORITY_COUNT.to_vec(), + crate::fg_primitives::well_known_keys::AUTHORITY_COUNT.to_vec(), auth_count.encode(), ); }); @@ -176,21 +214,29 @@ decl_storage! { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Report some misbehaviour. fn report_misbehavior(origin, _report: Vec) { ensure_signed(origin)?; - // TODO: https://github.com/paritytech/substrate/issues/1112 + // FIXME: https://github.com/paritytech/substrate/issues/1112 } fn on_finalise(block_number: T::BlockNumber) { if let Some(pending_change) = >::get() { if block_number == pending_change.scheduled_at { - Self::deposit_log(RawLog::AuthoritiesChangeSignal( - pending_change.delay, - pending_change.next_authorities.clone(), - )); + if let Some(median) = pending_change.forced { + Self::deposit_log(RawLog::ForcedAuthoritiesChangeSignal( + median, + pending_change.delay, + pending_change.next_authorities.clone(), + )); + } else { + Self::deposit_log(RawLog::AuthoritiesChangeSignal( + pending_change.delay, + pending_change.next_authorities.clone(), + )); + } } if block_number == pending_change.scheduled_at + pending_change.delay { @@ -217,18 +263,39 @@ impl Module { /// `in_blocks` after the current block. This value may be 0, in which /// case the change is applied at the end of the current block. /// + /// If the `forced` parameter is defined, this indicates that the current + /// set has been synchronously determined to be offline and that after + /// `in_blocks` the given change should be applied. The given block number + /// indicates the median last finalized block number and it should be used + /// as the canon block when starting the new grandpa voter. + /// /// No change should be signalled while any change is pending. Returns /// an error if a change is already pending. pub fn schedule_change( next_authorities: Vec<(T::SessionKey, u64)>, in_blocks: T::BlockNumber, + forced: Option, ) -> Result { + use primitives::traits::As; + if Self::pending_change().is_none() { let scheduled_at = system::ChainContext::::default().current_height(); + + if let Some(_) = forced { + if Self::next_forced().map_or(false, |next| next > scheduled_at) { + return Err("Cannot signal forced change so soon after last."); + } + + // only allow the next forced change when twice the window has passed since + // this one. + >::put(scheduled_at + in_blocks * T::BlockNumber::sa(2)); + } + >::put(StoredPendingChange { delay: in_blocks, scheduled_at, next_authorities, + forced, }); Ok(()) @@ -244,12 +311,19 @@ impl Module { } impl Module where AuthorityId: core::convert::From<::SessionKey> { - /// See if the digest contains any scheduled change. + /// See if the digest contains any standard scheduled change. pub fn scrape_digest_change(log: &Log) -> Option> { as GrandpaChangeSignal>::as_signal(log) } + + /// See if the digest contains any forced scheduled change. + pub fn scrape_digest_forced_change(log: &Log) + -> Option<(T::BlockNumber, ScheduledChange)> + { + as GrandpaChangeSignal>::as_forced_signal(log) + } } /// Helper for authorities being synchronized with the general session authorities. @@ -259,7 +333,7 @@ impl Module where AuthorityId: core::convert::From<::Se /// sets should be. pub struct SyncedAuthorities(::rstd::marker::PhantomData); -// TODO: remove when https://github.com/rust-lang/rust/issues/26925 is fixed +// FIXME: remove when https://github.com/rust-lang/rust/issues/26925 is fixed impl Default for SyncedAuthorities { fn default() -> Self { SyncedAuthorities(::rstd::marker::PhantomData) @@ -267,26 +341,43 @@ impl Default for SyncedAuthorities { } impl session::OnSessionChange for SyncedAuthorities where - T: Trait, - T: session::Trait, - ::ConvertAccountIdToSessionKey: Convert< - ::AccountId, - ::SessionKey, - >, + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>> { fn on_session_change(_: X, _: bool) { use primitives::traits::Zero; - let next_authorities = >::validators() + let next_authorities = >::authorities() .into_iter() - .map(T::ConvertAccountIdToSessionKey::convert) .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); // instant changes let last_authorities = >::grandpa_authorities(); if next_authorities != last_authorities { - let _ = >::schedule_change(next_authorities, Zero::zero()); + let _ = >::schedule_change(next_authorities, Zero::zero(), None); } } } + +impl finality_tracker::OnFinalizationStalled for SyncedAuthorities where + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>>, + T: finality_tracker::Trait, +{ + fn on_stalled(further_wait: T::BlockNumber) { + // when we record old authority sets, we can use `finality_tracker::median` + // to figure out _who_ failed. until then, we can't meaningfully guard + // against `next == last` the way that normal session changes do. + + let next_authorities = >::authorities() + .into_iter() + .map(|key| (key, 1)) // evenly-weighted. + .collect::::SessionKey, u64)>>(); + + let median = >::median(); + + // schedule a change for `further_wait` blocks. + let _ = >::schedule_change(next_authorities, further_wait, Some(median)); + } +} diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index c263083892525872e1780717fa3cf3e32d2122c0..7c35141e17969bcf20bf30d504447b892f9d58f2 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,12 +18,13 @@ #![cfg(test)] -use primitives::{BuildStorage, testing::{Digest, DigestItem, Header}}; +use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header}}; use primitives::generic::DigestItem as GenDigestItem; use runtime_io; +use srml_support::{impl_outer_origin, impl_outer_event}; use substrate_primitives::{H256, Blake2Hasher}; -use parity_codec::Encode; -use {system, GenesisConfig, Trait, Module, RawLog}; +use parity_codec::{Encode, Decode}; +use crate::{GenesisConfig, Trait, Module, RawLog}; impl_outer_origin!{ pub enum Origin for Test {} @@ -51,13 +52,14 @@ impl system::Trait for Test { type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; type Log = DigestItem; } mod grandpa { - pub use ::Event; + pub use crate::Event; } impl_outer_event!{ diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs index 4d8694b2a556fb7fd476f6c4873d55646716b04d..37902cfb17d8ce20b2d7b4ea36eac2c6e93094a9 100644 --- a/srml/grandpa/src/tests.rs +++ b/srml/grandpa/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,15 +21,17 @@ use primitives::{testing, traits::OnFinalise}; use primitives::traits::Header; use runtime_io::with_externalities; -use mock::{Grandpa, System, new_test_ext}; +use crate::mock::{Grandpa, System, new_test_ext}; use system::{EventRecord, Phase}; -use {RawLog, RawEvent}; +use crate::{RawLog, RawEvent}; +use codec::{Decode, Encode}; +use super::*; #[test] fn authorities_change_logged() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { System::initialise(&1, &Default::default(), &Default::default()); - Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0).unwrap(); + Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0, None).unwrap(); System::note_finished_extrinsics(); Grandpa::on_finalise(1); @@ -54,7 +56,7 @@ fn authorities_change_logged() { fn authorities_change_logged_after_delay() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { System::initialise(&1, &Default::default(), &Default::default()); - Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1).unwrap(); + Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); Grandpa::on_finalise(1); let header = System::finalise(); assert_eq!(header.digest, testing::Digest { @@ -84,25 +86,113 @@ fn authorities_change_logged_after_delay() { fn cannot_schedule_change_when_one_pending() { with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { System::initialise(&1, &Default::default(), &Default::default()); - Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1).unwrap(); + Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap(); assert!(Grandpa::pending_change().is_some()); - assert!(Grandpa::schedule_change(vec![(5, 1)], 1).is_err()); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); Grandpa::on_finalise(1); let header = System::finalise(); System::initialise(&2, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_some()); - assert!(Grandpa::schedule_change(vec![(5, 1)], 1).is_err()); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); Grandpa::on_finalise(2); let header = System::finalise(); System::initialise(&3, &header.hash(), &Default::default()); assert!(Grandpa::pending_change().is_none()); - assert!(Grandpa::schedule_change(vec![(5, 1)], 1).is_ok()); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); Grandpa::on_finalise(3); let _header = System::finalise(); }); } + +#[test] +fn new_decodes_from_old() { + let old = OldStoredPendingChange { + scheduled_at: 5u32, + delay: 100u32, + next_authorities: vec![(1u64, 5), (2u64, 10), (3u64, 2)], + }; + + let encoded = old.encode(); + let new = StoredPendingChange::::decode(&mut &encoded[..]).unwrap(); + assert!(new.forced.is_none()); + assert_eq!(new.scheduled_at, old.scheduled_at); + assert_eq!(new.delay, old.delay); + assert_eq!(new.next_authorities, old.next_authorities); +} + +#[test] +fn dispatch_forced_change() { + with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + System::initialise(&1, &Default::default(), &Default::default()); + Grandpa::schedule_change( + vec![(4, 1), (5, 1), (6, 1)], + 5, + Some(0), + ).unwrap(); + + assert!(Grandpa::pending_change().is_some()); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err()); + + Grandpa::on_finalise(1); + let mut header = System::finalise(); + + for i in 2..7 { + System::initialise(&i, &header.hash(), &Default::default()); + assert!(Grandpa::pending_change().unwrap().forced.is_some()); + assert_eq!(Grandpa::next_forced(), Some(11)); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err()); + + Grandpa::on_finalise(i); + header = System::finalise(); + } + + // change has been applied at the end of block 6. + // add a normal change. + { + System::initialise(&7, &header.hash(), &Default::default()); + assert!(Grandpa::pending_change().is_none()); + assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok()); + Grandpa::on_finalise(7); + header = System::finalise(); + } + + // run the normal change. + { + System::initialise(&8, &header.hash(), &Default::default()); + assert!(Grandpa::pending_change().is_some()); + assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]); + assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err()); + Grandpa::on_finalise(8); + header = System::finalise(); + } + + // normal change applied. but we can't apply a new forced change for some + // time. + for i in 9..11 { + System::initialise(&i, &header.hash(), &Default::default()); + assert!(Grandpa::pending_change().is_none()); + assert_eq!(Grandpa::grandpa_authorities(), vec![(5, 1)]); + assert_eq!(Grandpa::next_forced(), Some(11)); + assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1)], 5, Some(0)).is_err()); + Grandpa::on_finalise(i); + header = System::finalise(); + } + + { + System::initialise(&11, &header.hash(), &Default::default()); + assert!(Grandpa::pending_change().is_none()); + assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1), (7, 1)], 5, Some(0)).is_ok()); + assert_eq!(Grandpa::next_forced(), Some(21)); + Grandpa::on_finalise(11); + header = System::finalise(); + } + let _ = header; + }); +} diff --git a/srml/indices/Cargo.toml b/srml/indices/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..2331f325d1dd1aaf8fd42559bf143fc65bde7129 --- /dev/null +++ b/srml/indices/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "srml-indices" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", optional = true } +safe-mix = { version = "1.0", default-features = false} +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } +substrate-keyring = { path = "../../core/keyring", optional = true } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +srml-support = { path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +substrate-primitives = { path = "../../core/primitives", default-features = false } + +[dev-dependencies] +ref_thread_local = "0.0" + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "substrate-keyring", + "parity-codec/std", + "parity-codec-derive/std", + "substrate-primitives/std", + "rstd/std", + "runtime-io/std", + "srml-support/std", + "primitives/std", + "system/std", +] diff --git a/srml/balances/src/address.rs b/srml/indices/src/address.rs similarity index 94% rename from srml/balances/src/address.rs rename to srml/indices/src/address.rs index ccaa6b46a5db8ae63f5e523f885ff545093dcda4..fd8f0249dec960fcee28233504d03ad9366014b3 100644 --- a/srml/balances/src/address.rs +++ b/srml/indices/src/address.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,9 +18,10 @@ #[cfg(feature = "std")] use std::fmt; -use super::{Member, Decode, Encode, As, Input, Output}; +use crate::{Member, Decode, Encode, As, Input, Output}; -/// A vetted and verified extrinsic from the external world. +/// An indices-aware address, which can be either a direct `AccountId` or +/// an index. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug, Hash))] pub enum Address where diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..76261796c8b78b6131fb1fb00794b897b473b8c9 --- /dev/null +++ b/srml/indices/src/lib.rs @@ -0,0 +1,204 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! An index is a short form of an address. This module handles allocation +//! of indices for a newly created accounts. + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::{prelude::*, result, marker::PhantomData}; +use parity_codec::{Encode, Decode, Codec, Input, Output}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage}; +use primitives::traits::{One, SimpleArithmetic, As, StaticLookup, Member}; +use system::{IsDeadAccount, OnNewAccount}; + +use self::address::Address as RawAddress; + +mod mock; + +pub mod address; +mod tests; + +/// Number of account IDs stored per enum set. +const ENUM_SET_SIZE: usize = 64; + +pub type Address = RawAddress<::AccountId, ::AccountIndex>; + +/// Turn an Id into an Index, or None for the purpose of getting +/// a hint at a possibly desired index. +pub trait ResolveHint> { + /// Turn an Id into an Index, or None for the purpose of getting + /// a hint at a possibly desired index. + fn resolve_hint(who: &AccountId) -> Option; +} + +/// Simple encode-based resolve hint implemenntation. +pub struct SimpleResolveHint(PhantomData<(AccountId, AccountIndex)>); +impl> ResolveHint for SimpleResolveHint { + fn resolve_hint(who: &AccountId) -> Option { + Some(AccountIndex::sa(who.using_encoded(|e| e[0] as usize + e[1] as usize * 256))) + } +} + +/// The module's config trait. +pub trait Trait: system::Trait { + /// Type used for storing an account's index; implies the maximum number of accounts the system + /// can hold. + type AccountIndex: Parameter + Member + Codec + Default + SimpleArithmetic + As + As + As + As + As + Copy; + + /// Whether an account is dead or not. + type IsDeadAccount: IsDeadAccount; + + /// How to turn an id into an index. + type ResolveHint: ResolveHint; + + /// The overarching event type. + type Event: From> + Into<::Event>; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + } +} + +decl_event!( + pub enum Event where + ::AccountId, + ::AccountIndex + { + /// A new account index was assigned. + /// + /// This event is not triggered when an existing index is reassigned + /// to another `AccountId`. + NewAccountIndex(AccountId, AccountIndex), + } +); + +decl_storage! { + trait Store for Module as Indices { + /// The next free enumeration set. + pub NextEnumSet get(next_enum_set) build(|config: &GenesisConfig| { + T::AccountIndex::sa(config.ids.len() / ENUM_SET_SIZE) + }): T::AccountIndex; + + /// The enumeration sets. + pub EnumSet get(enum_set): map T::AccountIndex => Vec; + } + add_extra_genesis { + config(ids): Vec; + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { + for i in 0..(config.ids.len() + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE { + storage.insert(GenesisConfig::::hash(&>::key_for(T::AccountIndex::sa(i))).to_vec(), + config.ids[i * ENUM_SET_SIZE..config.ids.len().min((i + 1) * ENUM_SET_SIZE)].to_owned().encode()); + } + }); + } +} + +impl Module { + // PUBLIC IMMUTABLES + + /// Lookup an T::AccountIndex to get an Id, if there's one there. + pub fn lookup_index(index: T::AccountIndex) -> Option { + let enum_set_size = Self::enum_set_size(); + let set = Self::enum_set(index / enum_set_size); + let i: usize = (index % enum_set_size).as_(); + set.get(i).cloned() + } + + /// `true` if the account `index` is ready for reclaim. + pub fn can_reclaim(try_index: T::AccountIndex) -> bool { + let enum_set_size = Self::enum_set_size(); + let try_set = Self::enum_set(try_index / enum_set_size); + let i = (try_index % enum_set_size).as_(); + i < try_set.len() && T::IsDeadAccount::is_dead_account(&try_set[i]) + } + + /// Lookup an address to get an Id, if there's one there. + pub fn lookup_address(a: address::Address) -> Option { + match a { + address::Address::Id(i) => Some(i), + address::Address::Index(i) => Self::lookup_index(i), + } + } + + // PUBLIC MUTABLES (DANGEROUS) + + fn enum_set_size() -> T::AccountIndex { + T::AccountIndex::sa(ENUM_SET_SIZE) + } +} + +impl OnNewAccount for Module { + fn on_new_account(who: &T::AccountId) { + let enum_set_size = Self::enum_set_size(); + let next_set_index = Self::next_enum_set(); + + if let Some(try_index) = T::ResolveHint::resolve_hint(who) { + // then check to see if this account id identifies a dead account index. + let set_index = try_index / enum_set_size; + let mut try_set = Self::enum_set(set_index); + let item_index = (try_index % enum_set_size).as_(); + if item_index < try_set.len() { + if T::IsDeadAccount::is_dead_account(&try_set[item_index]) { + // yup - this index refers to a dead account. can be reused. + try_set[item_index] = who.clone(); + >::insert(set_index, try_set); + + return + } + } + } + + // insert normally as a back up + let mut set_index = next_set_index; + // defensive only: this loop should never iterate since we keep NextEnumSet up to date later. + let mut set = loop { + let set = Self::enum_set(set_index); + if set.len() < ENUM_SET_SIZE { + break set; + } + set_index += One::one(); + }; + + let index = T::AccountIndex::sa(set_index.as_() * ENUM_SET_SIZE + set.len()); + + // update set. + set.push(who.clone()); + + // keep NextEnumSet up to date + if set.len() == ENUM_SET_SIZE { + >::put(set_index + One::one()); + } + + // write set. + >::insert(set_index, set); + + Self::deposit_event(RawEvent::NewAccountIndex(who.clone(), index)); + } +} + +impl StaticLookup for Module { + type Source = address::Address; + type Target = T::AccountId; + fn lookup(a: Self::Source) -> result::Result { + Self::lookup_address(a).ok_or("invalid account index") + } + fn unlookup(a: Self::Target) -> Self::Source { + address::Address::Id(a) + } +} diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..80d3fa2c4fc9d3a4d15e33f607a6d44a03d26ac1 --- /dev/null +++ b/srml/indices/src/mock.rs @@ -0,0 +1,102 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::collections::HashSet; +use ref_thread_local::{ref_thread_local, RefThreadLocal}; +use primitives::BuildStorage; +use primitives::testing::{Digest, DigestItem, Header}; +use substrate_primitives::{H256, Blake2Hasher}; +use srml_support::impl_outer_origin; +use {runtime_io, system}; +use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint}; + +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +ref_thread_local! { + static managed ALIVE: HashSet = HashSet::new(); +} + +pub fn make_account(who: u64) { + ALIVE.borrow_mut().insert(who); + Indices::on_new_account(&who); +} + +pub fn kill_account(who: u64) { + ALIVE.borrow_mut().remove(&who); +} + +pub struct TestIsDeadAccount {} +impl IsDeadAccount for TestIsDeadAccount { + fn is_dead_account(who: &u64) -> bool { + !ALIVE.borrow_mut().contains(who) + } +} + +pub struct TestResolveHint; +impl ResolveHint for TestResolveHint { + fn resolve_hint(who: &u64) -> Option { + if *who < 256 { + None + } else { + Some(*who - 256) + } + } +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Runtime; +impl system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = ::primitives::traits::BlakeTwo256; + type Digest = Digest; + type AccountId = u64; + type Lookup = Indices; + type Header = Header; + type Event = (); + type Log = DigestItem; +} +impl Trait for Runtime { + type AccountIndex = u64; + type IsDeadAccount = TestIsDeadAccount; + type ResolveHint = TestResolveHint; + type Event = (); +} + +pub fn new_test_ext() -> runtime_io::TestExternalities { + { + let mut h = ALIVE.borrow_mut(); + h.clear(); + for i in 1..5 { h.insert(i); } + } + + let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; + t.extend(GenesisConfig:: { + ids: vec![1, 2, 3, 4] + }.build_storage().unwrap().0); + t.into() +} + +pub type Indices = Module; diff --git a/srml/indices/src/tests.rs b/srml/indices/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..7b60e305278c58be97d156b0bbffc892afe7b750 --- /dev/null +++ b/srml/indices/src/tests.rs @@ -0,0 +1,80 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +#![cfg(test)] + +use super::*; +use crate::mock::{Indices, new_test_ext, make_account, kill_account, TestIsDeadAccount}; +use runtime_io::with_externalities; + +#[test] +fn indexing_lookup_should_work() { + with_externalities( + &mut new_test_ext(), + || { + assert_eq!(Indices::lookup_index(0), Some(1)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(2), Some(3)); + assert_eq!(Indices::lookup_index(3), Some(4)); + assert_eq!(Indices::lookup_index(4), None); + }, + ); +} + +#[test] +fn default_indexing_on_new_accounts_should_work() { + with_externalities( + &mut new_test_ext(), + || { + assert_eq!(Indices::lookup_index(4), None); + make_account(5); + assert_eq!(Indices::lookup_index(4), Some(5)); + }, + ); +} + +#[test] +fn reclaim_indexing_on_new_accounts_should_work() { + with_externalities( + &mut new_test_ext(), + || { + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); + + kill_account(2); // index 1 no longer locked to id 2 + + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(1), Some(257)); + }, + ); +} + +#[test] +fn alive_account_should_prevent_reclaim() { + with_externalities( + &mut new_test_ext(), + || { + assert!(!TestIsDeadAccount::is_dead_account(&2)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); + + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(4), Some(257)); + }, + ); +} diff --git a/srml/metadata/Cargo.toml b/srml/metadata/Cargo.toml index d442a5e225d11ce4dbc25376db53df6d6acde3a2..eed5e6b4e3379fad722aecc007b46e92ab5d2de3 100644 --- a/srml/metadata/Cargo.toml +++ b/srml/metadata/Cargo.toml @@ -2,22 +2,21 @@ name = "srml-metadata" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -sr-std = { path = "../../core/sr-std", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } [features] default = ["std"] std = [ "parity-codec/std", - "parity-codec-derive/std", - "sr-std/std", - "substrate-primitives/std", + "rstd/std", + "primitives/std", "serde", "serde_derive" ] diff --git a/srml/metadata/src/lib.rs b/srml/metadata/src/lib.rs index 0809531a9f8feddfd1036f9f054f636af417adb5..3f40753006be64a43663d6d9b463ed0fec4d87af 100644 --- a/srml/metadata/src/lib.rs +++ b/srml/metadata/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,26 +22,19 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[macro_use] -extern crate parity_codec_derive; -extern crate parity_codec as codec; -extern crate sr_std as rstd; -extern crate substrate_primitives as primitives; - -#[cfg(feature = "std")] -extern crate serde; #[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; - -use codec::{Encode, Output}; +use serde_derive::Serialize; #[cfg(feature = "std")] -use codec::{Decode, Input}; +use parity_codec::{Decode, Input}; +use parity_codec::{Encode, Output}; use rstd::vec::Vec; #[cfg(feature = "std")] type StringBuf = String; +/// Curent prefix of metadata +pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warn endianness + /// On `no_std` we do not support `Decode` and thus `StringBuf` is just `&'static str`. /// So, if someone tries to decode this stuff on `no_std`, they will get a compilation error. #[cfg(not(feature = "std"))] @@ -110,8 +103,8 @@ impl serde::Serialize for DecodeDifferent O: serde::Serialize + 'static, { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, + where + S: serde::Serializer, { match self { DecodeDifferent::Encode(b) => b.serialize(serializer), @@ -120,34 +113,17 @@ impl serde::Serialize for DecodeDifferent } } -type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; +pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; #[cfg(feature = "std")] type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; #[cfg(not(feature = "std"))] type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; -/// All the metadata about a module. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct ModuleMetadata { - pub name: DecodeDifferentStr, - pub call: CallMetadata, -} - -/// All the metadata about a call. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct CallMetadata { - pub name: DecodeDifferentStr, - pub functions: DecodeDifferentArray, -} - /// All the metadata about a function. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] pub struct FunctionMetadata { - pub id: u16, pub name: DecodeDifferentStr, pub arguments: DecodeDifferentArray, pub documentation: DecodeDifferentArray<&'static str, StringBuf>, @@ -187,8 +163,8 @@ impl std::fmt::Debug for FnEncode { #[cfg(feature = "std")] impl serde::Serialize for FnEncode { fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, + where + S: serde::Serializer, { self.0().serialize(serializer) } @@ -218,7 +194,6 @@ pub struct EventMetadata { #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] pub struct StorageMetadata { - pub prefix: DecodeDifferentStr, pub functions: DecodeDifferentArray, } @@ -229,9 +204,55 @@ pub struct StorageFunctionMetadata { pub name: DecodeDifferentStr, pub modifier: StorageFunctionModifier, pub ty: StorageFunctionType, + pub default: ByteGetter, pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } +/// A technical trait to store lazy initiated vec value as static dyn pointer. +pub trait DefaultByte { + fn default_byte(&self) -> Vec; +} + +/// Wrapper over dyn pointer for accessing a cached once byte value. +#[derive(Clone)] +pub struct DefaultByteGetter(pub &'static dyn DefaultByte); + +/// Decode different for static lazy initiated byte value. +pub type ByteGetter = DecodeDifferent>; + +impl Encode for DefaultByteGetter { + fn encode_to(&self, dest: &mut W) { + self.0.default_byte().encode_to(dest) + } +} + +impl PartialEq for DefaultByteGetter { + fn eq(&self, other: &DefaultByteGetter) -> bool { + let left = self.0.default_byte(); + let right = other.0.default_byte(); + left.eq(&right) + } +} + +impl Eq for DefaultByteGetter { } + +#[cfg(feature = "std")] +impl serde::Serialize for DefaultByteGetter { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.default_byte().serialize(serializer) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for DefaultByteGetter { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.0.default_byte().fmt(f) + } +} + /// A storage function type. #[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] @@ -264,30 +285,71 @@ pub struct OuterDispatchMetadata { #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] pub struct OuterDispatchCall { pub name: DecodeDifferentStr, - pub prefix: DecodeDifferentStr, pub index: u16, } -/// All metadata about an runtime module. -#[derive(Clone, PartialEq, Eq, Encode)] +#[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct RuntimeModuleMetadata { - pub prefix: DecodeDifferentStr, - pub module: DecodeDifferent, ModuleMetadata>, - pub storage: Option, StorageMetadata>>, -} +/// Metadata prefixed by a u32 for reserved usage +pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata); /// The metadata of a runtime. +/// The version ID encoded/decoded through +/// the enum nature of `RuntimeMetadata`. #[derive(Eq, Encode, PartialEq)] #[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct RuntimeMetadata { - pub outer_event: OuterEventMetadata, - pub modules: DecodeDifferentArray, - pub outer_dispatch: OuterDispatchMetadata, +pub enum RuntimeMetadata { + /// Unused; enum filler. + V0(RuntimeMetadataDeprecated), + /// Version 1 for runtime metadata. + V1(RuntimeMetadataV1), +} + +/// Enum that should fail. +#[derive(Eq, PartialEq)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +pub enum RuntimeMetadataDeprecated { } + +impl Encode for RuntimeMetadataDeprecated { + fn encode_to(&self, _dest: &mut W) { + } } -impl Into for RuntimeMetadata { +#[cfg(feature = "std")] +impl Decode for RuntimeMetadataDeprecated { + fn decode(_input: &mut I) -> Option { + unimplemented!() + } +} + +/// The metadata of a runtime version 1. +#[derive(Eq, Encode, PartialEq)] +#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +pub struct RuntimeMetadataV1 { + pub modules: DecodeDifferentArray, +} + +/// All metadata about an runtime module. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +pub struct ModuleMetadata { + pub name: DecodeDifferentStr, + pub prefix: DecodeDifferent, StringBuf>, + pub storage: ODFnA, + pub calls: ODFnA, + pub event: ODFnA, +} + +type ODFnA = Option, Vec>>; + +impl Into for RuntimeMetadataPrefixed { fn into(self) -> primitives::OpaqueMetadata { primitives::OpaqueMetadata::new(self.encode()) } } + +impl Into for RuntimeMetadata { + fn into(self) -> RuntimeMetadataPrefixed { + RuntimeMetadataPrefixed(META_RESERVED, self) + } +} diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml index ad798edbdb53ba98951f657c785f80016ed07ee4..84b49b77882ff5212194122ee9af8b15956b1433 100644 --- a/srml/session/Cargo.toml +++ b/srml/session/Cargo.toml @@ -2,35 +2,36 @@ name = "srml-session" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -substrate-primitives = { path = "../../core/primitives", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-consensus = { path = "../consensus", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-timestamp = { path = "../timestamp", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../core/primitives" } +runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "parity-codec/std", "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-consensus/std", - "srml-system/std", - "srml-timestamp/std" + "primitives/std", + "consensus/std", + "system/std", + "timestamp/std" ] diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 8fc58feab2b3014a0b90a4d0945bee6bb07ae35d..47fb0fca417341027f27ae89488c30204ea00b86 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,29 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate sr_std as rstd; - -#[macro_use] -extern crate srml_support as runtime_support; - -#[macro_use] -extern crate parity_codec_derive; - -#[cfg(test)] -extern crate substrate_primitives; -#[cfg(test)] -extern crate sr_io as runtime_io; -extern crate parity_codec as codec; -extern crate sr_primitives as primitives; -extern crate srml_consensus as consensus; -extern crate srml_system as system; -extern crate srml_timestamp as timestamp; - use rstd::prelude::*; use primitives::traits::{As, Zero, One, Convert}; -use codec::HasCompact; -use runtime_support::{StorageValue, StorageMap}; -use runtime_support::dispatch::Result; +use srml_support::{StorageValue, StorageMap, for_each_tuple, decl_module, decl_event, decl_storage}; +use srml_support::{dispatch::Result, traits::OnFreeBalanceZero}; use system::ensure_signed; use rstd::ops::Mul; @@ -51,17 +32,6 @@ pub trait OnSessionChange { fn on_session_change(time_elapsed: T, should_reward: bool); } -macro_rules! for_each_tuple { - ($m:ident) => { - for_each_tuple! { @IMPL $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, } - }; - (@IMPL $m:ident !!) => { $m! { } }; - (@IMPL $m:ident !! $h:ident, $($t:ident,)*) => { - $m! { $h $($t)* } - for_each_tuple! { @IMPL $m !! $($t,)* } - } -} - macro_rules! impl_session_change { () => ( impl OnSessionChange for () { @@ -80,16 +50,15 @@ macro_rules! impl_session_change { for_each_tuple!(impl_session_change); - -pub trait Trait: timestamp::Trait { - type ConvertAccountIdToSessionKey: Convert; +pub trait Trait: timestamp::Trait + consensus::Trait { + type ConvertAccountIdToSessionKey: Convert>; type OnSessionChange: OnSessionChange; type Event: From> + Into<::Event>; } decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next /// session. @@ -100,8 +69,8 @@ decl_module! { } /// Set a new session length. Won't kick in until the next session change (at current length). - fn set_length(new: ::Type) { - >::put(new.into()); + fn set_length(#[compact] new: T::BlockNumber) { + >::put(new); } /// Forces a new session. @@ -126,7 +95,6 @@ decl_event!( decl_storage! { trait Store for Module as Session { - /// The current set of validators. pub Validators get(validators) config(): Vec; /// Current length of the session. @@ -142,16 +110,21 @@ decl_storage! { /// Block at which the session length last changed. LastLengthChange: Option; /// The next key for a given validator. - NextKeyFor: map T::AccountId => Option; + NextKeyFor build(|config: &GenesisConfig| { + config.keys.clone() + }): map T::AccountId => Option; /// The next session length. NextSessionLength: Option; } + add_extra_genesis { + config(keys): Vec<(T::AccountId, T::SessionKey)>; + } } impl Module { /// The number of validators currently. pub fn validator_count() -> u32 { - >::get().len() as u32 // TODO: can probably optimised + >::get().len() as u32 } /// The last length change, if there was one, zero if not. @@ -168,13 +141,10 @@ impl Module { /// Set the current set of validators. /// - /// Called by `staking::new_era()` only. `next_session` should be called after this in order to + /// Called by `staking::new_era()` only. `rotate_session` must be called after this in order to /// update the session keys to the next validator set. pub fn set_validators(new: &[T::AccountId]) { - >::put(&new.to_vec()); // TODO: optimise. - >::set_authorities( - &new.iter().cloned().map(T::ConvertAccountIdToSessionKey::convert).collect::>() - ); + >::put(&new.to_vec()); } /// Hook to be called after transaction processing. @@ -214,14 +184,17 @@ impl Module { >::put(block_number); } - T::OnSessionChange::on_session_change(time_elapsed, apply_rewards); - // Update any changes in session keys. - Self::validators().iter().enumerate().for_each(|(i, v)| { - if let Some(n) = >::take(v) { - >::set_authority(i as u32, &n); - } - }); + for (i, v) in Self::validators().into_iter().enumerate() { + >::set_authority( + i as u32, + &>::get(&v) + .or_else(|| T::ConvertAccountIdToSessionKey::convert(v)) + .unwrap_or_default() + ); + }; + + T::OnSessionChange::on_session_change(time_elapsed, apply_rewards); } /// Get the time that should have elapsed over a session if everything was working perfectly. @@ -242,14 +215,21 @@ impl Module { } } +impl OnFreeBalanceZero for Module { + fn on_free_balance_zero(who: &T::AccountId) { + >::remove(who); + } +} + #[cfg(test)] mod tests { use super::*; + use srml_support::{impl_outer_origin, assert_ok}; use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::BuildStorage; - use primitives::traits::{Identity, BlakeTwo256}; - use primitives::testing::{Digest, DigestItem, Header}; + use primitives::traits::{BlakeTwo256, IdentityLookup}; + use primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, ConvertUintAuthorityId}; impl_outer_origin!{ pub enum Origin for Test {} @@ -258,9 +238,8 @@ mod tests { #[derive(Clone, Eq, PartialEq)] pub struct Test; impl consensus::Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; type Log = DigestItem; - type SessionKey = u64; + type SessionKey = UintAuthorityId; type InherentOfflineReport = (); } impl system::Trait for Test { @@ -271,17 +250,17 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; type Moment = u64; type OnTimestampSet = (); } impl Trait for Test { - type ConvertAccountIdToSessionKey = Identity; + type ConvertAccountIdToSessionKey = ConvertUintAuthorityId; type OnSessionChange = (); type Event = (); } @@ -294,7 +273,7 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(consensus::GenesisConfig::{ code: vec![], - authorities: vec![1, 2, 3], + authorities: vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)], }.build_storage().unwrap().0); t.extend(timestamp::GenesisConfig::{ period: 5, @@ -302,6 +281,7 @@ mod tests { t.extend(GenesisConfig::{ session_length: 2, validators: vec![1, 2, 3], + keys: vec![], }.build_storage().unwrap().0); runtime_io::TestExternalities::new(t) } @@ -309,7 +289,7 @@ mod tests { #[test] fn simple_setup_should_work() { with_externalities(&mut new_test_ext(), || { - assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1).into(), UintAuthorityId(2).into(), UintAuthorityId(3).into()]); assert_eq!(Session::length(), 2); assert_eq!(Session::validators(), vec![1, 2, 3]); }); @@ -319,7 +299,7 @@ mod tests { fn should_work_with_early_exit() { with_externalities(&mut new_test_ext(), || { System::set_block_number(1); - assert_ok!(Session::set_length(10.into())); + assert_ok!(Session::set_length(10)); assert_eq!(Session::blocks_remaining(), 1); Session::check_rotate_session(1); @@ -354,14 +334,14 @@ mod tests { with_externalities(&mut new_test_ext(), || { // Block 1: Change to length 3; no visible change. System::set_block_number(1); - assert_ok!(Session::set_length(3.into())); + assert_ok!(Session::set_length(3)); Session::check_rotate_session(1); assert_eq!(Session::length(), 2); assert_eq!(Session::current_index(), 0); // Block 2: Length now changed to 3. Index incremented. System::set_block_number(2); - assert_ok!(Session::set_length(3.into())); + assert_ok!(Session::set_length(3)); Session::check_rotate_session(2); assert_eq!(Session::length(), 3); assert_eq!(Session::current_index(), 1); @@ -374,7 +354,7 @@ mod tests { // Block 4: Change to length 2; no visible change. System::set_block_number(4); - assert_ok!(Session::set_length(2.into())); + assert_ok!(Session::set_length(2)); Session::check_rotate_session(4); assert_eq!(Session::length(), 3); assert_eq!(Session::current_index(), 1); @@ -405,25 +385,25 @@ mod tests { // Block 1: No change System::set_block_number(1); Session::check_rotate_session(1); - assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); // Block 2: Session rollover, but no change. System::set_block_number(2); Session::check_rotate_session(2); - assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); // Block 3: Set new key for validator 2; no visible change. System::set_block_number(3); - assert_ok!(Session::set_key(Origin::signed(2), 5)); - assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_ok!(Session::set_key(Origin::signed(2), UintAuthorityId(5))); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); Session::check_rotate_session(3); - assert_eq!(Consensus::authorities(), vec![1, 2, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); // Block 4: Session rollover, authority 2 changes. System::set_block_number(4); Session::check_rotate_session(4); - assert_eq!(Consensus::authorities(), vec![1, 5, 3]); + assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); }); } } diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml index 4d355921441dde5b646f2f5fb54e515eaca03313..967cee3391f08fe8b323fb1d65ef917e5bb75495 100644 --- a/srml/staking/Cargo.toml +++ b/srml/staking/Cargo.toml @@ -2,40 +2,38 @@ name = "srml-staking" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-balances = { path = "../balances", default-features = false } -srml-consensus = { path = "../consensus", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-session = { path = "../session", default-features = false } -srml-timestamp = { path = "../timestamp", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +session = { package = "srml-session", path = "../session", default-features = false } + +[dev-dependencies] +substrate-primitives = { path = "../../core/primitives" } +timestamp = { package = "srml-timestamp", path = "../timestamp" } +balances = { package = "srml-balances", path = "../balances" } [features] default = ["std"] std = [ - "serde/std", + "serde", "safe-mix/std", "substrate-keyring", "parity-codec/std", - "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", + "runtime_io/std", "srml-support/std", - "sr-primitives/std", - "srml-balances/std", - "srml-session/std", - "srml-system/std", - "srml-timestamp/std" + "primitives/std", + "session/std", + "system/std", ] diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 208c14fc0f1bfeb74205df6122ea04e54061d406..4650bff981d778677e09b1a659234904d942242b 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,63 +21,62 @@ #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] -extern crate serde; - -#[macro_use] -extern crate srml_support as runtime_support; - -extern crate sr_std as rstd; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate parity_codec as codec; -extern crate sr_primitives as primitives; -extern crate srml_balances as balances; -extern crate srml_consensus as consensus; -extern crate srml_session as session; -extern crate srml_system as system; - -#[cfg(test)] -extern crate substrate_primitives; -#[cfg(test)] -extern crate sr_io as runtime_io; -#[cfg(test)] -extern crate srml_timestamp as timestamp; - -use rstd::prelude::*; -use rstd::cmp; -use codec::{HasCompact, Compact}; -use runtime_support::{Parameter, StorageValue, StorageMap}; -use runtime_support::dispatch::Result; +use runtime_io::with_storage; +use rstd::{prelude::*, result}; +use parity_codec::{HasCompact, Encode, Decode}; +use srml_support::{StorageValue, StorageMap, EnumerableStorageMap, dispatch::Result}; +use srml_support::{decl_module, decl_event, decl_storage, ensure}; +use srml_support::traits::{ + Currency, OnDilution, OnFreeBalanceZero, ArithmeticType, + LockIdentifier, LockableCurrency, WithdrawReasons +}; use session::OnSessionChange; -use primitives::{Perbill, traits::{Zero, One, Bounded, As}}; -use balances::{address::Address, OnDilution}; +use primitives::{Perbill}; +use primitives::traits::{Zero, One, As, StaticLookup, Saturating, Bounded}; +#[cfg(feature = "std")] +use primitives::{Serialize, Deserialize}; use system::ensure_signed; mod mock; - mod tests; +mod phragmen; +const RECENT_OFFLINE_COUNT: usize = 32; const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; +const MAX_NOMINATIONS: usize = 16; +const MAX_UNSTAKE_THRESHOLD: u32 = 10; -#[derive(PartialEq, Clone)] -#[cfg_attr(test, derive(Debug))] -pub enum LockStatus { - Liquid, - LockedUntil(BlockNumber), - Bonded, +// Indicates the initial status of the staker +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub enum StakerStatus { Idle, Validator, Nominator(Vec), } + +/// A destination account for payment. +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum RewardDestination { + /// Pay into the stash account, increasing the amount at stake accordingly. + Staked, + /// Pay into the stash account, not increasing the amount at stake. + Stash, + /// Pay into the controller account. + Controller, +} + +impl Default for RewardDestination { + fn default() -> Self { + RewardDestination::Staked + } } /// Preference of what happens on a slash event. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] -pub struct ValidatorPrefs { // TODO: @bkchr shouldn't need this Copy but derive(Encode) breaks otherwise +pub struct ValidatorPrefs { /// Validator should ensure this many more slashes than is necessary before being unstaked. #[codec(compact)] pub unstake_threshold: u32, - // Reward that validator takes up-front; only the rest is split between themselves and nominators. - #[codec(encoded_as = "::Type")] + /// Reward that validator takes up-front; only the rest is split between themselves and nominators. + #[codec(compact)] pub validator_payment: Balance, } @@ -90,126 +89,379 @@ impl Default for ValidatorPrefs { } } -pub trait Trait: balances::Trait + session::Trait { +/// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked. +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct UnlockChunk { + /// Amount of funds to be unlocked. + #[codec(compact)] + value: Balance, + /// Era number at which point it'll be unlocked. + #[codec(compact)] + era: BlockNumber, +} + +/// The ledger of a (bonded) stash. +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct StakingLedger { + /// The stash account whose balance is actually locked and at stake. + pub stash: AccountId, + /// The total amount of the stash's balance that we are currently accounting for. + /// It's just `active` plus all the `unlocking` balances. + #[codec(compact)] + pub total: Balance, + /// The total amount of the stash's balance that will be at stake in any forthcoming + /// rounds. + #[codec(compact)] + pub active: Balance, + /// Any balance that is becoming free, which may eventually be transferred out + /// of the stash (assuming it doesn't get slashed first). + pub unlocking: Vec>, +} + +impl< + AccountId, + Balance: HasCompact + Copy + Saturating, + BlockNumber: HasCompact + PartialOrd +> StakingLedger { + /// Remove entries from `unlocking` that are sufficiently old and reduce the + /// total by the sum of their balances. + fn consolidate_unlocked(self, current_era: BlockNumber) -> Self { + let mut total = self.total; + let unlocking = self.unlocking.into_iter() + .filter(|chunk| if chunk.era > current_era { + true + } else { + total = total.saturating_sub(chunk.value); + false + }) + .collect(); + Self { total, active: self.active, stash: self.stash, unlocking } + } +} + +/// The amount of exposure (to slashing) than an individual nominator has. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct IndividualExposure { + /// Which nominator. + who: AccountId, + /// Amount of funds exposed. + #[codec(compact)] + value: Balance, +} + +/// A snapshot of the stake backing a single validator in the system. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Exposure { + /// The total balance backing this validator. + #[codec(compact)] + pub total: Balance, + /// The validator's own stash that is exposed. + #[codec(compact)] + pub own: Balance, + /// The portions of nominators stashes that are exposed. + pub others: Vec>, +} + +type BalanceOf = <::Currency as ArithmeticType>::Type; + +pub trait Trait: system::Trait + session::Trait { + /// The staking balance. + type Currency: + ArithmeticType + + Currency> + + LockableCurrency; + /// Some tokens minted. - type OnRewardMinted: OnDilution<::Balance>; + type OnRewardMinted: OnDilution>; /// The overarching event type. type Event: From> + Into<::Event>; } -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; +const STAKING_ID: LockIdentifier = *b"staking "; + +decl_storage! { + trait Store for Module as Staking { + + /// The ideal number of staking participants. + pub ValidatorCount get(validator_count) config(): u32; + /// Minimum number of staking participants before emergency conditions are imposed. + pub MinimumValidatorCount get(minimum_validator_count) config(): u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; + /// The length of a staking era in sessions. + pub SessionsPerEra get(sessions_per_era) config(): T::BlockNumber = T::BlockNumber::sa(1000); + /// Maximum reward, per validator, that is provided per acceptable session. + pub SessionReward get(session_reward) config(): Perbill = Perbill::from_billionths(60); + /// Slash, per validator that is taken for the first time they are found to be offline. + pub OfflineSlash get(offline_slash) config(): Perbill = Perbill::from_millionths(1000); // Perbill::from_fraction() is only for std, so use from_millionths(). + /// Number of instances of offline reports before slashing begins for validators. + pub OfflineSlashGrace get(offline_slash_grace) config(): u32; + /// The length of the bonding duration in blocks. + pub BondingDuration get(bonding_duration) config(): T::BlockNumber = T::BlockNumber::sa(1000); - /// Declare the desire to stake for the transactor. + // TODO: remove once Alex/CC updated #1785 + pub Invulerables get(invulerables): Vec; + + /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're easy to initialise + /// and the performance hit is minimal (we expect no more than four invulnerables) and restricted to testnets. + pub Invulnerables get(invulnerables) config(): Vec; + + /// Map from all locked "stash" accounts to the controller account. + pub Bonded get(bonded): map T::AccountId => Option; + /// Map from all (unlocked) "controller" accounts to the info regarding the staking. + pub Ledger get(ledger): map T::AccountId => Option, T::BlockNumber>>; + + /// Where the reward payment should be made. + pub Payee get(payee): map T::AccountId => RewardDestination; + + /// The set of keys are all controllers that want to validate. /// - /// Effects will be felt at the beginning of the next era. - fn stake(origin) { - let who = ensure_signed(origin)?; - ensure!(Self::nominating(&who).is_none(), "Cannot stake if already nominating."); - let mut intentions = >::get(); - // can't be in the list twice. - ensure!(intentions.iter().find(|&t| t == &who).is_none(), "Cannot stake if already staked."); - - >::insert(&who, T::BlockNumber::max_value()); - intentions.push(who); - >::put(intentions); - } + /// The values are the preferences that a validator has. + pub Validators get(validators): linked_map T::AccountId => ValidatorPrefs>; - /// Retract the desire to stake for the transactor. + /// The set of keys are all controllers that want to nominate. /// - /// Effects will be felt at the beginning of the next era. - fn unstake(origin, intentions_index: Compact) -> Result { - let who = ensure_signed(origin)?; - let intentions_index: u32 = intentions_index.into(); - // unstake fails in degenerate case of having too few existing staked parties - if Self::intentions().len() <= Self::minimum_validator_count() as usize { - return Err("cannot unstake when there are too few staked participants") - } - Self::apply_unstake(&who, intentions_index as usize) - } + /// The value are the nominations. + pub Nominators get(nominators): linked_map T::AccountId => Vec; - fn nominate(origin, target: Address) { - let who = ensure_signed(origin)?; - let target = >::lookup(target)?; + /// Nominators for a particular account that is in action right now. You can't iterate through validators here, + /// but you can find them in the `sessions` module. + pub Stakers get(stakers): map T::AccountId => Exposure>; - ensure!(Self::nominating(&who).is_none(), "Cannot nominate if already nominating."); - ensure!(Self::intentions().iter().find(|&t| t == &who).is_none(), "Cannot nominate if already staked."); + // The historical validators and their nominations for a given era. Stored as a trie root of the mapping + // `T::AccountId` => `Exposure>`, which is just the contents of `Stakers`, + // under a key that is the `era`. + // + // Every era change, this will be appended with the trie root of the contents of `Stakers`, and the oldest + // entry removed down to a specific number of entries (probably around 90 for a 3 month history). + // pub HistoricalStakers get(historical_stakers): map T::BlockNumber => Option; - // update nominators_for - let mut t = Self::nominators_for(&target); - t.push(who.clone()); - >::insert(&target, t); + /// The current era index. + pub CurrentEra get(current_era) config(): T::BlockNumber; - // update nominating - >::insert(&who, &target); + /// Maximum reward, per validator, that is provided per acceptable session. + pub CurrentSessionReward get(current_session_reward) config(): BalanceOf; + /// Slash, per validator that is taken for the first time they are found to be offline. + pub CurrentOfflineSlash get(current_offline_slash) config(): BalanceOf; - // Update bondage - >::insert(&who, T::BlockNumber::max_value()); - } + /// The accumulated reward for the current era. Reset to zero at the beginning of the era and + /// increased for every successfully finished session. + pub CurrentEraReward get(current_era_reward): BalanceOf; - /// Will panic if called when source isn't currently nominating target. - /// Updates Nominating, NominatorsFor and NominationBalance. - fn unnominate(origin, target_index: Compact) { - let source = ensure_signed(origin)?; - let target_index: u32 = target_index.into(); - let target_index = target_index as usize; + /// The next value of sessions per era. + pub NextSessionsPerEra get(next_sessions_per_era): Option; + /// The session index at which the era length last changed. + pub LastEraLengthChange get(last_era_length_change): T::BlockNumber; + + /// The amount of balance actively at stake for each validator slot, currently. + /// + /// This is used to derive rewards and punishments. + pub SlotStake get(slot_stake) build(|config: &GenesisConfig| { + config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() + }): BalanceOf; + + /// The number of times a given validator has been reported offline. This gets decremented by one each era that passes. + pub SlashCount get(slash_count): map T::AccountId => u32; - let target = >::get(&source).ok_or("Account must be nominating")?; + /// We are forcing a new era. + pub ForcingNewEra get(forcing_new_era): Option<()>; + + /// Most recent `RECENT_OFFLINE_COUNT` instances. (who it was, when it was reported, how many instances they were offline for). + pub RecentlyOffline get(recently_offline): Vec<(T::AccountId, T::BlockNumber, u32)>; + } + add_extra_genesis { + config(stakers): Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { + with_storage(storage, || { + for &(ref stash, ref controller, balance, ref status) in &config.stakers { + let _ = >::bond( + T::Origin::from(Some(stash.clone()).into()), + T::Lookup::unlookup(controller.clone()), + balance, + RewardDestination::Staked + ); + let _ = match status { + StakerStatus::Validator => { + >::validate( + T::Origin::from(Some(controller.clone()).into()), + Default::default() + ) + }, StakerStatus::Nominator(votes) => { + >::nominate( + T::Origin::from(Some(controller.clone()).into()), + votes.iter().map(|l| {T::Lookup::unlookup(l.clone())}).collect() + ) + }, _ => Ok(()) + }; + } - let mut t = Self::nominators_for(&target); - if t.get(target_index) != Some(&source) { - return Err("Invalid target index") + >::select_validators(); + }); + }); + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + /// Take the origin account as a stash and lock up `value` of its balance. `controller` will be the + /// account that controls it. + fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination) { + let stash = ensure_signed(origin)?; + + if >::exists(&stash) { + return Err("stash already bonded") } - // Ok - all valid. + let controller = T::Lookup::lookup(controller)?; - // update nominators_for - t.swap_remove(target_index); - >::insert(&target, t); + // You're auto-bonded forever, here. We might improve this by only bonding when + // you actually validate/nominate. + >::insert(&stash, controller.clone()); - // update nominating - >::remove(&source); + let stash_balance = T::Currency::free_balance(&stash); + let value = value.min(stash_balance); - // update bondage - >::insert( - source, - >::block_number() + Self::bonding_duration() - ); + Self::update_ledger(&controller, StakingLedger { stash, total: value, active: value, unlocking: vec![] }); + >::insert(&controller, payee); } - /// Set the given account's preference for slashing behaviour should they be a validator. + /// Add some extra amount that have appeared in the stash `free_balance` into the balance up for + /// staking. /// - /// An error (no-op) if `Self::intentions()[intentions_index] != origin`. - fn register_preferences( - origin, - intentions_index: Compact, - prefs: ValidatorPrefs - ) { - let who = ensure_signed(origin)?; - let intentions_index: u32 = intentions_index.into(); - - if Self::intentions().get(intentions_index as usize) != Some(&who) { - return Err("Invalid index") + /// Use this if there are additional funds in your stash account that you wish to bond. + /// + /// NOTE: This call must be made by the controller, not the stash. + fn bond_extra(origin, max_additional: BalanceOf) { + let controller = ensure_signed(origin)?; + let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; + let stash_balance = T::Currency::free_balance(&ledger.stash); + + if stash_balance > ledger.total { + let extra = (stash_balance - ledger.total).min(max_additional); + ledger.total += extra; + ledger.active += extra; + Self::update_ledger(&controller, ledger); } + } + + /// Schedule a portion of the stash to be unlocked ready for transfer out after the bond + /// period ends. If this leaves an amount actively bonded less than + /// T::Currency::existential_deposit(), then it is increased to the full amount. + /// + /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move + /// the funds out of management ready for transfer. + /// + /// NOTE: This call must be made by the controller, not the stash. + /// + /// See also [`Call::withdraw_unbonded`]. + fn unbond(origin, #[compact] value: BalanceOf) { + let controller = ensure_signed(origin)?; + let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; + + let mut value = value.min(ledger.active); + + if !value.is_zero() { + ledger.active -= value; + + // Avoid there being a dust balance left in the staking system. + let ed = T::Currency::minimum_balance(); + if ledger.active < ed { + value += ledger.active; + ledger.active = Zero::zero(); + } + + let era = Self::current_era() + Self::bonding_duration(); + ledger.unlocking.push(UnlockChunk { value, era }); + Self::update_ledger(&controller, ledger); + } + } + + /// Remove any unlocked chunks from the `unlocking` queue from our management. + /// + /// This essentially frees up that balance to be used by the stash account to do + /// whatever it wants. + /// + /// NOTE: This call must be made by the controller, not the stash. + /// + /// See also [`Call::unbond`]. + fn withdraw_unbonded(origin) { + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or("not a controller")?; + let ledger = ledger.consolidate_unlocked(Self::current_era()); + Self::update_ledger(&controller, ledger); + } + + /// Declare the desire to validate for the origin controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// NOTE: This call must be made by the controller, not the stash. + fn validate(origin, prefs: ValidatorPrefs>) { + let controller = ensure_signed(origin)?; + let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + ensure!(prefs.unstake_threshold <= MAX_UNSTAKE_THRESHOLD, "unstake threshold too large"); + >::remove(&controller); + >::insert(controller, prefs); + } + + /// Declare the desire to nominate `targets` for the origin controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// NOTE: This call must be made by the controller, not the stash. + fn nominate(origin, targets: Vec<::Source>) { + let controller = ensure_signed(origin)?; + let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + ensure!(!targets.is_empty(), "targets cannot be empty"); + let targets = targets.into_iter() + .take(MAX_NOMINATIONS) + .map(T::Lookup::lookup) + .collect::, &'static str>>()?; + + >::remove(&controller); + >::insert(controller, targets); + } - >::insert(who, prefs); + /// Declare no desire to either validate or nominate. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// NOTE: This call must be made by the controller, not the stash. + fn chill(origin) { + let controller = ensure_signed(origin)?; + let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + >::remove(&controller); + >::remove(&controller); + } + + /// (Re-)set the payment target for a controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// NOTE: This call must be made by the controller, not the stash. + fn set_payee(origin, payee: RewardDestination) { + let controller = ensure_signed(origin)?; + let _ledger = Self::ledger(&controller).ok_or("not a controller")?; + >::insert(&controller, payee); } /// Set the number of sessions in an era. - fn set_sessions_per_era(new: ::Type) { - >::put(new.into()); + fn set_sessions_per_era(#[compact] new: T::BlockNumber) { + >::put(new); } /// The length of the bonding duration in eras. - fn set_bonding_duration(new: ::Type) { - >::put(new.into()); + fn set_bonding_duration(#[compact] new: T::BlockNumber) { + >::put(new); } /// The ideal number of validators. - fn set_validator_count(new: Compact) { - let new: u32 = new.into(); + fn set_validator_count(#[compact] new: u32) { >::put(new); } @@ -220,16 +472,20 @@ decl_module! { } /// Set the offline slash grace period. - fn set_offline_slash_grace(new: Compact) { - let new: u32 = new.into(); + fn set_offline_slash_grace(#[compact] new: u32) { >::put(new); } + + /// Set the validators who cannot be slashed (if any). + fn set_invulnerables(validators: Vec) { + >::put(validators); + } } } /// An event in this module. decl_event!( - pub enum Event where ::Balance, ::AccountId { + pub enum Event where Balance = BalanceOf, ::AccountId { /// All validators have been rewarded by the given balance. Reward(Balance), /// One validator (and their nominators) has been given a offline-warning (they're still @@ -240,62 +496,6 @@ decl_event!( } ); -pub type PairOf = (T, T); - -decl_storage! { - trait Store for Module as Staking { - - /// The ideal number of staking participants. - pub ValidatorCount get(validator_count) config(): u32; - /// Minimum number of staking participants before emergency conditions are imposed. - pub MinimumValidatorCount get(minimum_validator_count) config(): u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; - /// The length of a staking era in sessions. - pub SessionsPerEra get(sessions_per_era) config(): T::BlockNumber = T::BlockNumber::sa(1000); - /// Maximum reward, per validator, that is provided per acceptable session. - pub SessionReward get(session_reward) config(): Perbill = Perbill::from_billionths(60); - /// Slash, per validator that is taken for the first time they are found to be offline. - pub OfflineSlash get(offline_slash) config(): Perbill = Perbill::from_millionths(1000); // Perbill::from_fraction() is only for std, so use from_millionths(). - /// Number of instances of offline reports before slashing begins for validators. - pub OfflineSlashGrace get(offline_slash_grace) config(): u32; - /// The length of the bonding duration in blocks. - pub BondingDuration get(bonding_duration) config(): T::BlockNumber = T::BlockNumber::sa(1000); - - /// The current era index. - pub CurrentEra get(current_era) config(): T::BlockNumber; - /// Preferences that a validator has. - pub ValidatorPreferences get(validator_preferences): map T::AccountId => ValidatorPrefs; - /// All the accounts with a desire to stake. - pub Intentions get(intentions) config(): Vec; - /// All nominator -> nominee relationships. - pub Nominating get(nominating): map T::AccountId => Option; - /// Nominators for a particular account. - pub NominatorsFor get(nominators_for): map T::AccountId => Vec; - /// Nominators for a particular account that is in action right now. - pub CurrentNominatorsFor get(current_nominators_for): map T::AccountId => Vec; - - /// Maximum reward, per validator, that is provided per acceptable session. - pub CurrentSessionReward get(current_session_reward) config(): T::Balance; - /// Slash, per validator that is taken for the first time they are found to be offline. - pub CurrentOfflineSlash get(current_offline_slash) config(): T::Balance; - - /// The next value of sessions per era. - pub NextSessionsPerEra get(next_sessions_per_era): Option; - /// The session index at which the era length last changed. - pub LastEraLengthChange get(last_era_length_change): T::BlockNumber; - - /// The highest and lowest staked validator slashable balances. - pub StakeRange get(stake_range): PairOf; - - /// The block at which the `who`'s funds become entirely liquid. - pub Bondage get(bondage): map T::AccountId => T::BlockNumber; - /// The number of times a given validator has been reported offline. This gets decremented by one each era that passes. - pub SlashCount get(slash_count): map T::AccountId => u32; - - /// We are forcing a new era. - pub ForcingNewEra get(forcing_new_era): Option<()>; - } -} - impl Module { // Just force_new_era without origin check. fn apply_force_new_era(apply_rewards: bool) -> Result { @@ -310,118 +510,107 @@ impl Module { Self::sessions_per_era() * >::length() } - /// Balance of a (potential) validator that includes all nominators. - pub fn nomination_balance(who: &T::AccountId) -> T::Balance { - Self::nominators_for(who).iter() - .map(>::total_balance) - .fold(Zero::zero(), |acc, x| acc + x) + /// The stashed funds whose staking activities are controlled by `controller` and + /// which are actively in stake right now. + pub fn stash_balance(controller: &T::AccountId) -> BalanceOf { + Self::ledger(controller) + .map_or_else(Zero::zero, |l| l.active) } - /// The total balance that can be slashed from an account. - pub fn slashable_balance(who: &T::AccountId) -> T::Balance { - Self::nominators_for(who).iter() - .map(>::total_balance) - .fold(>::total_balance(who), |acc, x| acc + x) + /// The total balance that can be slashed from a validator controller account as of + /// right now. + pub fn slashable_balance(who: &T::AccountId) -> BalanceOf { + Self::stakers(who).total } - /// The block at which the `who`'s funds become entirely liquid. - pub fn unlock_block(who: &T::AccountId) -> LockStatus { - match Self::bondage(who) { - i if i == T::BlockNumber::max_value() => LockStatus::Bonded, - i if i <= >::block_number() => LockStatus::Liquid, - i => LockStatus::LockedUntil(i), - } - } + // MUTABLES (DANGEROUS) - /// Get the current validators. - pub fn validators() -> Vec { - session::Module::::validators() + /// Update the ledger for a controller. This will also update the stash lock. + fn update_ledger(controller: &T::AccountId, ledger: StakingLedger, T::BlockNumber>) { + T::Currency::set_lock(STAKING_ID, &ledger.stash, ledger.total, T::BlockNumber::max_value(), WithdrawReasons::all()); + >::insert(controller, ledger); } - // PUBLIC MUTABLES (DANGEROUS) - /// Slash a given validator by a specific amount. Removes the slash from their balance by preference, /// and reduces the nominators' balance if needed. - fn slash_validator(v: &T::AccountId, slash: T::Balance) { - // skip the slash in degenerate case of having only 4 staking participants despite having a larger - // desired number of validators (validator_count). - if Self::intentions().len() <= Self::minimum_validator_count() as usize { - return - } - - if let Some(rem) = >::slash(v, slash) { - let noms = Self::current_nominators_for(v); - let total = noms.iter().map(>::total_balance).fold(T::Balance::zero(), |acc, x| acc + x); + fn slash_validator(v: &T::AccountId, slash: BalanceOf) { + // The exposure (backing stake) information of the validator to be slashed. + let exposure = Self::stakers(v); + // The amount we are actually going to slash (can't be bigger than their total exposure) + let slash = slash.min(exposure.total); + // The amount we'll slash from the validator's stash directly. + let own_slash = exposure.own.min(slash); + let own_slash = own_slash - T::Currency::slash(v, own_slash).unwrap_or_default(); + // The amount remaining that we can't slash from the validator, that must be taken from the nominators. + let rest_slash = slash - own_slash; + if !rest_slash.is_zero() { + // The total to be slashed from the nominators. + let total = exposure.total - exposure.own; if !total.is_zero() { - let safe_mul_rational = |b| b * rem / total;// TODO: avoid overflow - for n in noms.iter() { - let _ = >::slash(n, safe_mul_rational(>::total_balance(n))); // best effort - not much that can be done on fail. + let safe_mul_rational = |b| b * rest_slash / total;// FIXME #1572 avoid overflow + for i in exposure.others.iter() { + let _ = T::Currency::slash(&i.who, safe_mul_rational(i.value)); // best effort - not much that can be done on fail. } } } } + /// Actually make a payment to a staker. This uses the currency's reward function + /// to pay the right payee for the given staker account. + fn make_payout(who: &T::AccountId, amount: BalanceOf) { + match Self::payee(who) { + RewardDestination::Controller => { + let _ = T::Currency::reward(&who, amount); + } + RewardDestination::Stash => { + let _ = Self::ledger(who).map(|l| T::Currency::reward(&l.stash, amount)); + } + RewardDestination::Staked => + if let Some(mut l) = Self::ledger(who) { + l.active += amount; + l.total += amount; + let _ = T::Currency::reward(&l.stash, amount); + Self::update_ledger(who, l); + }, + } + } + /// Reward a given validator by a specific amount. Add the reward to their, and their nominators' - /// balance, pro-rata. - fn reward_validator(who: &T::AccountId, reward: T::Balance) { - let off_the_table = reward.min(Self::validator_preferences(who).validator_payment); + /// balance, pro-rata based on their exposure, after having removed the validator's pre-payout cut. + fn reward_validator(who: &T::AccountId, reward: BalanceOf) { + let off_the_table = reward.min(Self::validators(who).validator_payment); let reward = reward - off_the_table; let validator_cut = if reward.is_zero() { Zero::zero() } else { - let noms = Self::current_nominators_for(who); - let total = noms.iter() - .map(>::total_balance) - .fold(>::total_balance(who), |acc, x| acc + x) - .max(One::one()); - let safe_mul_rational = |b| b * reward / total;// TODO: avoid overflow - for n in noms.iter() { - let _ = >::reward(n, safe_mul_rational(>::total_balance(n))); + let exposure = Self::stakers(who); + let total = exposure.total.max(One::one()); + let safe_mul_rational = |b| b * reward / total;// FIXME #1572: avoid overflow + for i in &exposure.others { + Self::make_payout(&i.who, safe_mul_rational(i.value)); } - safe_mul_rational(>::total_balance(who)) + safe_mul_rational(exposure.own) }; - let _ = >::reward(who, validator_cut + off_the_table); - } - - /// Actually carry out the unstake operation. - /// Assumes `intentions()[intentions_index] == who`. - fn apply_unstake(who: &T::AccountId, intentions_index: usize) -> Result { - let mut intentions = Self::intentions(); - if intentions.get(intentions_index) != Some(who) { - return Err("Invalid index"); - } - intentions.swap_remove(intentions_index); - >::put(intentions); - >::remove(who); - >::remove(who); - >::insert(who, >::block_number() + Self::bonding_duration()); - Ok(()) + Self::make_payout(who, validator_cut + off_the_table); } /// Get the reward for the session, assuming it ends with this block. - fn this_session_reward(actual_elapsed: T::Moment) -> T::Balance { + fn this_session_reward(actual_elapsed: T::Moment) -> BalanceOf { let ideal_elapsed = >::ideal_session_duration(); if ideal_elapsed.is_zero() { return Self::current_session_reward(); } let per65536: u64 = (T::Moment::sa(65536u64) * ideal_elapsed.clone() / actual_elapsed.max(ideal_elapsed)).as_(); - Self::current_session_reward() * T::Balance::sa(per65536) / T::Balance::sa(65536u64) + Self::current_session_reward() * >::sa(per65536) / >::sa(65536u64) } /// Session has just changed. We need to determine whether we pay a reward, slash and/or /// move to a new era. fn new_session(actual_elapsed: T::Moment, should_reward: bool) { if should_reward { - // apply good session reward + // accumulate good session reward let reward = Self::this_session_reward(actual_elapsed); - let validators = >::validators(); - for v in validators.iter() { - Self::reward_validator(v, reward); - } - Self::deposit_event(RawEvent::Reward(reward)); - let total_minted = reward * >::sa(validators.len()); - let total_rewarded_stake = Self::stake_range().1 * >::sa(validators.len()); - T::OnRewardMinted::on_dilution(total_minted, total_rewarded_stake); + >::mutate(|r| *r += reward); } let session_index = >::current_index(); @@ -437,6 +626,19 @@ impl Module { /// NOTE: This always happens immediately before a session change to ensure that new validators /// get a chance to set their session keys. fn new_era() { + // Payout + let reward = >::take(); + if !reward.is_zero() { + let validators = >::validators(); + for v in validators.iter() { + Self::reward_validator(v, reward); + } + Self::deposit_event(RawEvent::Reward(reward)); + let total_minted = reward * as As>::sa(validators.len()); + let total_rewarded_stake = Self::slot_stake() * as As>::sa(validators.len()); + T::OnRewardMinted::on_dilution(total_minted, total_rewarded_stake); + } + // Increment current era. >::put(&(>::get() + One::one())); @@ -448,52 +650,61 @@ impl Module { } } - // evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::internal::set_validators(). - // for now, this just orders would-be stakers by their balances and chooses the top-most - // >::get() of them. - // TODO: this is not sound. this should be moved to an off-chain solution mechanism. - let mut intentions = Self::intentions() - .into_iter() - .map(|v| (Self::slashable_balance(&v), v)) - .collect::>(); - - // Avoid reevaluate validator set if it would leave us with fewer than the minimum - // needed validators - if intentions.len() < Self::minimum_validator_count() as usize { - return - } - - intentions.sort_unstable_by(|&(ref b1, _), &(ref b2, _)| b2.cmp(&b1)); + // Reassign all Stakers. + let slot_stake = Self::select_validators(); - let desired_validator_count = >::get() as usize; - let stake_range = if !intentions.is_empty() { - let n = cmp::min(desired_validator_count, intentions.len()); - (intentions[0].0, intentions[n - 1].0) - } else { - (Zero::zero(), Zero::zero()) - }; - >::put(&stake_range); + // Update the balances for slashing/rewarding according to the stakes. + >::put(Self::offline_slash() * slot_stake); + >::put(Self::session_reward() * slot_stake); + } - let vals = &intentions.into_iter() - .map(|(_, v)| v) - .take(desired_validator_count) - .collect::>(); + /// Select a new validator set from the assembled stakers and their role preferences. + /// + /// @returns the new SlotStake value. + fn select_validators() -> BalanceOf { + // Map of (would-be) validator account to amount of stake backing it. + + let rounds = || >::get() as usize; + let validators = || >::enumerate(); + let nominators = || >::enumerate(); + let stash_of = |w| Self::stash_balance(&w); + let min_validator_count = Self::minimum_validator_count() as usize; + let elected_candidates = phragmen::elect::( + rounds, + validators, + nominators, + stash_of, + min_validator_count + ); + + // Figure out the minimum stake behind a slot. + let slot_stake = elected_candidates + .iter() + .min_by_key(|c| c.exposure.total) + .map(|c| c.exposure.total) + .unwrap_or_default(); + >::put(&slot_stake); + + // Clear Stakers and reduce their slash_count. for v in >::validators().iter() { - >::remove(v); + >::remove(v); let slash_count = >::take(v); if slash_count > 1 { >::insert(v, slash_count - 1); } } - for v in vals.iter() { - >::insert(v, Self::nominators_for(v)); + + // Populate Stakers. + for candidate in &elected_candidates { + >::insert(candidate.who.clone(), candidate.exposure.clone()); } - >::set_validators(vals); - // Update the balances for slashing/rewarding according to the stakes. - >::put(Self::offline_slash().times(stake_range.1)); - >::put(Self::session_reward().times(stake_range.1)); + // Set the new validator set. + >::set_validators( + &elected_candidates.into_iter().map(|i| i.who).collect::>() + ); + + slot_stake } /// Call when a validator is determined to be offline. `count` is the @@ -501,48 +712,56 @@ impl Module { pub fn on_offline_validator(v: T::AccountId, count: usize) { use primitives::traits::CheckedShl; - for _ in 0..count { - let slash_count = Self::slash_count(&v); - >::insert(v.clone(), slash_count + 1); - let grace = Self::offline_slash_grace(); - - let event = if slash_count >= grace { - let instances = slash_count - grace; - - let base_slash = Self::current_offline_slash(); - let slash = match base_slash.checked_shl(instances) { - Some(slash) => slash, - None => { - // freeze at last maximum valid slash if this starts - // to overflow. - >::insert(v.clone(), slash_count); - base_slash.checked_shl(instances - 1) - .expect("slash count no longer incremented after overflow; \ - prior check only fails with instances >= 1; \ - thus instances - 1 always works and is a valid amount of bits; qed") - } - }; - - let next_slash = slash << 1; - - let _ = Self::slash_validator(&v, slash); - if instances >= Self::validator_preferences(&v).unstake_threshold - || Self::slashable_balance(&v) < next_slash - { - if let Some(pos) = Self::intentions().into_iter().position(|x| &x == &v) { - Self::apply_unstake(&v, pos) - .expect("pos derived correctly from Self::intentions(); \ - apply_unstake can only fail if pos wrong; \ - Self::intentions() doesn't change; qed"); - } - let _ = Self::apply_force_new_era(false); - } - RawEvent::OfflineSlash(v.clone(), slash) + // Early exit if validator is invulnerable. + if Self::invulnerables().contains(&v) { + return + } + // TODO: remove once Alex/CC updated #1785 + if Self::invulerables().contains(&v) { + return + } + + let slash_count = Self::slash_count(&v); + let new_slash_count = slash_count + count as u32; + >::insert(&v, new_slash_count); + let grace = Self::offline_slash_grace(); + + if RECENT_OFFLINE_COUNT > 0 { + let item = (v.clone(), >::block_number(), count as u32); + >::mutate(|v| if v.len() >= RECENT_OFFLINE_COUNT { + let index = v.iter() + .enumerate() + .min_by_key(|(_, (_, block, _))| block) + .expect("v is non-empty; qed") + .0; + v[index] = item; } else { - RawEvent::OfflineWarning(v.clone(), slash_count) - }; - Self::deposit_event(event); + v.push(item); + }); } + + let prefs = Self::validators(&v); + let unstake_threshold = prefs.unstake_threshold.min(MAX_UNSTAKE_THRESHOLD); + let max_slashes = grace + unstake_threshold; + + let event = if new_slash_count > max_slashes { + let slot_stake = Self::slot_stake(); + // They're bailing. + let slash = Self::current_offline_slash() + // Multiply current_offline_slash by 2^(unstake_threshold with upper bound) + .checked_shl(unstake_threshold) + .map(|x| x.min(slot_stake)) + .unwrap_or(slot_stake); + let _ = Self::slash_validator(&v, slash); + >::remove(&v); + let _ = Self::apply_force_new_era(false); + + RawEvent::OfflineSlash(v.clone(), slash) + } else { + RawEvent::OfflineWarning(v.clone(), slash_count) + }; + + Self::deposit_event(event); } } @@ -552,19 +771,15 @@ impl OnSessionChange for Module { } } -impl balances::EnsureAccountLiquid for Module { - fn ensure_account_liquid(who: &T::AccountId) -> Result { - if Self::bondage(who) <= >::block_number() { - Ok(()) - } else { - Err("cannot transfer illiquid funds") - } - } -} - -impl balances::OnFreeBalanceZero for Module { +impl OnFreeBalanceZero for Module { fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who); + if let Some(controller) = >::take(who) { + >::remove(&controller); + >::remove(&controller); + >::remove(&controller); + >::remove(&controller); + >::remove(&controller); + } } } diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index a434b4510be8fb315697f0971afef58a362ce8d1..6a76f350efbeab86c28c444b2787db7b0f66aff2 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,12 +18,15 @@ #![cfg(test)] -use primitives::BuildStorage; -use primitives::{Perbill, traits::Identity}; -use primitives::testing::{Digest, DigestItem, Header}; +use primitives::{traits::IdentityLookup, BuildStorage, Perbill}; +use primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, ConvertUintAuthorityId}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use {GenesisConfig, Module, Trait, consensus, session, system, timestamp, balances}; +use srml_support::impl_outer_origin; +use crate::{GenesisConfig, Module, Trait, StakerStatus}; + +// The AccountId alias in this test module. +pub type AccountIdType = u64; impl_outer_origin!{ pub enum Origin for Test {} @@ -33,9 +36,8 @@ impl_outer_origin!{ #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; impl consensus::Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; type Log = DigestItem; - type SessionKey = u64; + type SessionKey = UintAuthorityId; type InherentOfflineReport = (); } impl system::Trait for Test { @@ -45,89 +47,192 @@ impl system::Trait for Test { type Hash = H256; type Hashing = ::primitives::traits::BlakeTwo256; type Digest = Digest; - type AccountId = u64; + type AccountId = AccountIdType; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; type OnFreeBalanceZero = Staking; - type EnsureAccountLiquid = Staking; + type OnNewAccount = (); type Event = (); } impl session::Trait for Test { - type ConvertAccountIdToSessionKey = Identity; + type ConvertAccountIdToSessionKey = ConvertUintAuthorityId; type OnSessionChange = Staking; type Event = (); } impl timestamp::Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; type Moment = u64; type OnTimestampSet = (); } impl Trait for Test { + type Currency = balances::Module; type OnRewardMinted = (); type Event = (); } -pub fn new_test_ext( - ext_deposit: u64, +pub struct ExtBuilder { + existential_deposit: u64, session_length: u64, sessions_per_era: u64, current_era: u64, monied: bool, - reward: u64 -) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; - let balance_factor = if ext_deposit > 0 { - 256 - } else { - 1 - }; - t.extend(consensus::GenesisConfig::{ - code: vec![], - authorities: vec![], - }.build_storage().unwrap().0); - t.extend(session::GenesisConfig::{ - session_length, - validators: vec![10, 20], - }.build_storage().unwrap().0); - t.extend(balances::GenesisConfig::{ - balances: if monied { - if reward > 0 { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor), (10, balance_factor), (20, balance_factor)] - } else { - vec![(1, 10 * balance_factor), (2, 20 * balance_factor), (3, 30 * balance_factor), (4, 40 * balance_factor)] - } + reward: u64, + validator_pool: bool, + nominate: bool, + validator_count: u32, + minimum_validator_count: u32, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + existential_deposit: 0, + session_length: 1, + sessions_per_era: 1, + current_era: 0, + monied: true, + reward: 10, + validator_pool: false, + nominate: true, + validator_count: 2, + minimum_validator_count: 0, + } + } +} + +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + pub fn session_length(mut self, session_length: u64) -> Self { + self.session_length = session_length; + self + } + pub fn sessions_per_era(mut self, sessions_per_era: u64) -> Self { + self.sessions_per_era = sessions_per_era; + self + } + pub fn _current_era(mut self, current_era: u64) -> Self { + self.current_era = current_era; + self + } + pub fn _monied(mut self, monied: bool) -> Self { + self.monied = monied; + self + } + pub fn reward(mut self, reward: u64) -> Self { + self.reward = reward; + self + } + pub fn validator_pool(mut self, validator_pool: bool) -> Self { + // NOTE: this should only be set to true with monied = false. + self.validator_pool = validator_pool; + self + } + pub fn nominate(mut self, nominate: bool) -> Self { + // NOTE: this only sets a dummy nominator for tests that want 10 and 20 (default validators) to be chosen by default. + self.nominate = nominate; + self + } + pub fn validator_count(mut self, count: u32) -> Self { + self.validator_count = count; + self + } + pub fn minimum_validator_count(mut self, count: u32) -> Self { + self.minimum_validator_count = count; + self + } + pub fn build(self) -> runtime_io::TestExternalities { + let (mut t, mut c) = system::GenesisConfig::::default().build_storage().unwrap(); + let balance_factor = if self.existential_deposit > 0 { + 256 } else { - vec![(10, balance_factor), (20, balance_factor)] - }, - transaction_base_fee: 0, - transaction_byte_fee: 0, - existential_deposit: ext_deposit, - transfer_fee: 0, - creation_fee: 0, - reclaim_rebate: 0, - }.build_storage().unwrap().0); - t.extend(GenesisConfig::{ - sessions_per_era, - current_era, - intentions: vec![10, 20], - validator_count: 2, - minimum_validator_count: 0, - bonding_duration: sessions_per_era * session_length * 3, - session_reward: Perbill::from_millionths((1000000 * reward / balance_factor) as u32), - offline_slash: if monied { Perbill::from_percent(40) } else { Perbill::zero() }, - current_session_reward: reward, - current_offline_slash: 20, - offline_slash_grace: 0, - }.build_storage().unwrap().0); - t.extend(timestamp::GenesisConfig::{ - period: 5, - }.build_storage().unwrap().0); - runtime_io::TestExternalities::new(t) + 1 + }; + let _ = consensus::GenesisConfig::{ + code: vec![], + authorities: vec![], + }.assimilate_storage(&mut t, &mut c); + let _ = session::GenesisConfig::{ + session_length: self.session_length, + // NOTE: if config.nominate == false then 100 is also selected in the initial round. + validators: if self.validator_pool { vec![10, 20, 30, 40] } else { vec![10, 20] }, + keys: vec![], + }.assimilate_storage(&mut t, &mut c); + let _ = balances::GenesisConfig::{ + balances: if self.monied { + if self.reward > 0 { + vec![ + (1, 10 * balance_factor), + (2, 20 * balance_factor), + (3, 300 * balance_factor), + (4, 400 * balance_factor), + (10, balance_factor), + (11, balance_factor * 1000), + (20, balance_factor), + (21, balance_factor * 2000), + (100, 2000 * balance_factor), + (101, 2000 * balance_factor), + ] + } else { + vec![ + (1, 10 * balance_factor), (2, 20 * balance_factor), + (3, 300 * balance_factor), (4, 400 * balance_factor) + ] + } + } else { + vec![ + (10, balance_factor), (11, balance_factor * 10), + (20, balance_factor), (21, balance_factor * 20), + (30, balance_factor), (31, balance_factor * 30), + (40, balance_factor), (41, balance_factor * 40) + ] + }, + existential_deposit: self.existential_deposit, + transfer_fee: 0, + creation_fee: 0, + vesting: vec![], + }.assimilate_storage(&mut t, &mut c); + let _ = GenesisConfig::{ + sessions_per_era: self.sessions_per_era, + current_era: self.current_era, + stakers: if self.validator_pool { + vec![ + (11, 10, balance_factor * 1000, StakerStatus::::Validator), + (21, 20, balance_factor * 2000, StakerStatus::::Validator), + (31, 30, balance_factor * 3000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }), + (41, 40, balance_factor * 4000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }), + // nominator + (101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![10, 20]) } else { StakerStatus::::Nominator(vec![]) }) + ] + } else { + vec![ + (11, 10, balance_factor * 1000, StakerStatus::::Validator), + (21, 20, balance_factor * 2000, StakerStatus::::Validator), + // nominator + (101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![10, 20]) } else { StakerStatus::::Nominator(vec![]) }) + ] + }, + validator_count: self.validator_count, + minimum_validator_count: self.minimum_validator_count, + bonding_duration: self.sessions_per_era * self.session_length * 3, + session_reward: Perbill::from_millionths((1000000 * self.reward / balance_factor) as u32), + offline_slash: if self.monied { Perbill::from_percent(40) } else { Perbill::zero() }, + current_session_reward: self.reward, + current_offline_slash: 20, + offline_slash_grace: 0, + invulnerables: vec![], + }.assimilate_storage(&mut t, &mut c); + let _ = timestamp::GenesisConfig::{ + period: 5, + }.assimilate_storage(&mut t, &mut c); + t.into() + } } pub type System = system::Module; diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs new file mode 100644 index 0000000000000000000000000000000000000000..bdaed1fee976041e20f71cb335ebe411f7a285fa --- /dev/null +++ b/srml/staking/src/phragmen.rs @@ -0,0 +1,223 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Rust implementation of the Phragmén election algorithm. + +use rstd::{prelude::*}; +use primitives::Perquintill; +use primitives::traits::{Zero, As}; +use parity_codec::{HasCompact, Encode, Decode}; +use crate::{Exposure, BalanceOf, Trait, ValidatorPrefs, IndividualExposure}; + +// Wrapper around validation candidates some metadata. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Candidate { + // The validator's account + pub who: AccountId, + // Exposure struct, holding info about the value that the validator has in stake. + pub exposure: Exposure, + // Accumulator of the stake of this candidate based on received votes. + approval_stake: Balance, + // Intermediary value used to sort candidates. + // See Phragmén reference implementation. + pub score: Perquintill, +} + +// Wrapper around the nomination info of a single nominator for a group of validators. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Nominations { + // The nominator's account. + who: AccountId, + // List of validators proposed by this nominator. + nominees: Vec>, + // the stake amount proposed by the nominator as a part of the vote. + // Same as `nom.budget` in Phragmén reference. + stake: Balance, + // Incremented each time a nominee that this nominator voted for has been elected. + load: Perquintill, +} + +// Wrapper around a nominator vote and the load of that vote. +// Referred to as 'edge' in the Phragmén reference implementation. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Vote { + // Account being voted for + who: AccountId, + // Load of this vote. + load: Perquintill, + // Final backing stake of this vote. + backing_stake: Balance +} + +/// Perform election based on Phragmén algorithm. +/// +/// Reference implementation: https://github.com/w3f/consensus +/// +/// @returns a vector of elected candidates +pub fn elect( + get_rounds: FR, + get_validators: FV, + get_nominators: FN, + stash_of: FS, + minimum_validator_count: usize, + ) -> Vec>> where + FR: Fn() -> usize, + FV: Fn() -> Box>) + >>, + FN: Fn() -> Box) + >>, + FS: Fn(T::AccountId) -> BalanceOf, +{ + let rounds = get_rounds(); + let mut elected_candidates = vec![]; + + // 1- Pre-process candidates and place them in a container + let mut candidates = get_validators().map(|(who, _)| { + let stash_balance = stash_of(who.clone()); + Candidate { + who, + approval_stake: BalanceOf::::zero(), + score: Perquintill::zero(), + exposure: Exposure { total: stash_balance, own: stash_balance, others: vec![] }, + } + }).collect::>>>(); + + // Just to be used when we are below minimum validator count + let original_candidates = candidates.clone(); + + // 2- Collect the nominators with the associated votes. + // Also collect approval stake along the way. + let mut nominations = get_nominators().map(|(who, nominees)| { + let nominator_stake = stash_of(who.clone()); + for n in &nominees { + candidates.iter_mut().filter(|i| i.who == *n).for_each(|c| { + c.approval_stake += nominator_stake; + }); + } + + Nominations { + who, + nominees: nominees.into_iter() + .map(|n| Vote {who: n, load: Perquintill::zero(), backing_stake: BalanceOf::::zero()}) + .collect::>>>(), + stake: nominator_stake, + load : Perquintill::zero(), + } + }).collect::>>>(); + + // 3- optimization: + // Candidates who have 0 stake => have no votes or all null-votes. Kick them out not. + let mut candidates = candidates.into_iter().filter(|c| c.approval_stake > BalanceOf::::zero()) + .collect::>>>(); + + // 4- If we have more candidates then needed, run Phragmén. + if candidates.len() > rounds { + // Main election loop + for _round in 0..rounds { + // Loop 1: initialize score + for nominaotion in &nominations { + for vote in &nominaotion.nominees { + let candidate = &vote.who; + if let Some(c) = candidates.iter_mut().find(|i| i.who == *candidate) { + let approval_stake = c.approval_stake; + c.score = Perquintill::from_xth(approval_stake.as_()); + } + } + } + // Loop 2: increment score. + for nominaotion in &nominations { + for vote in &nominaotion.nominees { + let candidate = &vote.who; + if let Some(c) = candidates.iter_mut().find(|i| i.who == *candidate) { + let approval_stake = c.approval_stake; + let temp = + nominaotion.stake.as_() + * *nominaotion.load + / approval_stake.as_(); + c.score = Perquintill::from_quintillionths(*c.score + temp); + } + } + } + + // Find the best + let (winner_index, _) = candidates.iter().enumerate().min_by_key(|&(_i, c)| *c.score) + .expect("candidates length is checked to be >0; qed"); + + // loop 3: update nominator and vote load + let winner = candidates.remove(winner_index); + for n in &mut nominations { + for v in &mut n.nominees { + if v.who == winner.who { + v.load = + Perquintill::from_quintillionths( + *winner.score + - *n.load + ); + n.load = winner.score; + } + } + } + + elected_candidates.push(winner); + + } // end of all rounds + + // 4.1- Update backing stake of candidates and nominators + for n in &mut nominations { + for v in &mut n.nominees { + // if the target of this vote is among the winners, otherwise let go. + if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == v.who) { + v.backing_stake = as As>::sa( + n.stake.as_() + * *v.load + / *n.load + ); + c.exposure.total += v.backing_stake; + // Update IndividualExposure of those who nominated and their vote won + c.exposure.others.push( + IndividualExposure {who: n.who.clone(), value: v.backing_stake } + ); + } + } + } + } else { + if candidates.len() > minimum_validator_count { + // if we don't have enough candidates, just choose all that have some vote. + elected_candidates = candidates; + // `Exposure.others` still needs an update + for n in &mut nominations { + for v in &mut n.nominees { + if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == v.who) { + c.exposure.total += n.stake; + c.exposure.others.push( + IndividualExposure {who: n.who.clone(), value: n.stake } + ); + } + } + } + } else { + // if we have less than minimum, use the previous validator set. + elected_candidates = original_candidates; + } + } + + elected_candidates +} \ No newline at end of file diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index 88ce66c8d79e1d8edf2de1732d6b75b763d50407..7921d7f3130275a6d7a5f05457880efbcfd5a932 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,406 +20,750 @@ use super::*; use runtime_io::with_externalities; -use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext, Origin}; +use phragmen; +use primitives::Perquintill; +use srml_support::{assert_ok, assert_noop, EnumerableStorageMap}; +use mock::{Balances, Session, Staking, System, Timestamp, Test, ExtBuilder, Origin}; +use srml_support::traits::Currency; #[test] -fn note_null_offline_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { +fn basic_setup_works() { + // Verifies initial conditions of mock + with_externalities(&mut ExtBuilder::default() + .build(), + || { + assert_eq!(Staking::bonded(&11), Some(10)); // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&21), Some(20)); // Account 21 is stashed and locked, and account 20 is the controller + assert_eq!(Staking::bonded(&1), None); // Account 1 is not a stashed + + // Account 10 controls the stash from account 11, which is 100 * balance_factor units + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + // Account 20 controls the stash from account 21, which is 200 * balance_factor units + assert_eq!(Staking::ledger(&20), Some(StakingLedger { stash: 21, total: 2000, active: 2000, unlocking: vec![] })); + // Account 1 does not control any stash + assert_eq!(Staking::ledger(&1), None); + + // ValidatorPrefs are default, thus unstake_threshold is 3, other values are default for their type + assert_eq!(>::enumerate().collect::>(), vec![ + (20, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }), + (10, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }) + ]); + + // Account 100 is the default nominator + assert_eq!(Staking::ledger(100), Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] })); + assert_eq!(Staking::nominators(100), vec![10, 20]); + + // Account 10 is exposed by 100 * balance_factor from their own stash in account 11 + assert_eq!(Staking::stakers(10), Exposure { total: 1500, own: 1000, others: vec![ IndividualExposure { who: 100, value: 500 }] }); + assert_eq!(Staking::stakers(20), Exposure { total: 2500, own: 2000, others: vec![ IndividualExposure { who: 100, value: 500 }] }); + + // The number of validators required. + assert_eq!(Staking::validator_count(), 2); + + // Initial Era and session + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + // initial rewards + assert_eq!(Staking::current_session_reward(), 10); + + // initial slot_stake + assert_eq!(Staking::slot_stake(), 1500); + + // initial slash_count of validators + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Staking::slash_count(&20), 0); + }); +} + +#[test] +fn no_offline_should_work() { + // Test the staking module works when no validators are offline + with_externalities(&mut ExtBuilder::default().build(), + || { + // Slashing begins for validators immediately if found offline assert_eq!(Staking::offline_slash_grace(), 0); + // Account 10 has not been reported offline assert_eq!(Staking::slash_count(&10), 0); + // Account 10 has `balance_factor` free balance assert_eq!(Balances::free_balance(&10), 1); - System::set_extrinsic_index(1); + // Nothing happens to Account 10, as expected assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 1); + // New era is not being forced assert!(Staking::forcing_new_era().is_none()); }); } #[test] -fn note_offline_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { +fn invulnerability_should_work() { + // Test that users can be invulnerable from slashing and being kicked + with_externalities(&mut ExtBuilder::default().build(), + || { + // Make account 10 invulnerable + assert_ok!(Staking::set_invulnerables(vec![10])); + // Give account 10 some funds Balances::set_free_balance(&10, 70); + // There is no slash grace -- slash immediately. assert_eq!(Staking::offline_slash_grace(), 0); + // Account 10 has not been slashed assert_eq!(Staking::slash_count(&10), 0); + // Account 10 has the 70 funds we gave it above assert_eq!(Balances::free_balance(&10), 70); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Balances::free_balance(&10), 50); + // Account 10 should be a validator + assert!(>::exists(&10)); + + // Set account 10 as an offline validator with a large number of reports + // Should exit early if invulnerable + Staking::on_offline_validator(10, 100); + + // Show that account 10 has not been touched + assert_eq!(Staking::slash_count(&10), 0); + assert_eq!(Balances::free_balance(&10), 70); + assert!(>::exists(&10)); + // New era not being forced + // NOTE: new era is always forced once slashing happens -> new validators need to be chosen. assert!(Staking::forcing_new_era().is_none()); }); } #[test] -fn note_offline_exponent_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Balances::set_free_balance(&10, 150); +fn offline_should_slash_and_kick() { + // Test that an offline validator gets slashed and kicked + with_externalities(&mut ExtBuilder::default().build(), || { + // Give account 10 some balance + Balances::set_free_balance(&10, 1000); + // Confirm account 10 is a validator + assert!(>::exists(&10)); + // Validators get slashed immediately assert_eq!(Staking::offline_slash_grace(), 0); + // Unstake threshold is 3 + assert_eq!(Staking::validators(&10).unstake_threshold, 3); + // Account 10 has not been slashed before assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Balances::free_balance(&10), 150); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Balances::free_balance(&10), 130); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Balances::free_balance(&10), 90); - assert!(Staking::forcing_new_era().is_none()); + // Account 10 has the funds we just gave it + assert_eq!(Balances::free_balance(&10), 1000); + // Report account 10 as offline, one greater than unstake threshold + Staking::on_offline_validator(10, 4); + // Confirm user has been reported + assert_eq!(Staking::slash_count(&10), 4); + // Confirm `slot_stake` is greater than exponential punishment, else math below will be different + assert!(Staking::slot_stake() > 2_u64.pow(3) * 20); + // Confirm balance has been reduced by 2^unstake_threshold * current_offline_slash() + assert_eq!(Balances::free_balance(&10), 1000 - 2_u64.pow(3) * 20); + // Confirm account 10 has been removed as a validator + assert!(!>::exists(&10)); + // A new era is forced due to slashing + assert!(Staking::forcing_new_era().is_some()); }); } #[test] -fn note_offline_grace_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { +fn offline_grace_should_delay_slashing() { + // Tests that with grace, slashing is delayed + with_externalities(&mut ExtBuilder::default().build(), || { + // Initialize account 10 with balance Balances::set_free_balance(&10, 70); - Balances::set_free_balance(&20, 70); - assert_ok!(Staking::set_offline_slash_grace(1.into())); + // Verify account 10 has balance + assert_eq!(Balances::free_balance(&10), 70); + + // Set offline slash grace + let offline_slash_grace = 1; + assert_ok!(Staking::set_offline_slash_grace(offline_slash_grace)); assert_eq!(Staking::offline_slash_grace(), 1); + // Check unstaked_threshold is 3 (default) + let default_unstake_threshold = 3; + assert_eq!(Staking::validators(&10), ValidatorPrefs { unstake_threshold: default_unstake_threshold, validator_payment: 0 }); + + // Check slash count is zero assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Balances::free_balance(&10), 70); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&10), 1); + // Report account 10 up to the threshold + Staking::on_offline_validator(10, default_unstake_threshold as usize + offline_slash_grace as usize); + // Confirm slash count + assert_eq!(Staking::slash_count(&10), 4); + + // Nothing should happen assert_eq!(Balances::free_balance(&10), 70); - assert_eq!(Staking::slash_count(&20), 0); - assert_eq!(Balances::free_balance(&20), 70); - System::set_extrinsic_index(1); + // Report account 10 one more time Staking::on_offline_validator(10, 1); - Staking::on_offline_validator(20, 1); - assert_eq!(Staking::slash_count(&10), 2); - assert_eq!(Balances::free_balance(&10), 50); - assert_eq!(Staking::slash_count(&20), 1); - assert_eq!(Balances::free_balance(&20), 70); - assert!(Staking::forcing_new_era().is_none()); + assert_eq!(Staking::slash_count(&10), 5); + // User gets slashed + assert_eq!(Balances::free_balance(&10), 0); + // New era is forced + assert!(Staking::forcing_new_era().is_some()); }); } + #[test] -fn note_offline_force_unstake_session_change_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Balances::set_free_balance(&10, 70); - Balances::set_free_balance(&20, 70); - assert_ok!(Staking::stake(Origin::signed(1))); +fn max_unstake_threshold_works() { + // Tests that max_unstake_threshold gets used when prefs.unstake_threshold is large + with_externalities(&mut ExtBuilder::default().build(), || { + const MAX_UNSTAKE_THRESHOLD: u32 = 10; + // Two users with maximum possible balance + Balances::set_free_balance(&10, u64::max_value()); + Balances::set_free_balance(&20, u64::max_value()); + + // Give them full exposer as a staker + >::insert(&10, Exposure { total: u64::max_value(), own: u64::max_value(), others: vec![]}); + >::insert(&20, Exposure { total: u64::max_value(), own: u64::max_value(), others: vec![]}); + + // Check things are initialized correctly + assert_eq!(Balances::free_balance(&10), u64::max_value()); + assert_eq!(Balances::free_balance(&20), u64::max_value()); + assert_eq!(Balances::free_balance(&10), Balances::free_balance(&20)); + assert_eq!(Staking::offline_slash_grace(), 0); + assert_eq!(Staking::current_offline_slash(), 20); + // Account 10 will have max unstake_threshold + assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { + unstake_threshold: MAX_UNSTAKE_THRESHOLD, + validator_payment: 0, + })); + // Account 20 could not set their unstake_threshold past 10 + assert_noop!(Staking::validate(Origin::signed(20), ValidatorPrefs { + unstake_threshold: 11, + validator_payment: 0}), + "unstake threshold too large" + ); + // Give Account 20 unstake_threshold 11 anyway, should still be limited to 10 + >::insert(20, ValidatorPrefs { + unstake_threshold: 11, + validator_payment: 0, + }); - assert_eq!(Staking::slash_count(&10), 0); - assert_eq!(Balances::free_balance(&10), 70); - assert_eq!(Staking::intentions(), vec![10, 20, 1]); - assert_eq!(Session::validators(), vec![10, 20]); + // Make slot_stake really large, as to not affect punishment curve + >::put(u64::max_value()); + // Confirm `slot_stake` is greater than exponential punishment, else math below will be different + assert!(Staking::slot_stake() > 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Balances::free_balance(&10), 50); - assert_eq!(Staking::slash_count(&10), 1); - assert_eq!(Staking::intentions(), vec![10, 20, 1]); + // Report each user 1 more than the max_unstake_threshold + Staking::on_offline_validator(10, MAX_UNSTAKE_THRESHOLD as usize + 1); + Staking::on_offline_validator(20, MAX_UNSTAKE_THRESHOLD as usize + 1); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::intentions(), vec![1, 20]); - assert_eq!(Balances::free_balance(&10), 10); - assert!(Staking::forcing_new_era().is_some()); + // Show that each balance only gets reduced by 2^max_unstake_threshold + assert_eq!(Balances::free_balance(&10), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); + assert_eq!(Balances::free_balance(&20), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 20); }); } #[test] -fn note_offline_auto_unstake_session_change_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - Balances::set_free_balance(&10, 7000); - Balances::set_free_balance(&20, 7000); - assert_ok!(Staking::register_preferences(Origin::signed(10), 0.into(), ValidatorPrefs { unstake_threshold: 1, validator_payment: 0 })); +fn slashing_does_not_cause_underflow() { + // Tests that slashing more than a user has does not underflow + with_externalities(&mut ExtBuilder::default().build(), || { + // One user with less than `max_value` will test underflow does not occur + Balances::set_free_balance(&10, 1); - assert_eq!(Staking::intentions(), vec![10, 20]); + // Verify initial conditions + assert_eq!(Balances::free_balance(&10), 1); + assert_eq!(Staking::offline_slash_grace(), 0); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - Staking::on_offline_validator(20, 1); - assert_eq!(Balances::free_balance(&10), 6980); - assert_eq!(Balances::free_balance(&20), 6980); - assert_eq!(Staking::intentions(), vec![10, 20]); - assert!(Staking::forcing_new_era().is_none()); + // Set validator preference so that 2^unstake_threshold would cause overflow (greater than 64) + >::insert(10, ValidatorPrefs { + unstake_threshold: 10, + validator_payment: 0, + }); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - Staking::on_offline_validator(20, 1); - assert_eq!(Balances::free_balance(&10), 6940); - assert_eq!(Balances::free_balance(&20), 6940); - assert_eq!(Staking::intentions(), vec![20]); - assert!(Staking::forcing_new_era().is_some()); + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); - System::set_extrinsic_index(1); - Staking::on_offline_validator(20, 1); - assert_eq!(Balances::free_balance(&10), 6940); - assert_eq!(Balances::free_balance(&20), 6860); - assert_eq!(Staking::intentions(), vec![20]); - - System::set_extrinsic_index(1); - Staking::on_offline_validator(20, 1); - assert_eq!(Balances::free_balance(&10), 6940); - assert_eq!(Balances::free_balance(&20), 6700); - assert_eq!(Staking::intentions(), vec![0u64; 0]); + // Should not panic + Staking::on_offline_validator(10, 100); + // Confirm that underflow has not occurred, and account balance is set to zero + assert_eq!(Balances::free_balance(&10), 0); }); } #[test] fn rewards_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { + // should check that: + // * rewards get recorded per session + // * rewards get paid per Era + // * Check that nominators are also rewarded + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .build(), + || { + let delay = 2; + // this test is only in the scope of one era. Since this variable changes + // at the last block/new era, we'll save it. + let session_reward = 10; + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // Initial config should be correct assert_eq!(Staking::era_length(), 9); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); + + assert_eq!(Staking::current_session_reward(), 10); + + // check the balance of a validator accounts. assert_eq!(Balances::total_balance(&10), 1); + // and the nominator (to-be) + assert_eq!(Balances::total_balance(&2), 20); - System::set_block_number(3); - Timestamp::set_timestamp(15); // on time. - Session::check_rotate_session(System::block_number()); + // add a dummy nominator. + // NOTE: this nominator is being added 'manually'. a Further test (nomination_and_reward..) will add it via '.nominate()' + >::insert(&10, Exposure { + own: 500, // equal division indicates that the reward will be equally divided among validator and nominator. + total: 1000, + others: vec![IndividualExposure {who: 2, value: 500 }] + }); + >::insert(&2, RewardDestination::Controller); + + + let mut block = 3; + // Block 3 => Session 1 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // on time. + Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Balances::total_balance(&10), 11); - System::set_block_number(6); - Timestamp::set_timestamp(31); // a little late + + // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. + assert_eq!(Staking::current_session_reward(), session_reward); + assert_eq!(Staking::current_era_reward(), session_reward); + + block = 6; // Block 6 => Session 2 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5 + delay); // a little late. Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Balances::total_balance(&10), 20); // less reward - System::set_block_number(9); - Timestamp::set_timestamp(50); // very late + + // session reward is the same, + assert_eq!(Staking::current_session_reward(), session_reward); + // though 2 will be deducted while stashed in the era reward due to delay + assert_eq!(Staking::current_era_reward(), 2*session_reward - delay); + + block = 9; // Block 9 => Session 3 => Era 1 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // back to being punktlisch. no delayss Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); - assert_eq!(Balances::total_balance(&10), 27); // much less reward + + assert_eq!(Balances::total_balance(&10), 1 + (3*session_reward - delay)/2); + assert_eq!(Balances::total_balance(&2), 20 + (3*session_reward - delay)/2); }); } #[test] -fn slashing_should_work() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { - assert_eq!(Staking::era_length(), 9); - assert_eq!(Staking::sessions_per_era(), 3); - assert_eq!(Staking::last_era_length_change(), 0); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); +fn multi_era_reward_should_work() { + // should check that: + // The value of current_session_reward is set at the end of each era, based on + // slot_stake and session_reward. Check and verify this. + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .nominate(false) + .build(), + || { + let delay = 0; + let session_reward = 10; + + // This is set by the test config builder. + assert_eq!(Staking::current_session_reward(), session_reward); + + // check the balance of a validator accounts. assert_eq!(Balances::total_balance(&10), 1); - System::set_block_number(3); + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + let mut block = 3; + // Block 3 => Session 1 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // on time. Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Balances::total_balance(&10), 11); - System::set_block_number(6); + // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. + assert_eq!(Staking::current_session_reward(), session_reward); + assert_eq!(Staking::current_era_reward(), session_reward); + + block = 6; // Block 6 => Session 2 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5 + delay); // a little late. Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); - assert_eq!(Balances::total_balance(&10), 21); - System::set_block_number(7); - System::set_extrinsic_index(1); - Staking::on_offline_validator(10, 1); - Staking::on_offline_validator(20, 1); - assert_eq!(Balances::total_balance(&10), 1); - }); -} + assert_eq!(Staking::current_session_reward(), session_reward); + assert_eq!(Staking::current_era_reward(), 2*session_reward - delay); + block = 9; // Block 9 => Session 3 => Era 1 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // back to being punktlisch. no delayss + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + // 1 + sum of of the session rewards accumulated + let recorded_balance = 1 + 3*session_reward - delay; + assert_eq!(Balances::total_balance(&10), recorded_balance); + + // the reward for next era will be: session_reward * slot_stake + let new_session_reward = Staking::session_reward() * Staking::slot_stake(); + assert_eq!(Staking::current_session_reward(), new_session_reward); + + // fast forward to next era: + block=12;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); + block=15;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); + + // intermediate test. + assert_eq!(Staking::current_era_reward(), 2*new_session_reward); + + // new era is triggered here. + block=18;System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number()); + + // pay time + assert_eq!(Balances::total_balance(&10), 3*new_session_reward + recorded_balance); + }); +} #[test] fn staking_should_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + // should test: + // * new validators can be added to the default set + // * new ones will be chosen per era + // * either one can unlock the stash and back-down from being a validator via `chill`ing. + with_externalities(&mut ExtBuilder::default() + .sessions_per_era(3) + .nominate(false) + .build(), + || { + assert_eq!(Staking::era_length(), 3); + // remember + compare this along with the test. + assert_eq!(Session::validators(), vec![20, 10]); + assert_ok!(Staking::set_bonding_duration(2)); + assert_eq!(Staking::bonding_duration(), 2); - assert_eq!(Staking::era_length(), 2); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Session::validators(), vec![10, 20]); + // put some money in account that we'll use. + for i in 1..5 { Balances::set_free_balance(&i, 1000); } - assert_ok!(Staking::set_bonding_duration(2.into())); - assert_eq!(Staking::bonding_duration(), 2); + // bond one account pair and state interest in nomination. + // this is needed to keep 10 and 20 in the validator list with phragmen + assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 4])); - // Block 1: Add three validators. No obvious change. + // --- Block 1: System::set_block_number(1); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_ok!(Staking::stake(Origin::signed(2))); - assert_ok!(Staking::stake(Origin::signed(4))); + + // add a new candidate for being a validator. account 3 controlled by 4. + assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); // balance of 3 = 3000, stashed = 1500 + Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::validators(), vec![10, 20]); + // No effects will be seen so far.s + assert_eq!(Session::validators(), vec![20, 10]); + - // Block 2: New validator set now. + // --- Block 2: System::set_block_number(2); + // Explicitly state the desire to validate + // note that the controller account will state interest as representative of the stash-controller pair. + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + Session::check_rotate_session(System::block_number()); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![4, 2]); + assert_eq!(Staking::current_era(), 0); + // No effects will be seen so far. Era has not been yet triggered. + assert_eq!(Session::validators(), vec![20, 10]); - // Block 3: Unstake highest, introduce another staker. No change yet. + + // --- Block 3: the validators will now change. System::set_block_number(3); - assert_ok!(Staking::stake(Origin::signed(3))); - assert_ok!(Staking::unstake(Origin::signed(4), (Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32).into())); - assert_eq!(Staking::current_era(), 1); Session::check_rotate_session(System::block_number()); - // Block 4: New era - validators change. + // 2 only voted for 4 and 20 + assert_eq!(Session::validators().len(), 2); + assert_eq!(Session::validators(), vec![4, 20]); + assert_eq!(Staking::current_era(), 1); + + + // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 System::set_block_number(4); - Session::check_rotate_session(System::block_number()); - assert_eq!(Staking::current_era(), 2); - assert_eq!(Session::validators(), vec![3, 2]); - // Block 5: Transfer stake from highest to lowest. No change yet. - System::set_block_number(5); - assert_ok!(Balances::transfer(Origin::signed(4), 1.into(), 40.into())); + // unlock the entire stashed value. + // Note that this will ne be enough to remove 4 as a validator candidate! + Staking::unbond(Origin::signed(4), Staking::ledger(&4).unwrap().active).unwrap(); + // explicit chill indicated that 4 no longer wants to be a validator. + Staking::chill(Origin::signed(4)).unwrap(); + + // nominator votes for 10 + assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); + Session::check_rotate_session(System::block_number()); - - // Block 6: Lowest now validator. - System::set_block_number(6); + // nothing should be changed so far. + assert_eq!(Session::validators(), vec![4, 20]); + assert_eq!(Staking::current_era(), 1); + + + // --- Block 5: nothing. 4 is still there. + System::set_block_number(5); Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![1, 3]); + assert_eq!(Session::validators(), vec![4, 20]); + assert_eq!(Staking::current_era(), 1); - // Block 7: Unstake three. No change yet. - System::set_block_number(7); - assert_ok!(Staking::unstake(Origin::signed(3), (Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32).into())); - Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![1, 3]); - // Block 8: Back to one and two. - System::set_block_number(8); + // --- Block 6: 4 will not be a validator. + System::set_block_number(6); Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::validators().contains(&4), false); + assert_eq!(Session::validators(), vec![20, 10]); }); } #[test] -fn nominating_and_rewards_should_work() { - with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { +fn less_than_needed_candidates_works() { + // Test the situation where the number of validators are less than `ValidatorCount` but more than + // The expected behavior is to choose all the candidates that have some vote. + with_externalities(&mut ExtBuilder::default() + .minimum_validator_count(1) + .validator_count(3) + .nominate(false) + .validator_pool(true) + .build(), + || { assert_eq!(Staking::era_length(), 1); - assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 3); - assert_eq!(Session::validators(), vec![10, 20]); + assert_eq!(Staking::validator_count(), 3); + + assert_eq!(Staking::minimum_validator_count(), 1); + assert_eq!(Staking::validator_count(), 3); + + // initial validators + assert_eq!(Session::validators(), vec![40, 30, 20, 10]); + + // only one nominator will exist and it will + assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20])); + // 10 and 20 are now valid candidates. + // trigger era System::set_block_number(1); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_ok!(Staking::stake(Origin::signed(2))); - assert_ok!(Staking::stake(Origin::signed(3))); - assert_ok!(Staking::nominate(Origin::signed(4), 1.into())); Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3 - assert_eq!(Balances::total_balance(&1), 10); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&3), 30); - assert_eq!(Balances::total_balance(&4), 40); - System::set_block_number(2); - assert_ok!(Staking::unnominate(Origin::signed(4), 0.into())); - Session::check_rotate_session(System::block_number()); - assert_eq!(Staking::current_era(), 2); - assert_eq!(Session::validators(), vec![3, 2]); - assert_eq!(Balances::total_balance(&1), 16); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&3), 60); - assert_eq!(Balances::total_balance(&4), 64); + // both validators will be chosen again. NO election algorithm is even executed. + assert_eq!(Session::validators(), vec![20, 10]); - System::set_block_number(3); - assert_ok!(Staking::stake(Origin::signed(4))); - assert_ok!(Staking::unstake(Origin::signed(3), (Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32).into())); - assert_ok!(Staking::nominate(Origin::signed(3), 1.into())); - Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![1, 4]); - assert_eq!(Balances::total_balance(&1), 16); - assert_eq!(Balances::total_balance(&2), 40); - assert_eq!(Balances::total_balance(&3), 80); - assert_eq!(Balances::total_balance(&4), 64); + // But the exposure is updated in a simple way. Each nominators vote is applied + assert_eq!(Staking::stakers(10).others.iter().map(|e| e.who).collect::>>(), vec![2]); + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.who).collect::>>(), vec![2]); + }); +} - System::set_block_number(4); +#[test] +fn no_candidate_emergency_condition() { + // Test the situation where the number of validators are less than `ValidatorCount` and less than + // The expected behavior is to choose all candidates from the previous era. + with_externalities(&mut ExtBuilder::default() + .minimum_validator_count(1) + .validator_count(3) + .nominate(false) + .validator_pool(true) + .build(), + || { + assert_eq!(Staking::era_length(), 1); + assert_eq!(Staking::validator_count(), 3); + + assert_eq!(Staking::minimum_validator_count(), 1); + assert_eq!(Staking::validator_count(), 3); + + // initial validators + assert_eq!(Session::validators(), vec![40, 30, 20, 10]); + + // trigger era + System::set_block_number(1); Session::check_rotate_session(System::block_number()); - assert_eq!(Balances::total_balance(&1), 26); - assert_eq!(Balances::total_balance(&2), 40); - assert_eq!(Balances::total_balance(&3), 133); - assert_eq!(Balances::total_balance(&4), 128); + assert_eq!(Staking::current_era(), 1); + + // No one nominates => no one has a proper vote => no change + assert_eq!(Session::validators(), vec![40, 30, 20, 10]); }); } #[test] -fn rewards_with_off_the_table_should_work() { - with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || { +fn nominating_and_rewards_should_work() { + // For now it tests a functionality which somehow overlaps with other tests: + // the fact that the nominator is rewarded properly. + // + // PHRAGMEN OUTPUT: running this test with the reference impl gives: + // + // Votes [('2', 500, ['10', '20', '30']), ('4', 500, ['10', '20', '40'])] + // Sequential Phragmén gives + // 10 is elected with stake 500.0 and score 0.001 + // 20 is elected with stake 500.0 and score 0.002 + // + // 2 has load 0.002 and supported + // 10 with stake 250.0 20 with stake 250.0 30 with stake 0.0 + // 4 has load 0.002 and supported + // 10 with stake 250.0 20 with stake 250.0 40 with stake 0.0 + + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .build(), + || { + // initial validators + assert_eq!(Session::validators(), vec![40, 30, 20, 10]); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); + + // default reward for the first session. + let session_reward = 10; + assert_eq!(Staking::current_session_reward(), session_reward); + + // give the man some money + let initial_balance = 1000; + for i in 1..5 { Balances::set_free_balance(&i, initial_balance); } + Balances::set_free_balance(&10, initial_balance); + Balances::set_free_balance(&20, initial_balance); + + // record their balances. + for i in 1..5 { assert_eq!(Balances::total_balance(&i), initial_balance); } + + // bond two account pairs and state interest in nomination. + // 2 will nominate for 10, 20, 30 + assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20, 30])); + // 4 will nominate for 10, 20, 40 + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Stash)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![10, 20, 40])); + System::set_block_number(1); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_ok!(Staking::nominate(Origin::signed(2), 1.into())); - assert_ok!(Staking::stake(Origin::signed(3))); Session::check_rotate_session(System::block_number()); - assert_eq!(Session::validators(), vec![1, 3]); // 1 + 2, 3 - assert_eq!(Balances::total_balance(&1), 10); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&3), 30); + assert_eq!(Staking::current_era(), 1); + // 10 and 20 have more votes, they will be chosen by phragmen. + assert_eq!(Session::validators(), vec![20, 10]); + // validators must have already received some rewards. + assert_eq!(Balances::total_balance(&10), initial_balance + session_reward); + assert_eq!(Balances::total_balance(&20), initial_balance + session_reward); + + // ------ check the staked value of all parties. + // total expo of 10, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(10).own, 1000); + assert_eq!(Staking::stakers(10).total, 1000 + 500); + // 2 and 4 supported 10, each with stake 250, according to phragmen. + assert_eq!(Staking::stakers(10).others.iter().map(|e| e.value).collect::>>(), vec![250, 250]); + assert_eq!(Staking::stakers(10).others.iter().map(|e| e.who).collect::>>(), vec![4, 2]); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(20).own, 2000); + assert_eq!(Staking::stakers(20).total, 2000 + 500); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.value).collect::>>(), vec![250, 250]); + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.who).collect::>>(), vec![4, 2]); + System::set_block_number(2); - assert_ok!(Staking::register_preferences( - Origin::signed(1), - (Staking::intentions().into_iter().position(|i| i == 1).unwrap() as u32).into(), - ValidatorPrefs { unstake_threshold: 3, validator_payment: 4 } - )); - Session::check_rotate_session(System::block_number()); - assert_eq!(Balances::total_balance(&1), 22); - assert_eq!(Balances::total_balance(&2), 37); - assert_eq!(Balances::total_balance(&3), 60); + // next session reward. + let new_session_reward = Staking::session_reward() * Staking::slot_stake(); + // nothing else will happen, era ends and rewards are paid again, + // it is expected that nominators will also be paid. See below + Session::check_rotate_session(System::block_number()); + + // Nominator 2: has [250/1500 ~ 1/6 from 10] + [250/2500 ~ 1/10 from 20]'s reward. ==> 1/6 + 1/10 + assert_eq!(Balances::total_balance(&2), initial_balance + (new_session_reward/6 + new_session_reward/10)); + // The Associated validator will get the other 4/6 --> 1500(total) minus 1/6(250) by each nominator -> 6/6 - 1/6 - 1/6 + assert_eq!(Balances::total_balance(&10), initial_balance + session_reward + 4*new_session_reward/6) ; + + // Nominator 4: has [250/1500 ~ 1/6 from 10] + [250/2500 ~ 1/10 from 20]'s reward. ==> 1/6 + 1/10 + // This nominator chose stash as the reward destination. This means that the reward will go to 3, which is bonded as the stash of 4. + assert_eq!(Balances::total_balance(&3), initial_balance + (new_session_reward/6 + new_session_reward/10)); + // The Associated validator will get the other 8/10 --> 2500(total) minus 1/10(250) by each nominator -> 10/10 - 1/10 - 1/10 + assert_eq!(Balances::total_balance(&20), initial_balance + session_reward + 8*new_session_reward/10); }); } #[test] -fn nominating_slashes_should_work() { - with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || { - assert_eq!(Staking::era_length(), 4); +fn nominators_also_get_slashed() { + // A nominator should be slashed if the validator they nominated is slashed + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + assert_eq!(Staking::era_length(), 1); assert_eq!(Staking::validator_count(), 2); - assert_eq!(Staking::bonding_duration(), 12); - assert_eq!(Session::validators(), vec![10, 20]); + // slash happens immediately. + assert_eq!(Staking::offline_slash_grace(), 0); + // Account 10 has not been reported offline + assert_eq!(Staking::slash_count(&10), 0); + // initial validators + assert_eq!(Session::validators(), vec![20, 10]); - System::set_block_number(2); - Session::check_rotate_session(System::block_number()); + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - Timestamp::set_timestamp(15); - System::set_block_number(4); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_ok!(Staking::stake(Origin::signed(3))); - assert_ok!(Staking::nominate(Origin::signed(2), 3.into())); - assert_ok!(Staking::nominate(Origin::signed(4), 1.into())); - Session::check_rotate_session(System::block_number()); + // give the man some money. + let initial_balance = 1000; + for i in 1..3 { Balances::set_free_balance(&i, initial_balance); } + Balances::set_free_balance(&10, initial_balance); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2 - assert_eq!(Balances::total_balance(&1), 10); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&3), 30); - assert_eq!(Balances::total_balance(&4), 40); + // 2 will nominate for 10 + let nominator_stake = 500; + assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); - System::set_block_number(5); - System::set_extrinsic_index(1); - Staking::on_offline_validator(1, 1); - Staking::on_offline_validator(3, 1); - assert_eq!(Balances::total_balance(&1), 0); //slashed - assert_eq!(Balances::total_balance(&2), 20); //not slashed - assert_eq!(Balances::total_balance(&3), 10); //slashed - assert_eq!(Balances::total_balance(&4), 30); //slashed - // TODO: change slash % to something sensible. + // new era, pay rewards, + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + // 10 goes offline + Staking::on_offline_validator(10, 4); + let slash_value = 2_u64.pow(3) * Staking::current_offline_slash(); + let expo = Staking::stakers(10); + let actual_slash = expo.own.min(slash_value); + let nominator_actual_slash = nominator_stake.min(expo.total - actual_slash); + // initial + first era reward + slash + assert_eq!(Balances::total_balance(&10), initial_balance + 10 - actual_slash); + assert_eq!(Balances::total_balance(&2), initial_balance - nominator_actual_slash); + // Because slashing happened. + assert!(Staking::forcing_new_era().is_some()); }); } #[test] fn double_staking_should_fail() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { + // should test (in the same order): + // * an account already bonded as controller CAN be reused as the controller of another account. + // * an account already bonded as stash cannot be the controller of another account. + // * an account already bonded as stash cannot nominate. + // * an account already bonded as controller can nominate. + with_externalities(&mut ExtBuilder::default() + .sessions_per_era(2) + .build(), + || { + let arbitrary_value = 5; System::set_block_number(1); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_noop!(Staking::stake(Origin::signed(1)), "Cannot stake if already staked."); - assert_noop!(Staking::nominate(Origin::signed(1), 1.into()), "Cannot nominate if already staked."); - assert_ok!(Staking::nominate(Origin::signed(2), 1.into())); - assert_noop!(Staking::stake(Origin::signed(2)), "Cannot stake if already nominating."); - assert_noop!(Staking::nominate(Origin::signed(2), 1.into()), "Cannot nominate if already nominating."); + // 2 = controller, 1 stashed => ok + assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default())); + // 2 = controller, 3 stashed (Note that 2 is reused.) => ok + assert_ok!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default())); + // 4 = not used so far, 1 stashed => not allowed. + assert_noop!(Staking::bond(Origin::signed(1), 4, arbitrary_value, RewardDestination::default()), "stash already bonded"); + // 1 = stashed => attempting to nominate should fail. + assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); + // 2 = controller => nominating should work. + assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); }); } #[test] -fn staking_eras_work() { - with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || { +fn session_and_eras_work() { + with_externalities(&mut ExtBuilder::default() + .sessions_per_era(2) + .reward(10) + .build(), + || { assert_eq!(Staking::era_length(), 2); assert_eq!(Staking::sessions_per_era(), 2); assert_eq!(Staking::last_era_length_change(), 0); @@ -444,7 +788,7 @@ fn staking_eras_work() { // Block 3: Schedule an era length change; no visible changes. System::set_block_number(3); - assert_ok!(Staking::set_sessions_per_era(3.into())); + assert_ok!(Staking::set_sessions_per_era(3)); Session::check_rotate_session(System::block_number()); assert_eq!(Session::current_index(), 3); assert_eq!(Staking::sessions_per_era(), 2); @@ -486,58 +830,756 @@ fn staking_eras_work() { } #[test] -fn staking_balance_transfer_when_bonded_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Balances::set_free_balance(&1, 111); - assert_ok!(Staking::stake(Origin::signed(1))); - assert_noop!(Balances::transfer(Origin::signed(1), 2.into(), 69.into()), "cannot transfer illiquid funds"); +fn cannot_transfer_staked_balance() { + // Tests that a stash account cannot transfer funds + with_externalities(&mut ExtBuilder::default().build(), || { + // Confirm account 11 is stashed + assert_eq!(Staking::bonded(&11), Some(10)); + // Confirm account 11 has some free balance + assert_eq!(Balances::free_balance(&11), 1000); + // Confirm account 11 (via controller 10) is totally staked + assert_eq!(Staking::stakers(&10).total, 1000 + 500); + // Confirm account 11 cannot transfer as a result + assert_noop!(Balances::transfer(Origin::signed(11), 20, 1), "account liquidity restrictions prevent withdrawal"); + + // Give account 11 extra free balance + Balances::set_free_balance(&11, 10000); + // Confirm that account 11 can now transfer some balance + assert_ok!(Balances::transfer(Origin::signed(11), 20, 1)); }); } #[test] -fn deducting_balance_when_bonded_should_not_work() { - with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - Balances::set_free_balance(&1, 111); - >::insert(1, 2); +fn cannot_reserve_staked_balance() { + // Checks that a bonded account cannot reserve balance from free balance + with_externalities(&mut ExtBuilder::default().build(), || { + // Confirm account 11 is stashed + assert_eq!(Staking::bonded(&11), Some(10)); + // Confirm account 11 has some free balance + assert_eq!(Balances::free_balance(&11), 1000); + // Confirm account 11 (via controller 10) is totally staked + assert_eq!(Staking::stakers(&10).total, 1000 + 500); + // Confirm account 11 cannot transfer as a result + assert_noop!(Balances::reserve(&11, 1), "account liquidity restrictions prevent withdrawal"); + + // Give account 11 extra free balance + Balances::set_free_balance(&11, 10000); + // Confirm account 11 can now reserve balance + assert_ok!(Balances::reserve(&11, 1)); + }); +} + +#[test] +fn reward_destination_works() { + // Rewards go to the correct destination as determined in Payee + with_externalities(&mut ExtBuilder::default().build(), || { + // Check that account 10 is a validator + assert!(>::exists(10)); + // Check the balance of the validator account + assert_eq!(Balances::free_balance(&10), 1); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 1000); + // Check these two accounts are bonded + assert_eq!(Staking::bonded(&11), Some(10)); + // Check how much is at stake + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + // Track current session reward + let mut current_session_reward = Staking::current_session_reward(); + + // Move forward the system for payment System::set_block_number(1); - assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); - assert_noop!(Balances::reserve(&1, 69), "cannot transfer illiquid funds"); + Timestamp::set_timestamp(5); + Session::check_rotate_session(System::block_number()); + + // Check that RewardDestination is Staked (default) + assert_eq!(Staking::payee(&10), RewardDestination::Staked); + // Check current session reward is 10 + assert_eq!(current_session_reward, 10); + // Check that reward went to the stash account of validator + // 1/3 of the reward is for the nominator. + let validator_reward = (10. * (2./3.)) as u64; // = 6 + assert_eq!(Balances::free_balance(&11), 1000 + validator_reward); + // Check that amount at stake increased accordingly + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 6, active: 1000 + 6, unlocking: vec![] })); + // Update current session reward + current_session_reward = Staking::current_session_reward(); + + //Change RewardDestination to Stash + >::insert(&10, RewardDestination::Stash); + + // Move forward the system for payment + System::set_block_number(2); + Timestamp::set_timestamp(10); + Session::check_rotate_session(System::block_number()); + + // Check that RewardDestination is Stash + assert_eq!(Staking::payee(&10), RewardDestination::Stash); + // Check that reward went to the stash account + let new_validator_reward = ((1000 + 6) as f64 / ( (1000 + 6) + (500 + 4) ) as f64) * current_session_reward as f64; + assert_eq!(Balances::free_balance(&11), 1000 + validator_reward + new_validator_reward as u64); + // Check that amount at stake is not increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1006, active: 1006, unlocking: vec![] })); + + //Change RewardDestination to Controller + >::insert(&10, RewardDestination::Controller); + + // Check controller balance + assert_eq!(Balances::free_balance(&10), 1); + + + // Move forward the system for payment + System::set_block_number(3); + Timestamp::set_timestamp(15); + Session::check_rotate_session(System::block_number()); + + // Check that RewardDestination is Controller + assert_eq!(Staking::payee(&10), RewardDestination::Controller); + // Check that reward went to the controller account + let reward_of = |w| Staking::stakers(w).own * Staking::current_session_reward() / Staking::stakers(w).total; + assert_eq!(Balances::free_balance(&10), 1 + reward_of(&10)); + // Check that amount at stake is not increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1006, active: 1006, unlocking: vec![] })); }); } #[test] -fn slash_value_calculation_does_not_overflow() { - with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || { +fn validator_payment_prefs_work() { + // Test that validator preferences are correctly honored + // Note: unstake threshold is being directly tested in slashing tests. + // This test will focus on validator payment. + with_externalities(&mut ExtBuilder::default() + .session_length(3) + .sessions_per_era(3) + .build(), + || { + let session_reward = 10; + let validator_cut = 5; + let validator_initial_balance = Balances::total_balance(&11); + // Initial config should be correct assert_eq!(Staking::era_length(), 9); assert_eq!(Staking::sessions_per_era(), 3); assert_eq!(Staking::last_era_length_change(), 0); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 0); + + assert_eq!(Staking::current_session_reward(), session_reward); + + // check the balance of a validator accounts. assert_eq!(Balances::total_balance(&10), 1); - assert_eq!(Staking::intentions(), vec![10, 20]); - assert_eq!(Staking::offline_slash_grace(), 0); + // check the balance of a validator's stash accounts. + assert_eq!(Balances::total_balance(&11), validator_initial_balance); + // and the nominator (to-be) + assert_eq!(Balances::total_balance(&2), 20); - // set validator preferences so the validator doesn't back down after - // slashing. - >::insert(10, ValidatorPrefs { - unstake_threshold: u32::max_value(), - validator_payment: 0, + // add a dummy nominator. + // NOTE: this nominator is being added 'manually', use '.nominate()' to do it realistically. + >::insert(&10, Exposure { + own: 500, // equal division indicates that the reward will be equally divided among validator and nominator. + total: 1000, + others: vec![IndividualExposure {who: 2, value: 500 }] + }); + >::insert(&2, RewardDestination::Controller); + >::insert(&10, ValidatorPrefs { + unstake_threshold: 3, + validator_payment: validator_cut }); - System::set_block_number(3); + // ------------ Fast forward + let mut block = 3; + // Block 3 => Session 1 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // on time. Session::check_rotate_session(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); - assert_eq!(Balances::total_balance(&10), 11); - // the balance type is u64, so after slashing 64 times, - // the slash value should have overflowed. add a couple extra for - // good measure with the slash grace. - trait TypeEq {} - impl TypeEq for (A, A) {} - fn assert_type_eq() {} - assert_type_eq::<(u64, ::Balance)>(); + // session triggered: the reward value stashed should be 10 -- defined in ExtBuilder genesis. + assert_eq!(Staking::current_session_reward(), session_reward); + assert_eq!(Staking::current_era_reward(), session_reward); + + block = 6; // Block 6 => Session 2 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); // a little late. + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); - Staking::on_offline_validator(10, 100); + assert_eq!(Staking::current_session_reward(), session_reward); + assert_eq!(Staking::current_era_reward(), 2*session_reward); + + block = 9; // Block 9 => Session 3 => Era 1 + System::set_block_number(block); + Timestamp::set_timestamp(block*5); + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + + // whats left to be shared is the sum of 3 rounds minus the validator's cut. + let shared_cut = 3 * session_reward - validator_cut; + // Validator's payee is Staked account, 11, reward will be paid here. + assert_eq!(Balances::total_balance(&11), validator_initial_balance + shared_cut/2 + validator_cut); + // Controller account will not get any reward. + assert_eq!(Balances::total_balance(&10), 1); + // Rest of the reward will be shared and paid to the nominator in stake. + assert_eq!(Balances::total_balance(&2), 20 + shared_cut/2); + }); + +} + +#[test] +fn bond_extra_works() { + // Tests that extra `free_balance` in the stash can be added to stake + // NOTE: this tests only verifies `StakingLedger` for correct updates. + // See `bond_extra_and_withdraw_unbonded_works` for more details and updates on `Exposure`. + with_externalities(&mut ExtBuilder::default().build(), + || { + // Check that account 10 is a validator + assert!(>::exists(10)); + // Check that account 10 is bonded to account 11 + assert_eq!(Staking::bonded(&11), Some(10)); + // Check how much is at stake + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + + // Give account 11 some large free balance greater than total + Balances::set_free_balance(&11, 1000000); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 1000000); + + // Call the bond_extra function from controller, add only 100 + assert_ok!(Staking::bond_extra(Origin::signed(10), 100)); + // There should be 100 more `total` and `active` in the ledger + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); + + // Call the bond_extra function with a large number, should handle it + assert_ok!(Staking::bond_extra(Origin::signed(10), u64::max_value())); + // The full amount of the funds should now be in the total and active + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000000, active: 1000000, unlocking: vec![] })); + + }); +} + +#[test] +fn bond_extra_and_withdraw_unbonded_works() { + // * Should test + // * Given an account being bonded [and chosen as a validator](not mandatory) + // * It can add extra funds to the bonded account. + // * it can unbond a portion of its funds from the stash account. + // * Once the unbonding period is done, it can actually take the funds out of the stash. + with_externalities(&mut ExtBuilder::default() + .reward(10) // it is the default, just for verbosity + .nominate(false) + .build(), + || { + // Set payee to controller. avoids confusion + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // Set unbonding era (bonding_duration) to 2 + assert_ok!(Staking::set_bonding_duration(2)); + + // Give account 11 some large free balance greater than total + Balances::set_free_balance(&11, 1000000); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 1000000); + + // Initial config should be correct + assert_eq!(Staking::sessions_per_era(), 1); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + assert_eq!(Staking::current_session_reward(), 10); + + // check the balance of a validator accounts. + assert_eq!(Balances::total_balance(&10), 1); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + System::set_block_number(1); + Timestamp::set_timestamp(5); + Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 1); + + // NOTE: despite having .nominate() in extBuilder, 20 doesn't have a share since + // rewards are paid before election in new_era() + assert_eq!(Balances::total_balance(&10), 1 + 10); + + // Initial state of 10 + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + assert_eq!(Staking::stakers(&10), Exposure { total: 1000, own: 1000, others: vec![] }); + + + // deposit the extra 100 units + Staking::bond_extra(Origin::signed(10), 100).unwrap(); + + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); + // Exposure is a snapshot! only updated after the next era update. + assert_ne!(Staking::stakers(&10), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + + // trigger next era. + System::set_block_number(2);Timestamp::set_timestamp(10);Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::current_index(), 2); + + // ledger should be the same. + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] })); + // Exposure is now updated. + assert_eq!(Staking::stakers(&10), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + // Note that by this point 10 also have received more rewards, but we don't care now. + // assert_eq!(Balances::total_balance(&10), 1 + 10 + MORE_REWARD); + + // Unbond almost all of the funds in stash. + Staking::unbond(Origin::signed(10), 1000).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })); + + // Attempting to free the balances now will fail. 2 eras need to pass. + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })); + + // trigger next era. + System::set_block_number(3);Timestamp::set_timestamp(15);Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 3); + assert_eq!(Session::current_index(), 3); + + // nothing yet + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })); + + // trigger next era. + System::set_block_number(4);Timestamp::set_timestamp(20);Session::check_rotate_session(System::block_number()); + assert_eq!(Staking::current_era(), 4); + assert_eq!(Session::current_index(), 4); + + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + // Now the value is free and the staking ledger is updated. + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 100, active: 100, unlocking: vec![] })); + }) +} + +#[test] +fn slot_stake_is_least_staked_validator_and_limits_maximum_punishment() { + // Test that slot_stake is determined by the least staked validator + // Test that slot_stake is the maximum punishment that can happen to a validator + // Note that rewardDestination is the stash account by default + // Note that unlike reward slash will affect free_balance, not the stash account. + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + // Confirm validator count is 2 + assert_eq!(Staking::validator_count(), 2); + // Confirm account 10 and 20 are validators + assert!(>::exists(&10) && >::exists(&20)); + // Confirm 10 has less stake than 20 + assert!(Staking::stakers(&10).total < Staking::stakers(&20).total); + assert_eq!(Staking::stakers(&10).total, 1000); + assert_eq!(Staking::stakers(&20).total, 2000); + + // Give the man some money. + Balances::set_free_balance(&10, 1000); + Balances::set_free_balance(&20, 1000); + + // Confirm initial free balance. + assert_eq!(Balances::free_balance(&10), 1000); + assert_eq!(Balances::free_balance(&20), 1000); + + // We confirm initialized slot_stake is this value + assert_eq!(Staking::slot_stake(), Staking::stakers(&10).total); + + // Now lets lower account 20 stake + >::insert(&20, Exposure { total: 69, own: 69, others: vec![] }); + assert_eq!(Staking::stakers(&20).total, 69); + >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); + + // New era --> rewards are paid --> stakes are changed + System::set_block_number(1); + Timestamp::set_timestamp(5); + Session::check_rotate_session(System::block_number()); + + assert_eq!(Staking::current_era(), 1); + // -- new balances + reward + assert_eq!(Staking::stakers(&10).total, 1000 + 10); + assert_eq!(Staking::stakers(&20).total, 69 + 10); + + // -- Note that rewards are going directly to stash, not as free balance. + assert_eq!(Balances::free_balance(&10), 1000); + assert_eq!(Balances::free_balance(&20), 1000); + + // -- slot stake should also be updated. + assert_eq!(Staking::slot_stake(), 79); + + // // If 10 gets slashed now, despite having +1000 in stash, it will be slashed byt 79, which is the slot stake + Staking::on_offline_validator(10, 4); + // // Confirm user has been reported + assert_eq!(Staking::slash_count(&10), 4); + // // check the balance of 10 (slash will be deducted from free balance.) + assert_eq!(Balances::free_balance(&10), 1000 - 79); + + }); +} + +#[test] +fn on_free_balance_zero_stash_removes_validator() { + // Tests that validator storage items are cleaned up when stash is empty + // Tests that storage items are untouched when controller is empty + with_externalities(&mut ExtBuilder::default() + .existential_deposit(10) + .build(), + || { + // Check that account 10 is a validator + assert!(>::exists(10)); + // Check the balance of the validator account + assert_eq!(Balances::free_balance(&10), 256); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 256000); + // Check these two accounts are bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Set some storage items which we expect to be cleaned up + // Initiate slash count storage item + Staking::on_offline_validator(10, 1); + // Set payee information + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); + + // Check storage items that should be cleaned up + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + + // Reduce free_balance of controller to 0 + Balances::set_free_balance(&10, 0); + // Check total balance of account 10 + assert_eq!(Balances::total_balance(&10), 0); + + // Check the balance of the stash account has not been touched + assert_eq!(Balances::free_balance(&11), 256000); + // Check these two accounts are still bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Check storage items have not changed + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + + // Reduce free_balance of stash to 0 + Balances::set_free_balance(&11, 0); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 0); + + // Check storage items do not exist + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&11)); + }); +} + +#[test] +fn on_free_balance_zero_stash_removes_nominator() { + // Tests that nominator storage items are cleaned up when stash is empty + // Tests that storage items are untouched when controller is empty + with_externalities(&mut ExtBuilder::default() + .existential_deposit(10) + .build(), + || { + // Make 10 a nominator + assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); + // Check that account 10 is a nominator + assert!(>::exists(10)); + // Check the balance of the nominator account + assert_eq!(Balances::free_balance(&10), 256); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 256000); + // Check these two accounts are bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Set payee information + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); + + + // Check storage items that should be cleaned up + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + + // Reduce free_balance of controller to 0 + Balances::set_free_balance(&10, 0); + // Check total balance of account 10 + assert_eq!(Balances::total_balance(&10), 0); + + // Check the balance of the stash account has not been touched + assert_eq!(Balances::free_balance(&11), 256000); + // Check these two accounts are still bonded + assert_eq!(Staking::bonded(&11), Some(10)); + + // Check storage items have not changed + assert!(>::exists(&10)); + assert!(>::exists(&10)); + assert!(>::exists(&10)); + + // Reduce free_balance of stash to 0 + Balances::set_free_balance(&11, 0); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 0); + + // Check storage items do not exist + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&10)); + assert!(!>::exists(&11)); + }); +} + +#[test] +fn phragmen_poc_works() { + // Tests the POC test of the phragmen, mentioned in the paper and reference implementation. + // Initial votes: + // vote_list = [ + // ("A", 10.0, ["X", "Y"]), + // ("B", 20.0, ["X", "Z"]), + // ("C", 30.0, ["Y", "Z"]) + // ] + // + // Sequential Phragmén gives + // Z is elected with stake 35.0 and score 0.02 + // Y is elected with stake 25.0 and score 0.04 + // + // A has load 0.04 and supported + // X with stake 0.0 Y with stake 10.0 + // B has load 0.02 and supported + // X with stake 0.0 Z with stake 20.0 + // C has load 0.04 and supported + // Y with stake 15.0 Z with stake 15.0 + // + // NOTE: doesn't X/Y/Z's stash value make a difference here in phragmen? + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .build(), + || { + // initial setup of 10 and 20, both validators. + assert_eq!(Session::validators(), vec![20, 10]); + + assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + assert_eq!(Staking::ledger(&20), Some(StakingLedger { stash: 21, total: 2000, active: 2000, unlocking: vec![] })); + + assert_eq!(Staking::validators(10), ValidatorPrefs::default()); + assert_eq!(Staking::validators(20), ValidatorPrefs::default()); + + assert_eq!(Balances::free_balance(10), 1); + assert_eq!(Balances::free_balance(20), 1); + + // no one is a nominator + assert_eq!(>::enumerate().count(), 0 as usize); + + // Bond [30, 31] as the third validator + assert_ok!(Staking::bond(Origin::signed(31), 30, 1000, RewardDestination::default())); + assert_ok!(Staking::validate(Origin::signed(30), ValidatorPrefs::default())); + + // bond [2,1](A), [4,3](B), [6,5](C) as the 3 nominators + // Give all of them some balance to be able to bond properly. + for i in &[1, 3, 5] { Balances::set_free_balance(i, 50); } + // Linking names to the above test: + // 10 => X + // 20 => Y + // 30 => Z + assert_ok!(Staking::bond(Origin::signed(1), 2, 10, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 20, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(4), vec![10, 30])); + + assert_ok!(Staking::bond(Origin::signed(5), 6, 30, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(6), vec![20, 30])); + + // New era => election algorithm will trigger + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // Z and Y are chosen + assert_eq!(Session::validators(), vec![30, 20]); + + // with stake 35 and 25 respectively + + // This is only because 30 has been bonded on the fly, exposures are stored at the very end of the era. + // 35 is the point, not 'own' Exposure. + assert_eq!(Staking::stakers(30).own, 0); + assert_eq!(Staking::stakers(30).total, 0 + 35); + // same as above. +25 is the point + assert_eq!(Staking::stakers(20).own, 2010); + assert_eq!(Staking::stakers(20).total, 2010 + 25); + + // 30(Z) was supported by B-4 and C-6 with stake 20 and 15 respectively. + assert_eq!(Staking::stakers(30).others.iter().map(|e| e.value).collect::>>(), vec![15, 20]); + assert_eq!(Staking::stakers(30).others.iter().map(|e| e.who).collect::>>(), vec![6, 4]); + + // 20(Y) was supported by A-2 and C-6 with stake 10 and 15 respectively. + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.value).collect::>>(), vec![15, 10]); + assert_eq!(Staking::stakers(20).others.iter().map(|e| e.who).collect::>>(), vec![6, 2]); + }); +} + +#[test] +fn phragmen_election_works() { + // tests the encapsulated phragmen::elect function. + with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + // initial setup of 10 and 20, both validators + assert_eq!(Session::validators(), vec![20, 10]); + + // no one is a nominator + assert_eq!(>::enumerate().count(), 0 as usize); + + // Bond [30, 31] as the third validator + assert_ok!(Staking::bond(Origin::signed(31), 30, 1000, RewardDestination::default())); + assert_ok!(Staking::validate(Origin::signed(30), ValidatorPrefs::default())); + + // bond [2,1](A), [4,3](B), as 2 nominators + // Give all of them some balance to be able to bond properly. + for i in &[1, 3] { Balances::set_free_balance(i, 50); } + assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 20])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 45, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(4), vec![10, 30])); + + let rounds = || 2 as usize; + let validators = || >::enumerate(); + let nominators = || >::enumerate(); + let stash_of = |w| Staking::stash_balance(&w); + let min_validator_count = Staking::minimum_validator_count() as usize; + + let winners = phragmen::elect::( + rounds, + validators, + nominators, + stash_of, + min_validator_count + ); + + // 10 and 30 must be the winners + assert_eq!(winners.iter().map(|w| w.who).collect::>>(), vec![10, 30]); + + let winner_10 = winners.iter().filter(|w| w.who == 10).nth(0).unwrap(); + let winner_30 = winners.iter().filter(|w| w.who == 30).nth(0).unwrap(); + + // python implementation output: + /* + 10 is elected with stake 26.31578947368421 and score 0.02 + 30 is elected with stake 23.684210526315788 and score 0.042222222222222223 + + 2 has load 0.02 and supported + 10 with stake 5.0 20 with stake 0.0 + 4 has load 0.042222222222222223 and supported + 10 with stake 21.31578947368421 30 with stake 23.684210526315788 + */ + + assert_eq!(winner_10.exposure.total, 1000 + 26); + assert_eq!(winner_10.score, Perquintill::from_fraction(0.02)); + assert_eq!(winner_10.exposure.others[0].value, 21); + assert_eq!(winner_10.exposure.others[1].value, 5); + + assert_eq!(winner_30.exposure.total, 23); + assert_eq!(winner_30.score, Perquintill::from_quintillionths(42222222222222222)); + assert_eq!(winner_30.exposure.others[0].value, 23); + }) +} + +#[test] +fn switching_roles() { + // Show: It should be possible to switch between roles (nominator, validator, idle) with minimal overhead. + with_externalities(&mut ExtBuilder::default() + .nominate(false) + .sessions_per_era(3) + .build(), + || { + assert_eq!(Session::validators(), vec![20, 10]); + + // put some money in account that we'll use. + for i in 1..7 { Balances::set_free_balance(&i, 5000); } + + // add 2 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![10, 6])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(4), vec![20, 2])); + + // add a new validator candidate + assert_ok!(Staking::bond(Origin::signed(5), 6, 1500, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); + + // new block + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + // no change + assert_eq!(Session::validators(), vec![20, 10]); + + // new block + System::set_block_number(2); + Session::check_rotate_session(System::block_number()); + + // no change + assert_eq!(Session::validators(), vec![20, 10]); + + // new block --> ne era --> new validators + System::set_block_number(3); + Session::check_rotate_session(System::block_number()); + + // with current nominators 10 and 4 have the most stake + assert_eq!(Session::validators(), vec![6, 10]); + + // 2 decides to be a validator. Consequences: + // 6 will not be chosen in the next round (no votes) + // 2 itself will be chosen + 20 who now has the higher votes + // 10 wil have no votes. + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + System::set_block_number(4); + Session::check_rotate_session(System::block_number()); + assert_eq!(Session::validators(), vec![6, 10]); + + System::set_block_number(5); + Session::check_rotate_session(System::block_number()); + assert_eq!(Session::validators(), vec![6, 10]); + + // ne era + System::set_block_number(6); + Session::check_rotate_session(System::block_number()); + assert_eq!(Session::validators(), vec![2, 20]); + }); +} + +#[test] +fn wrong_vote_is_null() { + with_externalities(&mut ExtBuilder::default() + .session_length(1) + .sessions_per_era(1) + .nominate(false) + .validator_pool(true) + .build(), + || { + // from the first era onward, only two will be chosen + assert_eq!(Session::validators(), vec![40, 30, 20, 10]); + + // put some money in account that we'll use. + for i in 1..3 { Balances::set_free_balance(&i, 5000); } + + // add 1 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![ + 10, 20, // good votes + 1, 2, 15, 1000, 25 // crap votes. No effect. + ])); + + // new block + System::set_block_number(1); + Session::check_rotate_session(System::block_number()); + + assert_eq!(Session::validators(), vec![20, 10]); }); } diff --git a/srml/sudo/Cargo.toml b/srml/sudo/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ef0bb59b538c5519b6b1f1cb7e4301d115eb5cac --- /dev/null +++ b/srml/sudo/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "srml-sudo" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +hex-literal = "0.1.0" +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } +parity-codec-derive = { version = "3.1", default-features = false } +sr-std = { path = "../../core/sr-std", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +srml-support = { path = "../support", default-features = false } +srml-support-procedural = { path = "../support/procedural" } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +sr-io = { path = "../../core/sr-io", default-features = false } +substrate-primitives = { path = "../../core/primitives" } + +[features] +default = ["std"] +std = [ + "serde", + "parity-codec/std", + "parity-codec-derive/std", + "sr-std/std", + "sr-primitives/std", + "srml-support/std", + "system/std", +] diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e4dfa480e9e3ee638383b40031a6a42409ebf698 --- /dev/null +++ b/srml/sudo/src/lib.rs @@ -0,0 +1,75 @@ +// 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 . + +//! The Example: A simple example of a runtime module demonstrating +//! concepts, APIs and structures common to most runtime modules. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sr_std::prelude::*; +use sr_primitives::traits::StaticLookup; +use srml_support::{StorageValue, Parameter, Dispatchable, decl_module, decl_event, decl_storage, ensure}; +use system::ensure_signed; + +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// A sudo-able call. + type Proposal: Parameter + Dispatchable; +} + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what its working on. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + fn sudo(origin, proposal: Box) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), "only the current sudo key can sudo"); + + let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok(); + Self::deposit_event(RawEvent::Sudid(ok)); + } + + fn set_key(origin, new: ::Source) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), "only the current sudo key can change the sudo key"); + let new = T::Lookup::lookup(new)?; + + Self::deposit_event(RawEvent::KeyChanged(Self::key())); + >::put(new); + } + } +} + +/// An event in this module. +decl_event!( + pub enum Event where AccountId = ::AccountId { + /// A sudo just took place. + Sudid(bool), + /// The sudoer just switched identity; the old key is supplied. + KeyChanged(AccountId), + } +); + +decl_storage! { + trait Store for Module as Sudo { + Key get(key) config(): T::AccountId; + } +} diff --git a/srml/support/Cargo.toml b/srml/support/Cargo.toml index 251964475c23843ad22cf0fb4f4fd6ec5a147e68..357aa0c75737f799e7449422004e18225cede1c6 100644 --- a/srml/support/Cargo.toml +++ b/srml/support/Cargo.toml @@ -2,34 +2,41 @@ name = "srml-support" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = { version = "0.1.0", optional = true } -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -parity-codec = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } srml-metadata = { path = "../metadata", default-features = false } sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } srml-support-procedural = { path = "./procedural" } -mashup = "0.1.7" +paste = "0.1" +once_cell = { version = "0.1.6", default-features = false, optional = true } +spin = "0.5" +bitmask = { git = "https://github.com/paritytech/bitmask", default-features = false } [dev-dependencies] pretty_assertions = "0.5.1" -parity-codec-derive = { version = "2.1" } [features] default = ["std"] std = [ "hex-literal", - "serde/std", + "once_cell", + "bitmask/std", + "serde", "serde_derive", - "sr-io/std", + "runtime_io/std", "parity-codec/std", "sr-std/std", "sr-primitives/std", "srml-metadata/std", + "inherents/std", ] nightly = [] strict = [] diff --git a/srml/support/procedural/Cargo.toml b/srml/support/procedural/Cargo.toml index 206ce708f95ffd19d092484d724941efe8f1b8ea..b01b45a4453225ecdff4e083938efafd6568b506 100644 --- a/srml/support/procedural/Cargo.toml +++ b/srml/support/procedural/Cargo.toml @@ -2,6 +2,7 @@ name = "srml-support-procedural" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [lib] proc-macro = true diff --git a/srml/support/procedural/src/lib.rs b/srml/support/procedural/src/lib.rs index 395e474b83e53c72f829162831781a59aa23411b..5464302e29b696fe1a10aace6f1e8419034c02c5 100644 --- a/srml/support/procedural/src/lib.rs +++ b/srml/support/procedural/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,16 +21,6 @@ #![recursion_limit="256"] extern crate proc_macro; -extern crate proc_macro2; - -#[macro_use] -extern crate syn; - -#[macro_use] -extern crate quote; - -#[macro_use] -extern crate srml_support_procedural_tools; mod storage; @@ -40,7 +30,7 @@ use proc_macro::TokenStream; /// /// ## Example /// -/// ```compile_fail +/// ```nocompile /// decl_storage! { /// trait Store for Module as Example { /// Dummy get(dummy) config(): Option; @@ -53,6 +43,33 @@ use proc_macro::TokenStream; /// storage item. This allows you to gain access to publicly visible storage items from a /// module type. Currently you must disambiguate by using `::Item` rather than /// the simpler `Module::Item`. Hopefully the rust guys with fix this soon. +/// +/// An optional `GenesisConfig` struct for storage initialization can be defined, either specifically as in : +/// ```nocompile +/// decl_storage! { +/// trait Store for Module as Example { +/// } +/// add_extra_genesis { +/// config(genesis_field): GenesisFieldType; +/// build(|_: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, _: &GenesisConfig| { +/// }) +/// } +/// } +/// ``` +/// or when at least one storage field requires default initialization (both `get` and `config` or `build`). +/// This struct can be expose as `Config` by `decl_runtime` macro. +/// +/// ### Module with instances +/// +/// `decl_storage!` macro support building modules with instances with the following syntax: (DefaultInstance type +/// is optionnal) +/// ```nocompile +/// trait Store for Module, I: Instance=DefaultInstance> as Example {} +/// ``` +/// +/// Then the genesis config is generated with two generic parameter `GenesisConfig` +/// and storages are now accessible using two generic parameters like: +/// `>::get()` or `Dummy::::get()` #[proc_macro] pub fn decl_storage(input: TokenStream) -> TokenStream { storage::transformation::decl_storage_impl(input) diff --git a/srml/support/procedural/src/storage/impls.rs b/srml/support/procedural/src/storage/impls.rs new file mode 100644 index 0000000000000000000000000000000000000000..efbb9a8d7a69f13bd0b2506b1cc2ef090947f373 --- /dev/null +++ b/srml/support/procedural/src/storage/impls.rs @@ -0,0 +1,540 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use proc_macro2::TokenStream as TokenStream2; +use syn; +use quote::quote; +use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts}; + +pub fn option_unwrap(is_option: bool) -> TokenStream2 { + if !is_option { + // raw type case + quote!( unwrap_or_else ) + } else { + // Option<> type case + quote!( or_else ) + } +} + +pub(crate) struct Impls<'a, I: Iterator> { + pub scrate: &'a TokenStream2, + pub visibility: &'a syn::Visibility, + pub traitinstance: &'a syn::Ident, + pub traittype: &'a syn::TypeParamBound, + pub instance_opts: &'a InstanceOpts, + pub type_infos: DeclStorageTypeInfos<'a>, + pub fielddefault: TokenStream2, + pub prefix: String, + pub cratename: &'a syn::Ident, + pub name: &'a syn::Ident, + pub attrs: I, +} + +impl<'a, I: Iterator> Impls<'a, I> { + pub fn simple_value(self) -> TokenStream2 { + let Self { + scrate, + visibility, + traitinstance, + traittype, + instance_opts, + type_infos, + fielddefault, + prefix, + name, + attrs, + .. + } = self; + let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; + let option_simple_1 = option_unwrap(is_option); + + let mutate_impl = if !is_option { + quote!{ + >::put(&val, storage) + } + } else { + quote!{ + match val { + Some(ref val) => >::put(&val, storage), + None => >::kill(storage), + } + } + }; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#method_name(#prefix.as_bytes()) } + } else { + quote!{ #prefix.as_bytes() } + }; + + // generator for value + quote!{ + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>); + + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance, #instance> { + type Query = #value_type; + + /// Get the storage key. + fn key() -> &'static [u8] { + #final_prefix + } + + /// Load the value from the provided storage instance. + fn get(storage: &S) -> Self::Query { + storage.get(>::key()) + .#option_simple_1(|| #fielddefault) + } + + /// Take a value from storage, removing it afterwards. + fn take(storage: &S) -> Self::Query { + storage.take(>::key()) + .#option_simple_1(|| #fielddefault) + } + + /// Mutate the value under a key. + fn mutate R, S: #scrate::GenericStorage>(f: F, storage: &S) -> R { + let mut val = >::get(storage); + + let ret = f(&mut val); + #mutate_impl ; + ret + } + } + } + } + + pub fn map(self, kty: &syn::Type) -> TokenStream2 { + let Self { + scrate, + visibility, + traitinstance, + traittype, + instance_opts, + type_infos, + fielddefault, + prefix, + name, + attrs, + .. + } = self; + let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; + let option_simple_1 = option_unwrap(is_option); + + let mutate_impl = if !is_option { + quote!{ + >::insert(key, &val, storage) + } + } else { + quote!{ + match val { + Some(ref val) => >::insert(key, &val, storage), + None => >::remove(key, storage), + } + } + }; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#method_name(#prefix.as_bytes()) } + } else { + quote!{ #prefix.as_bytes() } + }; + + // generator for map + quote!{ + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>); + + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> { + type Query = #value_type; + + /// Get the prefix key in storage. + fn prefix() -> &'static [u8] { + #final_prefix + } + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { + let mut key = >::prefix().to_vec(); + #scrate::codec::Encode::encode_to(x, &mut key); + key + } + + /// Load the value associated with the given key from the map. + fn get(key: &#kty, storage: &S) -> Self::Query { + let key = >::key_for(key); + storage.get(&key[..]).#option_simple_1(|| #fielddefault) + } + + /// Take the value, reading and removing it. + fn take(key: &#kty, storage: &S) -> Self::Query { + let key = >::key_for(key); + storage.take(&key[..]).#option_simple_1(|| #fielddefault) + } + + /// Mutate the value under a key + fn mutate R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R { + let mut val = >::get(key, storage); + + let ret = f(&mut val); + #mutate_impl ; + ret + } + + } + } + } + + pub fn linked_map(self, kty: &syn::Type) -> TokenStream2 { + let Self { + scrate, + visibility, + traitinstance, + traittype, + instance_opts, + type_infos, + fielddefault, + prefix, + name, + attrs, + .. + } = self; + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + + let final_prefix = if let Some(instance) = instance { + let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#method_name(#prefix.as_bytes()) } + } else { + quote!{ #prefix.as_bytes() } + }; + + // make sure to use different prefix for head and elements. + let final_head_key = if let Some(instance) = instance { + let method_name = syn::Ident::new(&format!("build_head_key_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + quote!{ #instance::#method_name(#prefix.as_bytes()) } + } else { + let final_head_key = format!("head of {}", prefix); + quote!{ #final_head_key.as_bytes() } + }; + + let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; + let option_simple_1 = option_unwrap(is_option); + let name_lowercase = name.to_string().to_lowercase(); + let inner_module = syn::Ident::new(&format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span()); + let linkage = syn::Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span()); + let phantom_data = quote! { #scrate::storage::generator::PhantomData }; + let as_map = quote!{ > }; + let put_or_insert = quote! { + match linkage { + Some(linkage) => storage.put(key_for, &(val, linkage)), + None => #as_map::insert(key, &val, storage), + } + }; + let mutate_impl = if !type_infos.is_option { + put_or_insert + } else { + quote! { + match val { + Some(ref val) => #put_or_insert, + None => #as_map::remove(key, storage), + } + } + }; + + // generator for linked map + let helpers = quote! { + /// Linkage data of an element (it's successor and predecessor) + #[derive(#scrate::codec::Encode, #scrate::codec::Decode)] + pub(crate) struct #linkage { + /// Previous element key in storage (None for the first element) + pub previous: Option, + /// Next element key in storage (None for the last element) + pub next: Option, + } + + mod #inner_module { + use super::*; + + /// Re-exported version of linkage to overcome proc-macro derivation issue. + pub(crate) use super::#linkage as Linkage; + + impl Default for Linkage { + fn default() -> Self { + Self { + previous: None, + next: None, + } + } + } + + /// A key-value pair iterator for enumerable map. + pub(crate) struct Enumerator<'a, S, K, V> { + pub storage: &'a S, + pub next: Option, + pub _data: #phantom_data, + } + + impl<'a, S: #scrate::GenericStorage, #traitinstance: #traittype, #instance #bound_instantiable> Iterator for Enumerator<'a, S, #kty, (#typ, #traitinstance, #instance)> + where #traitinstance: 'a + { + type Item = (#kty, #typ); + + fn next(&mut self) -> Option { + let next = self.next.take()?; + let key_for = as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(&next); + let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for) + .expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed"); + self.next = linkage.next; + Some((next, val)) + } + } + + pub(crate) trait Utils<#traitinstance: #traittype, #instance #bound_instantiable> { + /// Update linkage when this element is removed. + /// + /// Takes care of updating previous and next elements points + /// as well as updates head if the element is first or last. + fn remove_linkage(linkage: Linkage<#kty>, storage: &S); + + /// Read the contained data and it's linkage. + fn read_with_linkage(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)>; + + /// Generate linkage for newly inserted element. + /// + /// Takes care of updating head and previous head's pointer. + fn new_head_linkage( + storage: &S, + key: &#kty, + ) -> Linkage<#kty>; + + /// Read current head pointer. + fn read_head(storage: &S) -> Option<#kty>; + + /// Overwrite current head pointer. + /// + /// If `None` is given head is removed from storage. + fn write_head(storage: &S, head: Option<&#kty>); + } + } + }; + + let structure = quote! { + #( #[ #attrs ] )* + #visibility struct #name<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>(#phantom_data<(#traitinstance #comma_instance)>); + + impl<#traitinstance: #traittype, #instance #bound_instantiable> self::#inner_module::Utils<#traitinstance, #instance> for #name<#traitinstance, #instance> { + fn remove_linkage( + linkage: self::#inner_module::Linkage<#kty>, + storage: &S, + ) { + use self::#inner_module::Utils; + + let next_key = linkage.next.as_ref().map(|x| #as_map::key_for(x)); + let prev_key = linkage.previous.as_ref().map(|x| #as_map::key_for(x)); + + if let Some(prev_key) = prev_key { + // Retrieve previous element and update `next` + let mut res = Self::read_with_linkage(storage, &*prev_key) + .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); + res.1.next = linkage.next; + storage.put(&*prev_key, &res); + } else { + // we were first so let's update the head + Self::write_head(storage, linkage.next.as_ref()); + } + + if let Some(next_key) = next_key { + // Update previous of next element + let mut res = Self::read_with_linkage(storage, &*next_key) + .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); + res.1.previous = linkage.previous; + storage.put(&*next_key, &res); + } + } + + fn read_with_linkage( + storage: &S, + key: &[u8], + ) -> Option<(#value_type, self::#inner_module::Linkage<#kty>)> { + storage.get(key) + } + + fn new_head_linkage( + storage: &S, + key: &#kty, + ) -> self::#inner_module::Linkage<#kty> { + use self::#inner_module::Utils; + + if let Some(head) = Self::read_head(storage) { + // update previous head predecessor + { + let head_key = #as_map::key_for(&head); + let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#" + head is set when first element is inserted and unset when last element is removed; + if head is Some then it points to existing key; qed + "#); + storage.put(&*head_key, &(data, self::#inner_module::Linkage { + next: linkage.next.as_ref(), + previous: Some(key), + })); + } + // update to current head + Self::write_head(storage, Some(key)); + // return linkage with pointer to previous head + let mut linkage = self::#inner_module::Linkage::default(); + linkage.next = Some(head); + linkage + } else { + // we are first - update the head and produce empty linkage + Self::write_head(storage, Some(key)); + self::#inner_module::Linkage::default() + } + } + + fn read_head(storage: &S) -> Option<#kty> { + storage.get(#final_head_key) + } + + fn write_head(storage: &S, head: Option<&#kty>) { + match head { + Some(head) => storage.put(#final_head_key, head), + None => storage.kill(#final_head_key), + } + } + } + }; + + quote! { + #helpers + + #structure + + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance, #instance> { + type Query = #value_type; + + /// Get the prefix key in storage. + fn prefix() -> &'static [u8] { + #final_prefix + } + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn key_for(key: &#kty) -> #scrate::rstd::vec::Vec { + let mut key_for = #as_map::prefix().to_vec(); + #scrate::codec::Encode::encode_to(&key, &mut key_for); + key_for + } + + /// Load the value associated with the given key from the map. + fn get(key: &#kty, storage: &S) -> Self::Query { + storage.get(&*#as_map::key_for(key)).#option_simple_1(|| #fielddefault) + } + + /// Take the value, reading and removing it. + fn take(key: &#kty, storage: &S) -> Self::Query { + use self::#inner_module::Utils; + + let res: Option<(#value_type, self::#inner_module::Linkage<#kty>)> = storage.take(&*#as_map::key_for(key)); + match res { + Some((data, linkage)) => { + Self::remove_linkage(linkage, storage); + data + }, + None => #fielddefault, + } + } + + /// Remove the value under a key. + fn remove(key: &#kty, storage: &S) { + #as_map::take(key, storage); + } + + /// Store a value to be associated with the given key from the map. + fn insert(key: &#kty, val: &#typ, storage: &S) { + use self::#inner_module::Utils; + + let key_for = &*#as_map::key_for(key); + let linkage = match Self::read_with_linkage(storage, key_for) { + // overwrite but reuse existing linkage + Some((_data, linkage)) => linkage, + // create new linkage + None => Self::new_head_linkage(storage, key), + }; + storage.put(key_for, &(val, linkage)) + } + + /// Mutate the value under a key + fn mutate R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R { + use self::#inner_module::Utils; + + let key_for = &*#as_map::key_for(key); + let (mut val, linkage) = Self::read_with_linkage(storage, key_for) + .map(|(data, linkage)| (data, Some(linkage))) + .unwrap_or_else(|| (#fielddefault, None)); + + let ret = f(&mut val); + #mutate_impl ; + ret + } + } + + impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #scrate::storage::generator::EnumerableStorageMap<#kty, #typ> for #name<#traitinstance, #instance> { + fn head(storage: &S) -> Option<#kty> { + use self::#inner_module::Utils; + + Self::read_head(storage) + } + + fn enumerate<'a, S: #scrate::GenericStorage>(storage: &'a S) -> #scrate::storage::generator::Box + 'a> where + #kty: 'a, + #typ: 'a, + { + use self::#inner_module::{Utils, Enumerator}; + + #scrate::storage::generator::Box::new(Enumerator { + next: Self::read_head(storage), + storage, + _data: #phantom_data::<(#typ, #traitinstance, #instance)>::default(), + }) + } + } + } + } +} diff --git a/srml/support/procedural/src/storage/mod.rs b/srml/support/procedural/src/storage/mod.rs index 737a5a87f311083fddfe0243de2aa8b37e304010..7bb547c4f7bdba29ea75388367bc856286fb47b4 100644 --- a/srml/support/procedural/src/storage/mod.rs +++ b/srml/support/procedural/src/storage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,14 +19,17 @@ // end::description[] use srml_support_procedural_tools::syn_ext as ext; +use srml_support_procedural_tools::{ToTokens, Parse, custom_keyword, custom_keyword_impl}; -use syn::Ident; +use syn::{Ident, Token}; use syn::token::CustomKeyword; +mod impls; + pub mod transformation; /// Parsing usage only -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct StorageDefinition { pub hidden_crate: Option, pub visibility: syn::Visibility, @@ -36,49 +39,60 @@ struct StorageDefinition { pub module_ident: Ident, pub mod_lt_token: Token![<], pub mod_param: syn::GenericParam, + pub mod_instance_param_token: Option, + pub mod_instance: Option, + pub mod_instantiable_token: Option, + pub mod_instantiable: Option, + pub mod_default_instance_token: Option, + pub mod_default_instance: Option, pub mod_gt_token: Token![>], pub as_token: Token![as], pub crate_ident: Ident, pub content: ext::Braces>, pub extra_genesis: Option, + pub extra_genesis_skip_phantom_data_field: Option, } - -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct SpecificHiddenCrate { pub keyword: ext::CustomToken, pub ident: ext::Parens, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct AddExtraGenesis { pub extragenesis_keyword: ext::CustomToken, pub content: ext::Braces, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] +struct ExtraGenesisSkipPhantomDataField { + pub genesis_phantom_keyword: ext::CustomToken, + pub token: Token![;], +} + +#[derive(Parse, ToTokens, Debug)] struct AddExtraGenesisContent { pub lines: ext::Punctuated, } -#[derive(ParseEnum, ToTokensEnum, Debug)] +#[derive(Parse, ToTokens, Debug)] enum AddExtraGenesisLineEnum { AddExtraGenesisLine(AddExtraGenesisLine), AddExtraGenesisBuild(DeclStorageBuild), } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct AddExtraGenesisLine { pub attrs: ext::OuterAttributes, pub config_keyword: ext::CustomToken, pub extra_field: ext::Parens, pub coldot_token: Token![:], pub extra_type: syn::Type, - // TODO use a custom ext::Option instead (syn option on '=' fails) - pub default_value: ext::Seq, + pub default_value: ext::Opt, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct DeclStorageLine { // attrs (main use case is doc) pub attrs: ext::OuterAttributes, @@ -91,36 +105,36 @@ struct DeclStorageLine { pub build: Option, pub coldot_token: Token![:], pub storage_type: DeclStorageType, - // TODO use a custom ext::Option instead (syn option on '=' fails) - pub default_value: ext::Seq, + pub default_value: ext::Opt, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct DeclStorageGetter { pub getter_keyword: ext::CustomToken, pub getfn: ext::Parens, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct DeclStorageConfig { pub config_keyword: ext::CustomToken, pub expr: ext::Parens>, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct DeclStorageBuild { pub build_keyword: ext::CustomToken, pub expr: ext::Parens, } -#[derive(ParseEnum, ToTokensEnum, Debug)] +#[derive(Parse, ToTokens, Debug)] enum DeclStorageType { Map(DeclStorageMap), + LinkedMap(DeclStorageLinkedMap), Simple(syn::Type), } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] struct DeclStorageMap { pub map_keyword: ext::CustomToken, pub key: syn::Type, @@ -128,7 +142,15 @@ struct DeclStorageMap { pub value: syn::Type, } -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageLinkedMap { + pub map_keyword: ext::CustomToken, + pub key: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] struct DeclStorageDefault { pub equal_token: Token![=], pub expr: syn::Expr, @@ -142,3 +164,5 @@ custom_keyword_impl!(DeclStorageBuild, "build", "storage build config"); custom_keyword_impl!(AddExtraGenesis, "add_extra_genesis", "storage extra genesis"); custom_keyword_impl!(DeclStorageGetter, "get", "storage getter"); custom_keyword!(MapKeyword, "map", "map as keyword"); +custom_keyword!(LinkedMapKeyword, "linked_map", "linked_map as keyword"); +custom_keyword_impl!(ExtraGenesisSkipPhantomDataField, "extra_genesis_skip_phantom_data_field", "extra_genesis_skip_phantom_data_field as keyword"); diff --git a/srml/support/procedural/src/storage/transformation.rs b/srml/support/procedural/src/storage/transformation.rs index 8887a76f70dddd9cddcfb849859687540f916340..c2c7438673a269aff36b2a1b19400ef57f7e861c 100644 --- a/srml/support/procedural/src/storage/transformation.rs +++ b/srml/support/procedural/src/storage/transformation.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ // end::description[] use srml_support_procedural_tools::syn_ext as ext; -use srml_support_procedural_tools::{generate_crate_access, generate_hidden_includes}; +use srml_support_procedural_tools::{generate_crate_access, generate_hidden_includes, clean_type_string}; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; @@ -31,11 +31,15 @@ use syn::{ parse::{ Error, Result, - } + }, + parse_macro_input, }; +use quote::quote; use super::*; +const NUMBER_OF_INSTANCE: usize = 16; + // try macro but returning tokenized error macro_rules! try_tok(( $expre : expr ) => { match $expre { @@ -55,18 +59,27 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { ident: storetype, module_ident, mod_param: strait, + mod_instance, + mod_instantiable, + mod_default_instance, crate_ident: cratename, content: ext::Braces { content: storage_lines, ..}, extra_genesis, + extra_genesis_skip_phantom_data_field, .. } = def; + + let instance_opts = match get_instance_opts(mod_instance, mod_instantiable, mod_default_instance) { + Ok(opts) => opts, + Err(err) => return err.to_compile_error().into(), + }; + let hidden_crate_name = hidden_crate.map(|rc| rc.ident.content).map(|i| i.to_string()) .unwrap_or_else(|| "decl_storage".to_string()); let scrate = generate_crate_access(&hidden_crate_name, "srml-support"); let scrate_decl = generate_hidden_includes( &hidden_crate_name, "srml-support", - "srml_support", ); let ( @@ -88,13 +101,16 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { &scrate, &traitinstance, &traittype, + &instance_opts, &storage_lines, &extra_genesis, + extra_genesis_skip_phantom_data_field.is_some(), )); let decl_storage_items = decl_storage_items( &scrate, &traitinstance, &traittype, + &instance_opts, &cratename, &storage_lines, ); @@ -103,35 +119,56 @@ pub fn decl_storage_impl(input: TokenStream) -> TokenStream { ); let impl_store_items = impl_store_items( &traitinstance, + &instance_opts.instance, &storage_lines, ); let impl_store_fns = impl_store_fns( &scrate, &traitinstance, + &instance_opts.instance, &storage_lines, ); - let store_functions_to_metadata = store_functions_to_metadata( + let (store_default_struct, store_functions_to_metadata) = store_functions_to_metadata( &scrate, + &traitinstance, + &traittype, + &instance_opts, &storage_lines, ); + + let InstanceOpts { + instance, + bound_instantiable, + .. + } = instance_opts; + let cratename_string = cratename.to_string(); let expanded = quote! { #scrate_decl #decl_storage_items #visibility trait #storetype { - #decl_store_items + #decl_store_items } - impl<#traitinstance: #traittype> #storetype for #module_ident<#traitinstance> { + #store_default_struct + impl<#traitinstance: #traittype, #instance #bound_instantiable> #storetype for #module_ident<#traitinstance, #instance> { #impl_store_items } - impl<#traitinstance: #traittype> #module_ident<#traitinstance> { + impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> #module_ident<#traitinstance, #instance> { #impl_store_fns + #[doc(hidden)] pub fn store_metadata() -> #scrate::storage::generator::StorageMetadata { #scrate::storage::generator::StorageMetadata { - prefix: #scrate::storage::generator::DecodeDifferent::Encode(#cratename_string), - functions: #store_functions_to_metadata , + functions: #scrate::storage::generator::DecodeDifferent::Encode(#store_functions_to_metadata) , } } + #[doc(hidden)] + pub fn store_metadata_functions() -> &'static [#scrate::storage::generator::StorageFunctionMetadata] { + #store_functions_to_metadata + } + #[doc(hidden)] + pub fn store_metadata_name() -> &'static str { + #cratename_string + } } #extra_genesis @@ -145,18 +182,30 @@ fn decl_store_extra_genesis( scrate: &TokenStream2, traitinstance: &Ident, traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, storage_lines: &ext::Punctuated, extra_genesis: &Option, + extra_genesis_skip_phantom_data_field: bool, ) -> Result { + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; + let mut is_trait_needed = false; let mut has_trait_field = false; + let mut serde_complete_bound = std::collections::HashSet::new(); let mut config_field = TokenStream2::new(); let mut config_field_default = TokenStream2::new(); let mut builders = TokenStream2::new(); for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, getter, config, @@ -166,58 +215,87 @@ fn decl_store_extra_genesis( .. } = sline; - let is_simple = if let DeclStorageType::Simple(..) = storage_type { true } else { false }; + let type_infos = get_type_infos(storage_type); let mut opt_build; // need build line - if let (Some(ref getter), Some(ref config)) = (getter, config) { + if let Some(ref config) = config { let ident = if let Some(ident) = config.expr.content.as_ref() { quote!( #ident ) - } else { + } else if let Some(ref getter) = getter { let ident = &getter.getfn.content; quote!( #ident ) + } else { + return Err( + Error::new_spanned( + name, + "Invalid storage definiton, couldn't find config identifier: storage must either have a get identifier \ + `get(ident)` or a defined config identifier `config(ident)`" + ) + ); }; - let option_extracteed = if let DeclStorageType::Simple(ref st) = storage_type { - if ext::has_parametric_type(st, traitinstance) { - is_trait_needed = true; - has_trait_field = true; - } - ext::extract_type_option(st) - } else { None }; - let is_option = option_extracteed.is_some(); - let storage_type = option_extracteed.unwrap_or_else(|| quote!( #storage_type )); - config_field.extend(quote!( pub #ident: #storage_type, )); + if type_infos.kind.is_simple() && ext::has_parametric_type(type_infos.value_type, traitinstance) { + is_trait_needed = true; + has_trait_field = true; + } + + serde_complete_bound.insert(type_infos.value_type); + if let DeclStorageTypeInfosKind::Map { key_type, .. } = type_infos.kind { + serde_complete_bound.insert(key_type); + } + + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); + + let storage_type = type_infos.typ.clone(); + config_field.extend(match type_infos.kind { + DeclStorageTypeInfosKind::Simple => { + quote!( #( #[ #attrs ] )* pub #ident: #storage_type, ) + }, + DeclStorageTypeInfosKind::Map {key_type, .. } => { + quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key_type, #storage_type)>, ) + }, + }); opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b )) - .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) ))); - let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d| - if is_option { + .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance, #instance>| config.#ident.clone()) ))); + + let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d| + if type_infos.is_option { quote!( #d.unwrap_or_default() ) } else { quote!( #d ) }).unwrap_or_else(|| quote!( Default::default() )); - config_field_default.extend(quote!( #ident: #fielddefault, )); + config_field_default.extend(quote!( #ident: #fielddefault, )); } else { opt_build = build.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b )); } + let typ = type_infos.typ; if let Some(builder) = opt_build { is_trait_needed = true; - if is_simple { - builders.extend(quote!{{ - use #scrate::codec::Encode; - let v = (#builder)(&self); - r.insert(Self::hash(<#name<#traitinstance>>::key()).to_vec(), v.encode()); - }}); - } else { - builders.extend(quote!{{ - use #scrate::codec::Encode; - let data = (#builder)(&self); - for (k, v) in data.into_iter() { - r.insert(Self::hash(&<#name<#traitinstance>>::key_for(k)).to_vec(), v.encode()); - } - }}); - } + builders.extend(match type_infos.kind { + DeclStorageTypeInfosKind::Simple => { + quote!{{ + use #scrate::rstd::{cell::RefCell, marker::PhantomData}; + use #scrate::codec::{Encode, Decode}; + + let v = (#builder)(&self); + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>>::put(&v, &storage); + }} + }, + DeclStorageTypeInfosKind::Map { key_type, .. } => { + quote!{{ + use #scrate::rstd::{cell::RefCell, marker::PhantomData}; + use #scrate::codec::{Encode, Decode}; + + let data = (#builder)(&self); + for (k, v) in data.into_iter() { + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>>::insert(&k, &v, &storage); + } + }} + }, + }); } } @@ -242,11 +320,14 @@ fn decl_store_extra_genesis( is_trait_needed = true; has_trait_field = true; } + + serde_complete_bound.insert(extra_type); + let extrafield = &extra_field.content; genesis_extrafields.extend(quote!{ #attrs pub #extrafield: #extra_type, }); - let extra_default = default_value.inner.get(0).map(|d| &d.expr).map(|e| quote!{ #e }) + let extra_default = default_value.inner.as_ref().map(|d| &d.expr).map(|e| quote!{ #e }) .unwrap_or_else(|| quote!( Default::default() )); genesis_extrafields_default.extend(quote!{ #extrafield: #extra_default, @@ -264,29 +345,50 @@ fn decl_store_extra_genesis( } } + + let serde_bug_bound = if !serde_complete_bound.is_empty() { + let mut b_ser = String::new(); + let mut b_dser = String::new(); + // panic!("{:#?}", serde_complete_bound); + serde_complete_bound.into_iter().for_each(|bound| { + let stype = quote!(#bound); + b_ser.push_str(&format!("{} : {}::serde::Serialize, ", stype, scrate)); + b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", stype, scrate)); + }); + + quote! { + #[serde(bound(serialize = #b_ser))] + #[serde(bound(deserialize = #b_dser))] + } + } else { + quote!() + }; + let is_extra_genesis_needed = has_scall || !config_field.is_empty() || !genesis_extrafields.is_empty() || !builders.is_empty(); Ok(if is_extra_genesis_needed { - let (fparam, sparam, ph_field, ph_default) = if is_trait_needed { - if has_trait_field { + let (fparam_struct, fparam_impl, sparam, ph_field, ph_default) = if is_trait_needed { + if (has_trait_field && instance.is_none()) || extra_genesis_skip_phantom_data_field { // no phantom data required ( - quote!(<#traitinstance: #traittype>), - quote!(<#traitinstance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable>), + quote!(<#traitinstance, #instance>), quote!(), quote!(), ) } else { // need phantom data ( - quote!(<#traitinstance: #traittype>), - quote!(<#traitinstance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>), + quote!(<#traitinstance: #traittype, #instance #bound_instantiable>), + quote!(<#traitinstance, #instance>), quote!{ #[serde(skip)] - pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<#traitinstance>, + pub _genesis_phantom_data: #scrate::storage::generator::PhantomData<(#traitinstance #comma_instance)>, }, quote!{ _genesis_phantom_data: Default::default(), @@ -295,22 +397,23 @@ fn decl_store_extra_genesis( } } else { // do not even need type parameter - (quote!(), quote!(), quote!(), quote!()) + (quote!(), quote!(), quote!(), quote!(), quote!()) }; quote!{ - #[derive(Serialize, Deserialize)] + #[derive(#scrate::Serialize, #scrate::Deserialize)] #[cfg(feature = "std")] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] - pub struct GenesisConfig#fparam { + #serde_bug_bound + pub struct GenesisConfig#fparam_struct { #ph_field #config_field #genesis_extrafields } #[cfg(feature = "std")] - impl#fparam Default for GenesisConfig#sparam { + impl#fparam_impl Default for GenesisConfig#sparam { fn default() -> Self { GenesisConfig { #ph_default @@ -321,17 +424,18 @@ fn decl_store_extra_genesis( } #[cfg(feature = "std")] - impl#fparam #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam { - - fn build_storage(self) -> ::std::result::Result<(#scrate::runtime_primitives::StorageMap, #scrate::runtime_primitives::ChildrenStorageMap), String> { - let mut r: #scrate::runtime_primitives::StorageMap = Default::default(); - let mut c: #scrate::runtime_primitives::ChildrenStorageMap = Default::default(); + impl#fparam_impl #scrate::runtime_primitives::BuildStorage for GenesisConfig#sparam { + fn assimilate_storage(self, r: &mut #scrate::runtime_primitives::StorageOverlay, c: &mut #scrate::runtime_primitives::ChildrenStorageOverlay) -> ::std::result::Result<(), String> { + use #scrate::rstd::{cell::RefCell, marker::PhantomData}; + let storage = (RefCell::new(r), PhantomData::::default()); #builders - #scall(&mut r, &mut c, &self); + let r = storage.0.into_inner(); + + #scall(r, c, &self); - Ok((r, c)) + Ok(()) } } } @@ -344,13 +448,99 @@ fn decl_storage_items( scrate: &TokenStream2, traitinstance: &Ident, traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, cratename: &Ident, storage_lines: &ext::Punctuated, ) -> TokenStream2 { let mut impls = TokenStream2::new(); + + let InstanceOpts { + instance, + default_instance, + instantiable, + .. + } = instance_opts; + + // Build Instantiable trait + if instance.is_some() { + let mut method_defs = TokenStream2::new(); + let mut method_impls = TokenStream2::new(); + for sline in storage_lines.inner.iter() { + let DeclStorageLine { + storage_type, + name, + .. + } = sline; + + let type_infos = get_type_infos(storage_type); + + let method_name = syn::Ident::new(&format!("build_prefix_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + + method_defs.extend(quote!{ fn #method_name(prefix: &'static [u8]) -> &'static [u8]; }); + method_impls.extend(quote!{ + fn #method_name(prefix: &'static [u8]) -> &'static [u8] { + static LAZY: #scrate::lazy::Lazy<#scrate::rstd::vec::Vec> = #scrate::lazy::Lazy::INIT; + LAZY.get(|| { + let mut final_prefix = #scrate::rstd::vec::Vec::new(); + final_prefix.extend_from_slice(prefix); + final_prefix.extend_from_slice(Self::INSTANCE_PREFIX.as_bytes()); + final_prefix + }) + } + }); + + if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind { + let method_name = syn::Ident::new(&format!("build_head_key_once_for_{}", name.to_string()), proc_macro2::Span::call_site()); + + method_defs.extend(quote!{ fn #method_name(prefix: &'static [u8]) -> &'static [u8]; }); + method_impls.extend(quote!{ + fn #method_name(prefix: &'static [u8]) -> &'static [u8] { + static LAZY: #scrate::lazy::Lazy<#scrate::rstd::vec::Vec> = #scrate::lazy::Lazy::INIT; + LAZY.get(|| { + let mut final_prefix = #scrate::rstd::vec::Vec::new(); + final_prefix.extend_from_slice("head of ".as_bytes()); + final_prefix.extend_from_slice(prefix); + final_prefix.extend_from_slice(Self::INSTANCE_PREFIX.as_bytes()); + final_prefix + }) + } + }); + } + } + + impls.extend(quote! { + pub trait #instantiable: 'static { + const INSTANCE_PREFIX: &'static str; + #method_defs + } + }); + + let instances = (0..NUMBER_OF_INSTANCE) + .map(|i| { + let name = format!("Instance{}", i); + let ident = syn::Ident::new(&name, proc_macro2::Span::call_site()); + (name, ident) + }) + .chain(default_instance.clone().map(|ident| (String::new(), ident))); + + for (prefix, ident) in instances { + impls.extend(quote! { + // Those trait are derived because of wrong bounds for generics + #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)] + pub struct #ident; + impl #instantiable for #ident { + const INSTANCE_PREFIX: &'static str = #prefix; + #method_impls + } + }); + } + } + for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, storage_type, default_value, @@ -358,132 +548,36 @@ fn decl_storage_items( .. } = sline; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; - let is_option = extracted_opt.is_some(); - let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d| quote!( #d )) - .unwrap_or_else(|| quote!{ Default::default() }); - - let typ = extracted_opt.unwrap_or(quote!( #gettype )); + let type_infos = get_type_infos(storage_type); + let kind = type_infos.kind.clone(); + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); - let option_simple_1 = if !is_option { - // raw type case - quote!( unwrap_or_else ) - } else { - // Option<> type case - quote!( or_else ) + let i = impls::Impls { + scrate, + visibility, + cratename, + traitinstance, + traittype, + instance_opts, + type_infos, + fielddefault: default_value.inner.as_ref().map(|d| &d.expr).map(|d| quote!( #d )) + .unwrap_or_else(|| quote!{ Default::default() }), + prefix: format!("{} {}", cratename, name), + name, + attrs, }; - let implementation = if is_simple { - let mutate_impl = if !is_option { - quote!{ - >::put(&val, storage) - } - } else { - quote!{ - match val { - Some(ref val) => >::put(&val, storage), - None => >::kill(storage), - } - } - }; - - let key_string = cratename.to_string() + " " + &name.to_string(); - // generator for value - quote!{ - - #visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>); - - impl<#traitinstance: #traittype> #scrate::storage::generator::StorageValue<#typ> for #name<#traitinstance> { - type Query = #gettype; - - /// Get the storage key. - fn key() -> &'static [u8] { - #key_string.as_bytes() - } - - /// Load the value from the provided storage instance. - fn get(storage: &S) -> Self::Query { - storage.get(<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::key()) - .#option_simple_1(|| #fielddefault) - } - - /// Take a value from storage, removing it afterwards. - fn take(storage: &S) -> Self::Query { - storage.take(<#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::key()) - .#option_simple_1(|| #fielddefault) - } - - /// Mutate the value under a key. - fn mutate R, S: #scrate::GenericStorage>(f: F, storage: &S) -> R { - let mut val = >::get(storage); - - let ret = f(&mut val); - #mutate_impl ; - ret - } - } - - } - } else { - let kty = stk.expect("is not simple; qed"); - let mutate_impl = if !is_option { - quote!{ - >::insert(key, &val, storage) - } - } else { - quote!{ - match val { - Some(ref val) => >::insert(key, &val, storage), - None => >::remove(key, storage), - } - } - }; - let prefix_string = cratename.to_string() + " " + &name.to_string(); - // generator for map - quote!{ - #visibility struct #name<#traitinstance: #traittype>(#scrate::storage::generator::PhantomData<#traitinstance>); - - impl<#traitinstance: #traittype> #scrate::storage::generator::StorageMap<#kty, #typ> for #name<#traitinstance> { - type Query = #gettype; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8] { - #prefix_string.as_bytes() - } - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { - let mut key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::prefix().to_vec(); - #scrate::codec::Encode::encode_to(x, &mut key); - key - } - /// Load the value associated with the given key from the map. - fn get(key: &#kty, storage: &S) -> Self::Query { - let key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(key); - storage.get(&key[..]).#option_simple_1(|| #fielddefault) - } - - /// Take the value, reading and removing it. - fn take(key: &#kty, storage: &S) -> Self::Query { - let key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(key); - storage.take(&key[..]).#option_simple_1(|| #fielddefault) - } - - /// Mutate the value under a key - fn mutate R, S: #scrate::GenericStorage>(key: &#kty, f: F, storage: &S) -> R { - let mut val = >::take(key, storage); - - let ret = f(&mut val); - #mutate_impl ; - ret - } - - } - - } + let implementation = match kind { + DeclStorageTypeInfosKind::Simple => { + i.simple_value() + }, + DeclStorageTypeInfosKind::Map { key_type, is_linked: false } => { + i.map(key_type) + }, + DeclStorageTypeInfosKind::Map { key_type, is_linked: true } => { + i.linked_map(key_type) + }, }; impls.extend(implementation) } @@ -503,23 +597,30 @@ fn decl_store_items( fn impl_store_items( traitinstance: &Ident, + instance: &Option, storage_lines: &ext::Punctuated, ) -> TokenStream2 { storage_lines.inner.iter().map(|sline| &sline.name) .fold(TokenStream2::new(), |mut items, name| { - items.extend(quote!(type #name = #name<#traitinstance>;)); - items + items.extend( + quote!( + type #name = #name<#traitinstance, #instance>; + ) + ); + items }) } fn impl_store_fns( scrate: &TokenStream2, traitinstance: &Ident, + instance: &Option, storage_lines: &ext::Punctuated, ) -> TokenStream2 { let mut items = TokenStream2::new(); for sline in storage_lines.inner.iter() { let DeclStorageLine { + attrs, name, getter, storage_type, @@ -528,24 +629,29 @@ fn impl_store_fns( if let Some(getter) = getter { let get_fn = &getter.getfn.content; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; - let typ = extracted_opt.unwrap_or(quote!(#gettype)); - let item = if is_simple { - quote!{ - pub fn #get_fn() -> #gettype { - <#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage) + let type_infos = get_type_infos(storage_type); + let value_type = type_infos.value_type; + + // Propagate doc attributes. + let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); + + let typ = type_infos.typ; + let item = match type_infos.kind { + DeclStorageTypeInfosKind::Simple => { + quote!{ + #( #[ #attrs ] )* + pub fn #get_fn() -> #value_type { + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage) + } } - } - } else { - let kty = stk.expect("is not simple; qed"); - // map - quote!{ - pub fn #get_fn>(key: K) -> #gettype { - <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage) + }, + DeclStorageTypeInfosKind::Map { key_type, .. } => { + quote!{ + #( #[ #attrs ] )* + pub fn #get_fn>(key: K) -> #value_type { + <#name<#traitinstance, #instance> as #scrate::storage::generator::StorageMap<#key_type, #typ>> :: get(key.borrow(), &#scrate::storage::RuntimeStorage) + } } } }; @@ -557,54 +663,70 @@ fn impl_store_fns( fn store_functions_to_metadata ( scrate: &TokenStream2, + traitinstance: &Ident, + traittype: &syn::TypeParamBound, + instance_opts: &InstanceOpts, storage_lines: &ext::Punctuated, -) -> TokenStream2 { +) -> (TokenStream2, TokenStream2) { + + let InstanceOpts { + comma_instance, + equal_default_instance, + bound_instantiable, + instance, + .. + } = instance_opts; let mut items = TokenStream2::new(); + let mut default_getter_struct_def = TokenStream2::new(); for sline in storage_lines.inner.iter() { let DeclStorageLine { attrs, name, storage_type, + default_value, .. } = sline; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; + let type_infos = get_type_infos(storage_type); + let value_type = type_infos.value_type; - let is_option = extracted_opt.is_some(); - let typ = extracted_opt.unwrap_or(quote!( #gettype )); - let stype = if is_simple { - let styp = typ.to_string(); - quote!{ - #scrate::storage::generator::StorageFunctionType::Plain( - #scrate::storage::generator::DecodeDifferent::Encode(#styp), - ) - } - } else { - let kty = stk.expect("is not simple; qed"); - let kty = quote!(#kty).to_string(); - let styp = typ.to_string(); - quote!{ - #scrate::storage::generator::StorageFunctionType::Map { - key: #scrate::storage::generator::DecodeDifferent::Encode(#kty), - value: #scrate::storage::generator::DecodeDifferent::Encode(#styp), + let typ = type_infos.typ; + let styp = clean_type_string(&typ.to_string()); + let stype = match type_infos.kind { + DeclStorageTypeInfosKind::Simple => { + quote!{ + #scrate::storage::generator::StorageFunctionType::Plain( + #scrate::storage::generator::DecodeDifferent::Encode(#styp), + ) } - } + }, + DeclStorageTypeInfosKind::Map { key_type, .. } => { + let kty = clean_type_string("e!(#key_type).to_string()); + quote!{ + #scrate::storage::generator::StorageFunctionType::Map { + key: #scrate::storage::generator::DecodeDifferent::Encode(#kty), + value: #scrate::storage::generator::DecodeDifferent::Encode(#styp), + } + } + }, }; - let modifier = if !is_option { + let modifier = if type_infos.is_option { quote!{ - #scrate::storage::generator::StorageFunctionModifier::Default + #scrate::storage::generator::StorageFunctionModifier::Optional } } else { quote!{ - #scrate::storage::generator::StorageFunctionModifier::Optional + #scrate::storage::generator::StorageFunctionModifier::Default } }; + let default = default_value.inner.as_ref().map(|d| &d.expr) + .map(|d| { + quote!( #d ) + }) + .unwrap_or_else(|| quote!( Default::default() )); let mut docs = TokenStream2::new(); - for attr in attrs.inner.iter().filter_map(|v| v.interpret_meta()) { + for attr in attrs.inner.iter().filter_map(|v| v.parse_meta().ok()) { if let syn::Meta::NameValue(syn::MetaNameValue{ ref ident, ref lit, @@ -616,20 +738,148 @@ fn store_functions_to_metadata ( } } let str_name = name.to_string(); + let struct_name = proc_macro2::Ident::new(&("__GetByteStruct".to_string() + &str_name), name.span()); + let cache_name = proc_macro2::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), name.span()); let item = quote! { #scrate::storage::generator::StorageFunctionMetadata { name: #scrate::storage::generator::DecodeDifferent::Encode(#str_name), modifier: #modifier, ty: #stype, + default: #scrate::storage::generator::DecodeDifferent::Encode( + #scrate::storage::generator::DefaultByteGetter( + &#struct_name::<#traitinstance, #instance>(#scrate::rstd::marker::PhantomData) + ) + ), documentation: #scrate::storage::generator::DecodeDifferent::Encode(&[ #docs ]), }, }; items.extend(item); + let def_get = quote! { + #[doc(hidden)] + pub struct #struct_name<#traitinstance, #instance #bound_instantiable #equal_default_instance>(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>); + #[cfg(feature = "std")] + #[allow(non_upper_case_globals)] + static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = #scrate::once_cell::sync::OnceCell::INIT; + #[cfg(feature = "std")] + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { + use #scrate::codec::Encode; + #cache_name.get_or_init(|| { + let def_val: #value_type = #default; + <#value_type as Encode>::encode(&def_val) + }).clone() + } + } + #[cfg(not(feature = "std"))] + impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance, #instance> { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { + use #scrate::codec::Encode; + let def_val: #value_type = #default; + <#value_type as Encode>::encode(&def_val) + } + } + }; + default_getter_struct_def.extend(def_get); + } + (default_getter_struct_def, quote!{ + { + &[ + #items + ] + } + }) +} + + +#[derive(Debug, Clone)] +pub(crate) struct DeclStorageTypeInfos<'a> { + pub is_option: bool, + pub typ: TokenStream2, + pub value_type: &'a syn::Type, + kind: DeclStorageTypeInfosKind<'a>, +} + +#[derive(Debug, Clone)] +enum DeclStorageTypeInfosKind<'a> { + Simple, + Map { + key_type: &'a syn::Type, + is_linked: bool, + }, +} + +impl<'a> DeclStorageTypeInfosKind<'a> { + fn is_simple(&self) -> bool { + match *self { + DeclStorageTypeInfosKind::Simple => true, + _ => false, + } } +} + +fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos { + let (value_type, kind) = match storage_type { + DeclStorageType::Simple(ref st) => (st, DeclStorageTypeInfosKind::Simple), + DeclStorageType::Map(ref map) => (&map.value, DeclStorageTypeInfosKind::Map { + key_type: &map.key, + is_linked: false, + }), + DeclStorageType::LinkedMap(ref map) => (&map.value, DeclStorageTypeInfosKind::Map { + key_type: &map.key, + is_linked: true, + }), + }; - quote!{ - #scrate::storage::generator::DecodeDifferent::Encode(&[ - #items - ]) + let extracted_type = ext::extract_type_option(value_type); + let is_option = extracted_type.is_some(); + let typ = extracted_type.unwrap_or(quote!( #value_type )); + + DeclStorageTypeInfos { + is_option, + typ, + value_type, + kind, + } + +} + +#[derive(Default)] +pub(crate) struct InstanceOpts { + pub instance: Option, + pub default_instance: Option, + pub instantiable: Option, + pub comma_instance: TokenStream2, + pub equal_default_instance: TokenStream2, + pub bound_instantiable: TokenStream2, +} + +fn get_instance_opts( + instance: Option, + instantiable: Option, + default_instance: Option, +) -> syn::Result { + + let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; + + match (instance, instantiable, default_instance) { + (Some(instance), Some(instantiable), default_instance_def) => { + let (equal_default_instance, default_instance) = if let Some(default_instance) = default_instance_def { + (quote!{= #default_instance}, Some(default_instance)) + } else { + (quote!{}, None) + }; + Ok(InstanceOpts { + comma_instance: quote!{, #instance}, + equal_default_instance, + bound_instantiable: quote!{: #instantiable}, + instance: Some(instance), + default_instance, + instantiable: Some(instantiable), + }) + }, + (None, None, None) => Ok(Default::default()), + (Some(instance), None, _) => Err(syn::Error::new(instance.span(), format!("Expect instantiable trait bound for instance: {}. {}", instance, right_syntax))), + (None, Some(instantiable), _) => Err(syn::Error::new(instantiable.span(), format!("Expect instance generic for bound instantiable: {}. {}", instantiable, right_syntax))), + (None, _, Some(default_instance)) => Err(syn::Error::new(default_instance.span(), format!("Expect instance generic for default instance: {}. {}", default_instance, right_syntax))), } } diff --git a/srml/support/procedural/tools/Cargo.toml b/srml/support/procedural/tools/Cargo.toml index c773bc65d8ae1cea2a33982075d98d76efdbbd83..0c8dfe156844eedb3f7423063e20d1f771c2f8f2 100644 --- a/srml/support/procedural/tools/Cargo.toml +++ b/srml/support/procedural/tools/Cargo.toml @@ -2,9 +2,11 @@ name = "srml-support-procedural-tools" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] srml-support-procedural-tools-derive = { path = "./derive" } proc-macro2 = "0.4" quote = { version = "0.6" } syn = { version = "0.15", features = ["full"] } +proc-macro-crate = "0.1.3" diff --git a/srml/support/procedural/tools/derive/Cargo.toml b/srml/support/procedural/tools/derive/Cargo.toml index d55659442e40c6cbafafd8adcb142a21ec01dc04..aa6e6e736e0d1773ddcd67af39d77ecad12a1629 100644 --- a/srml/support/procedural/tools/derive/Cargo.toml +++ b/srml/support/procedural/tools/derive/Cargo.toml @@ -2,6 +2,7 @@ name = "srml-support-procedural-tools-derive" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [lib] proc-macro = true diff --git a/srml/support/procedural/tools/derive/src/lib.rs b/srml/support/procedural/tools/derive/src/lib.rs index acb6b744d21d58db14e55f0707092e425755a878..0e3fcb22475fc2e9babeeb3a3c7268c4a16ab018 100644 --- a/srml/support/procedural/tools/derive/src/lib.rs +++ b/srml/support/procedural/tools/derive/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,21 +18,14 @@ //! Use to derive parsing for parsing struct. // end::description[] - #![recursion_limit = "128"] -#[macro_use] -extern crate syn; - -#[macro_use] -extern crate quote; - extern crate proc_macro; -extern crate proc_macro2; use proc_macro::TokenStream; use proc_macro2::Span; - +use syn::parse_macro_input; +use quote::quote; pub(crate) fn fields_idents( fields: impl Iterator, @@ -59,16 +52,30 @@ pub(crate) fn fields_access( }) } -/// self defined parsing struct (use where clause on struct for it: not meant for good struct -/// design but fast parse impl). -#[proc_macro_derive(ParseStruct)] -pub fn derive_parse_struct(input: TokenStream) -> TokenStream { +/// self defined parsing struct or enum. +/// not meant for any struct/enum, just for fast +/// parse implementation. +/// For enums: +/// variant are tested in order of definition. +/// Empty variant is always true. +/// Please use carefully, this will fully parse successfull variant twice. +#[proc_macro_derive(Parse)] +pub fn derive_parse(input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + match item { + syn::Item::Enum(input) => derive_parse_enum(input), + syn::Item::Struct(input) => derive_parse_struct(input), + _ => TokenStream::new(), // ignore + } +} + +fn derive_parse_struct(input: syn::ItemStruct) -> TokenStream { let syn::ItemStruct { ident, generics, fields, .. - } = parse_macro_input!(input as syn::ItemStruct); + } = input; let field_names = { let name = fields_idents(fields.iter().map(Clone::clone)); quote!{ @@ -93,42 +100,13 @@ pub fn derive_parse_struct(input: TokenStream) -> TokenStream { tokens.into() } -#[proc_macro_derive(ToTokensStruct)] -pub fn derive_totokens_struct(input: TokenStream) -> TokenStream { - let syn::ItemStruct { - ident, - generics, - fields, - .. - } = parse_macro_input!(input as syn::ItemStruct); - let fields = fields_access(fields.iter().map(Clone::clone)); - let tokens = quote! { - - impl #generics quote::ToTokens for #ident #generics { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - #( - self.#fields.to_tokens(tokens); - )* - } - } - - }; - tokens.into() -} - - -/// self defined parsing enum, variant are tested in order of definition. -/// Empty variant allways true. -/// Please use carefully, this will fully parse successfull variant twice. -#[proc_macro_derive(ParseEnum)] -pub fn derive_parse_enum(input: TokenStream) -> TokenStream { - +fn derive_parse_enum(input: syn::ItemEnum) -> TokenStream { let syn::ItemEnum { ident, generics, variants, .. - } = parse_macro_input!(input as syn::ItemEnum); + } = input; let variants = variants.iter().map(|v| { let variant_ident = v.ident.clone(); let fields_build = if v.fields.iter().count() > 0 { @@ -187,15 +165,51 @@ pub fn derive_parse_enum(input: TokenStream) -> TokenStream { tokens.into() } -/// only output field (empty field act as a None) -#[proc_macro_derive(ToTokensEnum)] -pub fn derive_totokens_enum(input: TokenStream) -> TokenStream { +/// self defined parsing struct or enum. +/// not meant for any struct/enum, just for fast +/// parse implementation. +/// For enum: +/// it only output fields (empty field act as a None). +#[proc_macro_derive(ToTokens)] +pub fn derive_totokens(input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + match item { + syn::Item::Enum(input) => derive_totokens_enum(input), + syn::Item::Struct(input) => derive_totokens_struct(input), + _ => TokenStream::new(), // ignore + } +} + +fn derive_totokens_struct(input: syn::ItemStruct) -> TokenStream { + let syn::ItemStruct { + ident, + generics, + fields, + .. + } = input; + + let fields = fields_access(fields.iter().map(Clone::clone)); + let tokens = quote! { + + impl #generics quote::ToTokens for #ident #generics { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + #( + self.#fields.to_tokens(tokens); + )* + } + } + + }; + tokens.into() +} + +fn derive_totokens_enum(input: syn::ItemEnum) -> TokenStream { let syn::ItemEnum { ident, generics, variants, .. - } = parse_macro_input!(input as syn::ItemEnum); + } = input; let variants = variants.iter().map(|v| { let v_ident = v.ident.clone(); let fields_build = if v.fields.iter().count() > 0 { diff --git a/srml/support/procedural/tools/src/lib.rs b/srml/support/procedural/tools/src/lib.rs index d37831fb1f20976568bd3fa84aa0e6211d7315ad..34b96df8104b50e33656a3636cb55530d9f84963 100644 --- a/srml/support/procedural/tools/src/lib.rs +++ b/srml/support/procedural/tools/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,18 +18,13 @@ //! Proc macro helpers for procedural macros // end::description[] -extern crate syn; -#[macro_use] -extern crate quote; -extern crate proc_macro2; - -extern crate proc_macro; - -#[macro_use] extern crate srml_support_procedural_tools_derive; - // reexport proc macros pub use srml_support_procedural_tools_derive::*; +use proc_macro_crate::crate_name; +use syn::parse::Error; +use quote::quote; + pub mod syn_ext; #[macro_export] @@ -56,10 +51,7 @@ macro_rules! custom_keyword { } } - -// TODO following functions are copied from sr-api-macros : do a merge to get a unique procedural -// macro tooling crate (this crate path does not look good for it) - +// FIXME #1569, remove the following functions, which are copied from sr-api-macros use proc_macro2::{TokenStream, Span}; use syn::Ident; @@ -67,28 +59,57 @@ fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident { Ident::new(&format!("sr_api_hidden_includes_{}", unique_id), Span::call_site()) } -/// Generates the access to the `subtrate_client` crate. +/// Generates the access to the `srml-support` crate. pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream { if ::std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { - quote!( crate ) + quote::quote!( crate ) } else { let mod_name = generate_hidden_includes_mod_name(unique_id); - quote!( self::#mod_name::hidden_include ) - }.into() + quote::quote!( self::#mod_name::hidden_include ) + } } /// Generates the hidden includes that are required to make the macro independent from its scope. -pub fn generate_hidden_includes(unique_id: &str, def_crate: &str, crate_id: &str) -> TokenStream { - let crate_id = Ident::new(crate_id, Span::call_site()); +pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream { if ::std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { TokenStream::new() } else { let mod_name = generate_hidden_includes_mod_name(unique_id); - quote!( - #[doc(hidden)] - mod #mod_name { - pub extern crate #crate_id as hidden_include; + + match crate_name(def_crate) { + Ok(name) => { + let name = Ident::new(&name, Span::call_site()); + quote::quote!( + #[doc(hidden)] + mod #mod_name { + pub extern crate #name as hidden_include; + } + ) + }, + Err(e) => { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + quote!( #err ) } - ) - }.into() + } + + } +} + +// fn to remove white spaces arount string types +// (basically whitespaces arount tokens) +pub fn clean_type_string(input: &str) -> String { + input + .replace(" ::", "::") + .replace(":: ", "::") + .replace(" ,", ",") + .replace(" ;", ";") + .replace(" [", "[") + .replace("[ ", "[") + .replace(" ]", "]") + .replace(" (", "(") + .replace("( ", "(") + .replace(" )", ")") + .replace(" <", "<") + .replace("< ", "<") + .replace(" >", ">") } diff --git a/srml/support/procedural/tools/src/syn_ext.rs b/srml/support/procedural/tools/src/syn_ext.rs index 6998f6f511d73fe5125f9399b83bab858e146dea..c2136b2cd8f96599d09f8ce4ff34d5c6a2349142 100644 --- a/srml/support/procedural/tools/src/syn_ext.rs +++ b/srml/support/procedural/tools/src/syn_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,13 +25,14 @@ use syn::parse::{ }; use syn::token::CustomKeyword; use proc_macro2::TokenStream as T2; -use quote::ToTokens; +use quote::{ToTokens, quote}; use std::iter::once; use syn::Ident; +use srml_support_procedural_tools_derive::{ToTokens, Parse}; /// stop parsing here getting remaining token as content /// Warn duplicate stream (part of) -#[derive(ParseStruct, ToTokensStruct, Debug)] +#[derive(Parse, ToTokens, Debug)] pub struct StopParse { pub inner: T2, } @@ -191,33 +192,25 @@ impl ToTokens for OuterAttributes { } #[derive(Debug)] -pub struct Seq

{ - pub inner: Vec

, +pub struct Opt

{ + pub inner: Option

, } -impl Parse for Seq

{ +impl Parse for Opt

{ // Note that it cost a double parsing (same as enum derive) fn parse(input: ParseStream) -> Result { - let mut inner = Vec::new(); - loop { - let fork = input.fork(); - let res: Result

= fork.parse(); - match res { - Ok(_item) => { - // move cursor - let item: P = input.parse().expect("Same parsing ran before"); - inner.push(item); - }, - Err(_e) => break, - } - } - Ok(Seq { inner }) + let inner = match input.fork().parse::

() { + Ok(_item) => Some(input.parse().expect("Same parsing ran before")), + Err(_e) => None, + }; + + Ok(Opt { inner }) } } -impl ToTokens for Seq

{ +impl ToTokens for Opt

{ fn to_tokens(&self, tokens: &mut T2) { - for p in self.inner.iter() { + if let Some(ref p) = self.inner { p.to_tokens(tokens); } } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 4d0815c41f5a169c4b034e209e1bd3203902b755..c6151d23903f8161adb45e7572c0595968bad27a 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,26 +14,39 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Dispatch system. Just dispatches calls. +//! Dispatch system. Contains a macro for defining runtime modules and +//! generating values representing lazy module function calls. -pub use rstd::prelude::{Vec, Clone, Eq, PartialEq}; +pub use crate::rstd::prelude::{Vec, Clone, Eq, PartialEq}; #[cfg(feature = "std")] pub use std::fmt; -pub use rstd::result; -pub use codec::{Codec, Decode, Encode, Input, Output}; +pub use crate::rstd::result; +pub use crate::codec::{Codec, Decode, Encode, Input, Output, HasCompact, EncodeAsRef}; pub use srml_metadata::{ - ModuleMetadata, FunctionMetadata, DecodeDifferent, - CallMetadata, FunctionArgumentMetadata, OuterDispatchMetadata, OuterDispatchCall + FunctionMetadata, DecodeDifferent, DecodeDifferentArray, + FunctionArgumentMetadata, OuterDispatchMetadata, OuterDispatchCall }; +/// A type that can not be instantiated. +pub enum Never {} + +/// Result of a module function call; either nothing (functions are only called for "side effects") +/// or an error message. pub type Result = result::Result<(), &'static str>; +/// A lazy call (module function and argument values) that can be executed via its dispatch() +/// method. pub trait Dispatchable { + /// Every function call to your runtime has an origin which specifies where the extrinsic was + /// generated from. In the case of a signed extrinsic (transaction), the origin contains an + /// identifier for the caller. The origin can be empty in the case of an inherent extrinsic. type Origin; type Trait; fn dispatch(self, origin: Self::Origin) -> Result; } +/// Serializable version of Dispatchable. +/// This value can be used as a "function" in an extrinsic. pub trait Callable { type Call: Dispatchable + Codec + Clone + PartialEq + Eq; } @@ -54,43 +67,74 @@ pub trait Parameter: Codec + Clone + Eq {} #[cfg(not(feature = "std"))] impl Parameter for T where T: Codec + Clone + Eq {} -/// Declare a struct for this module, then implement dispatch logic to create a pairing of several -/// dispatch traits and enums. +/// Declare a module struct and implement the dispatch logic. +/// +/// Usually used as follows: +/// +/// decl_module! { +/// pub struct Module for enum Call where origin: T::Origin +///{} +/// } +/// +/// where "Trait" is a trait describing this module's requirements for the Runtime type. +/// T::Origin is declared using a impl_outer_origin! per-module macro (which is generated by the +/// construct_runtime! macro) and automatically includes all the modules that are used by the +/// runtime (alongside with a variant called "system"). +/// +/// A runtime module is a collection of functions unified by a common problem domain and certain +/// shared types. The "functions" do not actually return values (see Dispatchable) and are only +/// used for side effects. /// -/// The `on_finalise` function is special, since it can either take no parameters, -/// or one parameter, which has the runtime's block number type. +/// For every module an associated enum (usually "Call") is generated with every variant +/// corresponding to a function of the module. This enum implements Callable and thus its values +/// can be used as an extrinsic's payload. +/// +/// The `on_initialise` and `on_finalise` functions are special, since it can either take no +/// parameters, or one parameter, which has the runtime's block number type. +/// +/// ### Module with instances +/// +/// decl_module! support modules with instances with the following syntax: (DefaultInstance type is +/// optionnal) +/// ```nocompile +/// pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {} +/// ``` #[macro_export] macro_rules! decl_module { + // Macro transformations (to convert invocations with incomplete parameters to the canonical + // form) ( $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty { $($t:tt)* } ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = system {} {} + {} [] $($t)* ); }; ( $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $($t:tt)* } ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system {} {} + {} [] $($t)* ); @@ -98,20 +142,22 @@ macro_rules! decl_module { (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event() = default; + $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* () = default; $($rest:tt)* ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system - { $vis fn deposit_event() = default; } + { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* () = default; } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* ] $($rest)* @@ -119,20 +165,24 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {} + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* ( + $($param_name:ident : $param:ty),* + ) { $( $impl:tt )* } $($rest:tt)* ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system - { $vis fn deposit_event($( $param_name: $param ),* ) { $( $impl )* } } + { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* ($( $param_name: $param ),* ) { $( $impl )* } } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* ] $($rest)* @@ -140,9 +190,10 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident - { $( $deposit_event:tt )* } + { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } {} [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* @@ -151,9 +202,10 @@ macro_rules! decl_module { ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { fn on_finalise( $( $param_name : $param ),* ) { $( $impl )* } } [ $($t)* ] $($rest)* @@ -161,43 +213,70 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $deposit_event:tt )* } + {} + { $( $on_finalise:tt )* } + [ $($t:tt)* ] + $(#[doc = $doc_attr:tt])* + fn on_initialise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $deposit_event )* } + { fn on_initialise( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $on_finalise )* } + [ $($t)* ] + $($rest)* + ); + }; + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - $origin:ident $(, $param_name:ident : $param:ty)* + $origin:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* $(#[doc = $doc_attr])* $fn_vis fn $fn_name( - $origin $( , $param_name : $param )* + $origin $( , $(#[$codec_attr])* $param_name : $param )* ) $( -> $result )* { $( $impl )* } + { $($instance: $instantiable)? } ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - $origin:ident : T::Origin $(, $param_name:ident : $param:ty)* + $origin:ident : T::Origin $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -209,14 +288,15 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - origin : $origin:ty $(, $param_name:ident : $param:ty)* + origin : $origin:ty $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -228,272 +308,335 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - $( $param_name:ident : $param:ty),* + $( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),* ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } [ $($t)* $(#[doc = $doc_attr])* $fn_vis fn $fn_name( - root $( , $param_name : $param )* + root $( , $(#[$codec_attr])* $param_name : $param )* ) $( -> $result )* { $( $impl )* } + { $($instance: $instantiable)? } ] $($rest)* ); }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } [ $($t:tt)* ] ) => { decl_module!(@imp $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $($t)* } { $( $deposit_event )* } + { $( $on_initialise )* } { $( $on_finalise )* } ); }; + // Implementation of Call enum's .dispatch() method. + // TODO: this probably should be a different macro? + (@call root - $mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] + $mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] ) => { { $system::ensure_root($origin)?; - <$mod_type<$trait_instance>>::$fn_name( $( $param_name ),* ) + <$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $( $param_name ),* ) } }; (@call $ingore:ident - $mod_type:ident $trait_instance:ident $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] + $mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ] ) => { - <$mod_type<$trait_instance>>::$fn_name( $origin $(, $param_name )* ) + <$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $origin $(, $param_name )* ) }; // no `deposit_event` function wanted (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path)?>; $system:ident; ) => {}; (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $system:ident; - $vis:vis fn deposit_event() = default; + $vis:vis fn deposit_event$(<$event_trait_instance:ident $(, $event_instance:ident)?>)?() = default; ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn deposit_event(event: Event<$trait_instance>) { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> { + $vis fn deposit_event(event: Event$(<$event_trait_instance $(, $event_instance)?>)?) { <$system::Module<$trait_instance>>::deposit_event( - <$trait_instance as $trait_name>::Event::from(event).into() + <$trait_instance as $trait_name$(<$instance>)?>::Event::from(event).into() ); } } }; (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $system:ident; $vis:vis fn deposit_event($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> { $vis fn deposit_event($param: $param_ty) { $( $impl )* } } }; + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_initialise() { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + { + fn on_initialise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + } + }; + + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + fn on_initialise($param:ident : $param_ty:ty) { $( $impl:tt )* } + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + { + fn on_initialise($param: $param_ty) { $( $impl )* } + } + }; + + (@impl_on_initialise + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::runtime_primitives::traits::OnInitialise<$trait_instance::BlockNumber> + for $module<$trait_instance$(, $instance)?> + {} + }; + (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; fn on_finalise() { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> { + for $module<$trait_instance$(, $instance)?> + { fn on_finalise(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; fn on_finalise($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> { + for $module<$trait_instance$(, $instance)?> + { fn on_finalise($param: $param_ty) { $( $impl )* } } }; (@impl_on_finalise - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; ) => { - impl<$trait_instance: $trait_name> + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $crate::runtime_primitives::traits::OnFinalise<$trait_instance::BlockNumber> - for $module<$trait_instance> {} + for $module<$trait_instance$(, $instance)?> + { + } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; root; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result { - { $( $impl )* } - Ok(()) - } + $(#[doc = $doc_attr])* + $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result { + { $( $impl )* } + Ok(()) } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; root; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) -> $result:ty { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($( $param: $param_ty ),* ) -> $result { - $( $impl )* - } + $(#[doc = $doc_attr])* + $vis fn $name($( $param: $param_ty ),* ) -> $result { + $( $impl )* } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; $ignore:ident; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( $origin:ident $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name( - $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::Result { - { $( $impl )* } - Ok(()) - } + $(#[doc = $doc_attr])* + $vis fn $name( + $origin: $origin_ty $(, $param: $param_ty )* + ) -> $crate::dispatch::Result { + { $( $impl )* } + Ok(()) } }; (@impl_function - $module:ident<$trait_instance:ident: $trait_name:ident>; + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; $ignore:ident; + $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( $origin:ident $(, $param:ident : $param_ty:ty )* ) -> $result:ty { $( $impl:tt )* } ) => { - impl<$trait_instance: $trait_name> $module<$trait_instance> { - $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { - $( $impl )* - } + $(#[doc = $doc_attr])* + $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { + $( $impl )* } }; + // The main macro expansion that actually renders the module code. + (@imp $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - $from:ident $( , $param_name:ident : $param:ty)* + $from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } + { $($fn_instance:ident: $fn_instantiable:path)? } )* } { $( $deposit_event:tt )* } + { $( $on_initialise:tt )* } { $( $on_finalise:tt )* } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] - // TODO: switching based on std feature is because of an issue in + // FIXME: switching based on std feature is because of an issue in // serde-derive for when we attempt to derive `Deserialize` on these types, // in a situation where we've imported `srml_support` as another name. #[cfg(feature = "std")] - pub struct $mod_type<$trait_instance: $trait_name>(::std::marker::PhantomData<$trait_instance>); + pub struct $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)?>(::std::marker::PhantomData<($trait_instance $(, $instance)?)>); // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] #[cfg(not(feature = "std"))] - pub struct $mod_type<$trait_instance: $trait_name>(::core::marker::PhantomData<$trait_instance>); + pub struct $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)?>(::core::marker::PhantomData<($trait_instance $(, $instance)?)>); + + decl_module! { + @impl_on_initialise + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + $( $on_initialise )* + } decl_module! { @impl_on_finalise - $mod_type<$trait_instance: $trait_name>; + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; $( $on_finalise )* } decl_module! { @impl_deposit_event - $mod_type<$trait_instance: $trait_name>; + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; $system; $( $deposit_event )* } - $( - decl_module! { - @impl_function - $mod_type<$trait_instance: $trait_name>; - $origin_type; - $from; - $fn_vis fn $fn_name ( - $from $(, $param_name : $param )* - ) $( -> $result )* { $( $impl )* } - } - )* + /// Can also be called using [`Call`]. + /// + /// [`Call`]: enum.Call.html + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + $( + decl_module! { + @impl_function + $mod_type<$trait_instance: $trait_name $(, $fn_instance: $fn_instantiable)?>; + $origin_type; + $from; + $(#[doc = $doc_attr])* + $fn_vis fn $fn_name ( + $from $(, $param_name : $param )* + ) $( -> $result )* { $( $impl )* } + } + )* + } #[cfg(feature = "std")] $(#[$attr])* - pub enum $call_type<$trait_instance: $trait_name> { - __PhantomItem(::std::marker::PhantomData<$trait_instance>), - __OtherPhantomItem(::std::marker::PhantomData<$trait_instance>), + pub enum $call_type<$trait_instance: $trait_name$(, $instance: $instantiable $( = $module_default_instance)?)?> { + #[doc(hidden)] + __PhantomItem(::std::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never), $( #[allow(non_camel_case_types)] + $(#[doc = $doc_attr])* $fn_name ( $( $param ),* ), )* } #[cfg(not(feature = "std"))] $(#[$attr])* - pub enum $call_type<$trait_instance: $trait_name> { - __PhantomItem(::core::marker::PhantomData<$trait_instance>), - __OtherPhantomItem(::core::marker::PhantomData<$trait_instance>), + pub enum $call_type<$trait_instance: $trait_name$(, $instance: $instantiable $( = $module_default_instance)?)?> { + #[doc(hidden)] + __PhantomItem(::core::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never), $( #[allow(non_camel_case_types)] + $(#[doc = $doc_attr])* $fn_name ( $( $param ),* ), )* } // manual implementation of clone/eq/partialeq because using derive erroneously requires // clone/eq/partialeq from T. - impl<$trait_instance: $trait_name> $crate::dispatch::Clone - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Clone + for $call_type<$trait_instance $(, $instance)?> { fn clone(&self) -> Self { match *self { @@ -505,8 +648,8 @@ macro_rules! decl_module { } } } - impl<$trait_instance: $trait_name> $crate::dispatch::PartialEq - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::PartialEq + for $call_type<$trait_instance $(, $instance)?> { fn eq(&self, _other: &Self) -> bool { match *self { @@ -517,8 +660,7 @@ macro_rules! decl_module { self_params == ( $( $param_name, )* ) } else { match *_other { - $call_type::__PhantomItem(_) => unreachable!(), - $call_type::__OtherPhantomItem(_) => unreachable!(), + $call_type::__PhantomItem(_, _) => unreachable!(), _ => false, } } @@ -528,13 +670,13 @@ macro_rules! decl_module { } } } - impl<$trait_instance: $trait_name> $crate::dispatch::Eq - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Eq + for $call_type<$trait_instance $(, $instance)?> {} #[cfg(feature = "std")] - impl<$trait_instance: $trait_name> $crate::dispatch::fmt::Debug - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::fmt::Debug + for $call_type<$trait_instance $(, $instance)?> { fn fmt(&self, _f: &mut $crate::dispatch::fmt::Formatter) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> { match *self { @@ -550,22 +692,20 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name> $crate::dispatch::Decode for $call_type<$trait_instance> { - fn decode(input: &mut I) -> Option { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Decode for $call_type<$trait_instance $(, $instance)?> { + fn decode(input: &mut Input) -> Option { let _input_id = input.read_byte()?; - __impl_decode!(input; _input_id; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*) + $crate::__impl_decode!(input; _input_id; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*) } } - impl<$trait_instance: $trait_name> $crate::dispatch::Encode for $call_type<$trait_instance> { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Encode for $call_type<$trait_instance $(, $instance)?> { fn encode_to(&self, _dest: &mut W) { - __impl_encode!(_dest; *self; 0; $call_type; $( fn $fn_name( $( $param_name ),* ); )*); - if let $call_type::__PhantomItem(_) = *self { unreachable!() } - if let $call_type::__OtherPhantomItem(_) = *self { unreachable!() } + $crate::__impl_encode!(_dest; *self; 0; $call_type; $( fn $fn_name( $( $(#[$codec_attr on type $param])* $param_name ),* ); )*); } } - impl<$trait_instance: $trait_name> $crate::dispatch::Dispatchable - for $call_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable + for $call_type<$trait_instance $(, $instance)?> { type Trait = $trait_instance; type Origin = $origin_type; @@ -573,31 +713,32 @@ macro_rules! decl_module { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { - decl_module!( + $crate::decl_module!( @call $from - $mod_type $trait_instance $fn_name _origin $system [ $( $param_name ),* ] + $mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ] ) }, )* - _ => { panic!("__PhantomItem should never be used.") }, + $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") }, } } } - impl<$trait_instance: $trait_name> $crate::dispatch::Callable - for $mod_type<$trait_instance> + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Callable + for $mod_type<$trait_instance $(, $instance)?> { - type Call = $call_type<$trait_instance>; + type Call = $call_type<$trait_instance $(, $instance)?>; } - impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + #[doc(hidden)] pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { d.dispatch(origin) } } - __dispatch_impl_metadata! { - $mod_type $trait_instance $trait_name $call_type $origin_type - {$( $(#[doc = $doc_attr])* fn $fn_name($from $(, $param_name : $param )*); )*} + $crate::__dispatch_impl_metadata! { + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?> $call_type $origin_type + {$( $(#[doc = $doc_attr])* fn $fn_name($from $(, $(#[$codec_attr])* $param_name : $param )*); )*} } } } @@ -611,19 +752,23 @@ macro_rules! __impl_decode { $fn_id:expr; $call_type:ident; fn $fn_name:ident( - $( $param_name:ident ),* + $( $(#[$codec_attr:ident on type $param:ty])* $param_name:ident ),* ); $($rest:tt)* ) => { { if $input_id == ($fn_id) { $( - let $param_name = $crate::dispatch::Decode::decode($input)?; + $crate::__impl_decode!(@decode + $(#[$codec_attr on type $param])* + $param_name; + $input; + ); )* return Some($call_type:: $fn_name( $( $param_name ),* )); } - __impl_decode!($input; $input_id; $fn_id + 1; $call_type; $($rest)*) + $crate::__impl_decode!($input; $input_id; $fn_id + 1; $call_type; $($rest)*) } }; ( @@ -633,7 +778,31 @@ macro_rules! __impl_decode { $call_type:ident; ) => { None - } + }; + (@decode + #[compact on type $param:ty] + $param_name:ident; + $input:expr; + ) => { + let $param_name = <<$param as $crate::dispatch::HasCompact>::Type as $crate::dispatch::Decode>::decode($input)?.into(); + }; + (@decode + $param_name:ident; + $input:expr; + ) => { + let $param_name = $crate::dispatch::Decode::decode($input)?; + }; + (@decode + $(#[$codec_attr:ident on type])* + $param_name:ident; + $input:expr; + ) => { + compile_error!(concat!( + "Invalid attribute for parameter `", + stringify!($param_name), + "`, the following attributes are supported: `#[compact]`" + )) + }; } #[macro_export] @@ -645,7 +814,7 @@ macro_rules! __impl_encode { $fn_id:expr; $call_type:ident; fn $fn_name:ident( - $( $param_name:ident ),* + $( $(#[$codec_attr:ident on type $param:ty])* $param_name:ident ),* ); $($rest:tt)* ) => { @@ -657,11 +826,15 @@ macro_rules! __impl_encode { ) = $self { $dest.push_byte(($fn_id) as u8); $( - $param_name.encode_to($dest); + $crate::__impl_encode!(@encode_as + $(#[$codec_attr on type $param])* + $param_name; + $dest; + ); )* } - __impl_encode!($dest; $self; $fn_id + 1; $call_type; $($rest)*) + $crate::__impl_encode!($dest; $self; $fn_id + 1; $call_type; $($rest)*) } }; ( @@ -669,7 +842,30 @@ macro_rules! __impl_encode { $self:expr; $fn_id:expr; $call_type:ident; - ) => {{}} + ) => {{}}; + (@encode_as + #[compact on type $param:ty] + $param_name:ident; + $dest:expr; + ) => { + <<$param as $crate::dispatch::HasCompact>::Type as $crate::dispatch::EncodeAsRef<$param>>::RefType::from($param_name).encode_to($dest); + }; + (@encode_as + $param_name:ident; + $dest:expr; + ) => { + $param_name.encode_to($dest); + }; + (@encode_as + $(#[$codec_attr:ident on type $param:ty])* + $param_name:ident; + $dest:expr; + ) => { + compile_error!(concat!( + "Invalid attribute for parameter `", stringify!($param_name), + "`, the following attributes are supported: `#[compact]`" + )) + }; } pub trait IsSubType { @@ -695,7 +891,7 @@ macro_rules! impl_outer_dispatch { $camelcase ( $crate::dispatch::CallableCallFor<$camelcase> ) ,)* } - __impl_outer_dispatch_common! { $call_type, $($camelcase,)* } + $crate::__impl_outer_dispatch_common! { $call_type, $($camelcase,)* } impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; @@ -718,7 +914,6 @@ macro_rules! impl_outer_dispatch { } } )* - __impl_outer_dispatch_metadata!($runtime; $call_type; $( $module::$camelcase, )*); } } @@ -732,76 +927,30 @@ macro_rules! __impl_outer_dispatch_common { impl $crate::dispatch::Decode for $call_type { fn decode(input: &mut I) -> Option { let input_id = input.read_byte()?; - __impl_decode!(input; input_id; 0; $call_type; $( fn $camelcase ( outer_dispatch_param ); )*) + $crate::__impl_decode!(input; input_id; 0; $call_type; $( fn $camelcase ( outer_dispatch_param ); )*) } } impl $crate::dispatch::Encode for $call_type { fn encode_to(&self, dest: &mut W) { - __impl_encode!(dest; *self; 0; $call_type; $( fn $camelcase( outer_dispatch_param ); )*) + $crate::__impl_encode!(dest; *self; 0; $call_type; $( fn $camelcase( outer_dispatch_param ); )*) } } } } -/// Implement metadata for outer dispatch. -#[macro_export] -#[doc(hidden)] -macro_rules! __impl_outer_dispatch_metadata { - ( - $runtime:ident; - $outer_name:ident; - $( $module:ident::$call:ident, )* - ) => { - impl $runtime { - pub fn outer_dispatch_metadata() -> $crate::dispatch::OuterDispatchMetadata { - $crate::dispatch::OuterDispatchMetadata { - name: $crate::dispatch::DecodeDifferent::Encode(stringify!($outer_name)), - calls: __impl_outer_dispatch_metadata!(@encode_calls 0; ; $( $module::$call, )*), - } - } - } - }; - (@encode_calls - $index:expr; - $( $encoded_call:expr ),*; - $module:ident::$call:ident, - $( $rest_module:ident::$rest:ident, )* - ) => { - __impl_outer_dispatch_metadata!( - @encode_calls - $index + 1; - $( $encoded_call, )* - $crate::dispatch::OuterDispatchCall { - name: $crate::dispatch::DecodeDifferent::Encode(stringify!($call)), - prefix: $crate::dispatch::DecodeDifferent::Encode(stringify!($module)), - index: $index, - }; - $( $rest_module::$rest, )* - ) - }; - (@encode_calls - $index:expr; - $( $encoded_call:expr ),*; - ) => { - $crate::dispatch::DecodeDifferent::Encode(&[ $( $encoded_call ),* ]) - }; -} - /// Implement metadata for dispatch. #[macro_export] #[doc(hidden)] macro_rules! __dispatch_impl_metadata { ( - $mod_type:ident $trait_instance:ident $trait_name:ident + $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?> $($rest:tt)* ) => { - impl<$trait_instance: $trait_name> $mod_type<$trait_instance> { - pub fn metadata() -> $crate::dispatch::ModuleMetadata { - $crate::dispatch::ModuleMetadata { - name: $crate::dispatch::DecodeDifferent::Encode(stringify!($mod_type)), - call: __call_to_metadata!($($rest)*), - } + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { + #[doc(hidden)] + pub fn call_functions() -> &'static [$crate::dispatch::FunctionMetadata] { + $crate::__call_to_functions!($($rest)*) } } } @@ -810,28 +959,26 @@ macro_rules! __dispatch_impl_metadata { /// Convert the list of calls into their JSON representation, joined by ",". #[macro_export] #[doc(hidden)] -macro_rules! __call_to_metadata { +macro_rules! __call_to_functions { ( $call_type:ident $origin_type:ty {$( $(#[doc = $doc_attr:tt])* fn $fn_name:ident($from:ident $( - , $param_name:ident : $param:ty + , $(#[$codec_attr:ident])* $param_name:ident : $param:ty )* ); )*} ) => { - $crate::dispatch::CallMetadata { - name: $crate::dispatch::DecodeDifferent::Encode(stringify!($call_type)), - functions: __functions_to_metadata!(0; $origin_type;; $( - fn $fn_name( $( $param_name: $param ),* ); - $( $doc_attr ),*; - )*), - } + $crate::__functions_to_metadata!(0; $origin_type;; $( + fn $fn_name( $($(#[$codec_attr])* $param_name: $param ),* ); + $( $doc_attr ),*; + )*) }; } + /// Convert a list of functions into a list of `FunctionMetadata` items. #[macro_export] #[doc(hidden)] @@ -842,16 +989,16 @@ macro_rules! __functions_to_metadata{ $( $function_metadata:expr ),*; fn $fn_name:ident( $( - $param_name:ident : $param:ty + $(#[$codec_attr:ident])* $param_name:ident : $param:ty ),* ); $( $fn_doc:expr ),*; $( $rest:tt )* ) => { - __functions_to_metadata!( + $crate::__functions_to_metadata!( $fn_id + 1; $origin_type; - $( $function_metadata, )* __function_to_metadata!( - fn $fn_name($( $param_name : $param ),*); $( $fn_doc ),*; $fn_id; + $( $function_metadata, )* $crate::__function_to_metadata!( + fn $fn_name($( $(#[$codec_attr])* $param_name : $param ),*); $( $fn_doc ),*; $fn_id; ); $($rest)* ) @@ -861,7 +1008,7 @@ macro_rules! __functions_to_metadata{ $origin_type:ty; $( $function_metadata:expr ),*; ) => { - $crate::dispatch::DecodeDifferent::Encode(&[ $( $function_metadata ),* ]) + &[ $( $function_metadata ),* ] } } @@ -871,25 +1018,41 @@ macro_rules! __functions_to_metadata{ macro_rules! __function_to_metadata { ( fn $fn_name:ident( - $($param_name:ident : $param:ty),* + $( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),* ); $( $fn_doc:expr ),*; $fn_id:expr; ) => { $crate::dispatch::FunctionMetadata { - id: $fn_id, name: $crate::dispatch::DecodeDifferent::Encode(stringify!($fn_name)), arguments: $crate::dispatch::DecodeDifferent::Encode(&[ $( $crate::dispatch::FunctionArgumentMetadata { name: $crate::dispatch::DecodeDifferent::Encode(stringify!($param_name)), - ty: $crate::dispatch::DecodeDifferent::Encode(stringify!($param)), + ty: $crate::dispatch::DecodeDifferent::Encode( + $crate::__function_to_metadata!(@stringify_expand_attr + $(#[$codec_attr])* $param_name: $param + ) + ), } ),* ]), documentation: $crate::dispatch::DecodeDifferent::Encode(&[ $( $fn_doc ),* ]), } }; + + (@stringify_expand_attr #[compact] $param_name:ident : $param:ty) => { + concat!("Compact<", stringify!($param), ">") + }; + + (@stringify_expand_attr $param_name:ident : $param:ty) => { stringify!($param) }; + + (@stringify_expand_attr $(#[codec_attr:ident])* $param_name:ident : $param:ty) => { + compile_error!(concat!( + "Invalid attribute for parameter `", stringify!($param_name), + "`, the following attributes are supported: `#[compact]`" + )) + } } #[cfg(test)] @@ -897,10 +1060,11 @@ macro_rules! __function_to_metadata { #[allow(dead_code)] mod tests { use super::*; + use crate::runtime_primitives::traits::{OnInitialise, OnFinalise}; pub trait Trait { type Origin; - type BlockNumber; + type BlockNumber: Into; } pub mod system { @@ -915,20 +1079,18 @@ mod tests { pub struct Module for enum Call where origin: T::Origin { /// Hi, this is a comment. fn aux_0(_origin) -> Result { unreachable!() } - fn aux_1(_origin, _data: i32) -> Result { unreachable!() } + fn aux_1(_origin, #[compact] _data: u32) -> Result { unreachable!() } fn aux_2(_origin, _data: i32, _data2: String) -> Result { unreachable!() } fn aux_3() -> Result { unreachable!() } fn aux_4(_data: i32) -> Result { unreachable!() } + + fn on_initialise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialise") } } + fn on_finalise(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalise") } } } } - const EXPECTED_METADATA: ModuleMetadata = ModuleMetadata { - name: DecodeDifferent::Encode("Module"), - call: CallMetadata { - name: DecodeDifferent::Encode("Call"), - functions: DecodeDifferent::Encode(&[ + const EXPECTED_METADATA: &'static [FunctionMetadata] = &[ FunctionMetadata { - id: 0, name: DecodeDifferent::Encode("aux_0"), arguments: DecodeDifferent::Encode(&[]), documentation: DecodeDifferent::Encode(&[ @@ -936,18 +1098,16 @@ mod tests { ]) }, FunctionMetadata { - id: 1, name: DecodeDifferent::Encode("aux_1"), arguments: DecodeDifferent::Encode(&[ FunctionArgumentMetadata { name: DecodeDifferent::Encode("_data"), - ty: DecodeDifferent::Encode("i32"), + ty: DecodeDifferent::Encode("Compact") } ]), documentation: DecodeDifferent::Encode(&[]), }, FunctionMetadata { - id: 2, name: DecodeDifferent::Encode("aux_2"), arguments: DecodeDifferent::Encode(&[ FunctionArgumentMetadata { @@ -962,13 +1122,11 @@ mod tests { documentation: DecodeDifferent::Encode(&[]), }, FunctionMetadata { - id: 3, name: DecodeDifferent::Encode("aux_3"), arguments: DecodeDifferent::Encode(&[]), documentation: DecodeDifferent::Encode(&[]), }, FunctionMetadata { - id: 4, name: DecodeDifferent::Encode("aux_4"), arguments: DecodeDifferent::Encode(&[ FunctionArgumentMetadata { @@ -978,9 +1136,7 @@ mod tests { ]), documentation: DecodeDifferent::Encode(&[]), } - ]), - }, - }; + ]; struct TraitImpl {} @@ -991,7 +1147,26 @@ mod tests { #[test] fn module_json_metadata() { - let metadata = Module::::metadata(); + let metadata = Module::::call_functions(); assert_eq!(EXPECTED_METADATA, metadata); } + + #[test] + fn compact_attr() { + let call: Call = Call::aux_1(0); + let encoded = call.encode(); + assert_eq!(encoded.len(), 2); + } + + #[test] + #[should_panic(expected = "on_initialise")] + fn on_initialise_should_work() { + as OnInitialise>::on_initialise(42); + } + + #[test] + #[should_panic(expected = "on_finalise")] + fn on_finalise_should_work() { + as OnFinalise>::on_finalise(42); + } } diff --git a/srml/support/src/double_map.rs b/srml/support/src/double_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..a6dad9eabec2bf766ba8be40e0b6fce48c16cab3 --- /dev/null +++ b/srml/support/src/double_map.rs @@ -0,0 +1,138 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! An implementation of double map backed by storage. + +use crate::rstd::prelude::*; +use crate::codec::{Codec, Encode}; +use crate::storage::unhashed; +use sr_std::borrow::Borrow; + +/// An implementation of a map with a two keys. +/// +/// It provides an important ability to efficiently remove all entries +/// that have a common first key. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part +/// is a hash of a `Key2`. +pub trait StorageDoubleMap { + type Key1: Codec; + type Key2: Codec; + type Value: Codec + Default; + + const PREFIX: &'static [u8]; + + /// Insert an entry into this map. + fn insert(k1: &Q, k2: &R, val: Self::Value) + where + Self::Key1: Borrow, + Self::Key2: Borrow, + Q: Codec, + R: Codec + { + unhashed::put(&Self::full_key(k1, k2)[..], &val); + } + + /// Remove an entry from this map. + fn remove(k1: &Q, k2: &R) + where + Self::Key1: Borrow, + Self::Key2: Borrow, + Q: Codec, + R: Codec + { + unhashed::kill(&Self::full_key(k1, k2)[..]); + } + + /// Get an entry from this map. + /// + /// If there is entry stored under the given keys, returns `None`. + fn get(k1: &Q, k2: &R) -> Option + where + Self::Key1: Borrow, + Self::Key2: Borrow, + Q: Codec, + R: Codec + { + unhashed::get(&Self::full_key(k1, k2)[..]) + } + + /// Returns `true` if value under the specified keys exists. + fn exists(k1: &Q, k2: &R) -> bool + where + Self::Key1: Borrow, + Self::Key2: Borrow, + Q: Codec, + R: Codec + { + unhashed::exists(&Self::full_key(k1, k2)[..]) + } + + /// Removes all entries that shares the `k1` as the first key. + fn remove_prefix(k1: &Q) + where + Self::Key1: Borrow, + Q: Codec + { + unhashed::kill_prefix(&Self::derive_key1(Self::encode_key1(k1))) + } + + /// Encode key1 into Vec and prepend a prefix + fn encode_key1(key: &Q) -> Vec + where + Self::Key1: Borrow, + Q: Codec + { + let mut raw_prefix = Vec::new(); + raw_prefix.extend(Self::PREFIX); + key.encode_to(&mut raw_prefix); + raw_prefix + } + + /// Encode key2 into Vec + fn encode_key2(key: &R) -> Vec + where + Self::Key2: Borrow, + R: Codec + { + Encode::encode(&key) + } + + /// Derive the first part of the key + fn derive_key1(key1_data: Vec) -> Vec; + + /// Derive the remaining part of the key + fn derive_key2(key2_data: Vec) -> Vec; + + /// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`. + /// The first part is hashed and then concatenated with a hash of `k2`. + fn full_key(k1: &Q, k2: &R) -> Vec + where + Self::Key1: Borrow, + Self::Key2: Borrow, + Q: Codec, + R: Codec + { + let key1_data = Self::encode_key1(k1); + let key2_data = Self::encode_key2(k2); + let mut key = Self::derive_key1(key1_data); + key.extend(Self::derive_key2(key2_data)); + key + } +} diff --git a/srml/support/src/event.rs b/srml/support/src/event.rs index ddc6b7d64f01c7e4c386b39e438cfce5c81fd656..3dc132a490c3bdec90caa3ae37e0d3400c24f075 100644 --- a/srml/support/src/event.rs +++ b/srml/support/src/event.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -11,6 +11,9 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. +//! Macros that define an Event types. Events can be used to easily report changes or conditions +//! in your runtime to external entities like users, chain explorers, or dApps. + // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . @@ -23,9 +26,8 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// ```rust /// #[macro_use] /// extern crate srml_support; -/// extern crate parity_codec as codec; /// #[macro_use] -/// extern crate parity_codec_derive; +/// extern crate parity_codec as codec; /// #[macro_use] /// extern crate serde_derive; /// @@ -45,7 +47,7 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// extern crate srml_support; /// extern crate parity_codec as codec; /// #[macro_use] -/// extern crate parity_codec_derive; +/// extern crate parity_codec; /// #[macro_use] /// extern crate serde_derive; /// @@ -65,7 +67,7 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// /// mod event2 { /// // Event that uses the generic parameter `Balance`. -/// // If no name for the generic parameter is speciefied explicitly, +/// // If no name for the generic parameter is specified explicitly, /// // the name will be taken from the type name of the trait. /// decl_event!( /// pub enum Event where ::Balance { @@ -86,23 +88,49 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn /// ``` /// /// The syntax for generic events requires the `where`. +/// +/// # Generic Event with Instance Example: +/// +/// ```rust +/// #[macro_use] +/// extern crate srml_support; +/// extern crate parity_codec as codec; +/// #[macro_use] +/// extern crate parity_codec; +/// #[macro_use] +/// extern crate serde_derive; +/// +///# struct DefaultInstance; +///# trait Instance {} +///# impl Instance for DefaultInstance {} +/// trait Trait { +/// type Balance; +/// type Token; +/// } +/// +/// // For module with instances, DefaultInstance is optionnal +/// decl_event!( +/// pub enum Event where +/// ::Balance, +/// ::Token +/// { +/// Message(Balance, Token), +/// } +/// ); +///# fn main() {} +/// ``` #[macro_export] macro_rules! decl_event { ( $(#[$attr:meta])* - pub enum Event<$evt_generic_param:ident> where - $( $( $generic_rename:ident = )* <$generic:ident as $trait:path>::$trait_type:ident ),* - { - $( - $events:tt - )* - } + pub enum Event<$evt_generic_param:ident $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where + $( $tt:tt )* ) => { - __decl_generic_event!( + $crate::__decl_generic_event!( $( #[ $attr ] )*; $evt_generic_param; - $( $( $generic_rename = )* <$generic as $trait>::$trait_type ),*; - Events { $( $events )* }; + $($instance $( = $event_default_instance)? )?; + { $( $tt )* }; ); }; ( @@ -114,7 +142,7 @@ macro_rules! decl_event { } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug))] $(#[$attr])* pub enum Event { @@ -128,7 +156,7 @@ macro_rules! decl_event { impl Event { #[allow(dead_code)] pub fn metadata() -> &'static [ $crate::event::EventMetadata ] { - __events_to_metadata!(; $( $events )* ) + $crate::__events_to_metadata!(; $( $events )* ) } } } @@ -136,102 +164,142 @@ macro_rules! decl_event { #[macro_export] #[doc(hidden)] +// This parsing to retrieve last ident on unnamed generic could be improved. +// but user can still name it if the parsing fails. And improving parsing seems difficult. macro_rules! __decl_generic_event { ( $(#[$attr:meta])*; $event_generic_param:ident; - $generic_rename:ident = <$generic:ident as $trait:path>::$trait_type:ident - $(, $( $rest_gen_rename:ident = )* <$rest_gen:ident as $rest_trait:path>::$rest_trait_type:ident )*; - Events { $( $events:tt )* }; + $($instance:ident $( = $event_default_instance:path)? )?; + { $( $tt:tt )* }; ) => { - __decl_generic_event!( + $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; - $( $( $rest_gen_rename = )* <$rest_gen as $rest_trait>::$rest_trait_type ),*; - Events { $( $events )* }; - $generic_rename; - <$generic as $trait>::$trait_type; + $($instance $( = $event_default_instance)? )?; + { $( $tt )* }; + {}; ); }; - ( + // Parse named + (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; - $generic_rename:ident = <$generic:ident as $trait:path>::$trait_type:ident - $(, $( $rest_gen_rename:ident = )* <$rest_gen:ident as $rest_trait:path>::$rest_trait_type:ident )*; - Events { $( $events:tt )* }; - $( $parsed_generic_params:ident ),*; - $( <$parsed_generic:ident as $parsed_trait:path>::$parsed_trait_type:ident ),*; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_rename:ident = $generic_type:ty, $($rest:tt)* }; + {$( $parsed:tt)*}; ) => { - __decl_generic_event!( + $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; - $( $( $rest_gen_rename = )* <$rest_gen as $rest_trait>::$rest_trait_type ),*; - Events { $( $events )* }; - $( $parsed_generic_params ),*, $generic_rename; - $( <$parsed_generic as $parsed_trait>::$parsed_trait_type ),*, <$generic as $trait>::$trait_type; + $($instance $( = $event_default_instance)? )?; + { $($rest)* }; + { $($parsed)*, $generic_rename = $generic_type }; ); }; - ( + // Parse unnamed + (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; - <$generic:ident as $trait:path>::$trait_type:ident - $(, $( $rest_gen_rename:ident = )* <$rest_gen:ident as $rest_trait:path>::$rest_trait_type:ident )*; - Events { $( $events:tt )* }; + $($instance:ident $( = $event_default_instance:path)? )?; + { <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* }; + {$($parsed:tt)*}; ) => { - __decl_generic_event!( + $crate::__decl_generic_event!(@format_generic $( #[ $attr ] )*; $event_generic_param; - $( $( $rest_gen_rename = )* <$rest_gen as $rest_trait>::$rest_trait_type ),*; - Events { $( $events )* }; - $trait_type; - <$generic as $trait>::$trait_type; + $($instance $( = $event_default_instance)? )?; + { $($rest)* }; + { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type }; ); }; - ( + // Unnamed type can't be parsed + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_type:ty, $($rest:tt)* }; + {$($parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@cannot_parse $generic_type); + }; + // Finish formatting on an unnamed one + (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; - <$generic:ident as $trait:path>::$trait_type:ident - $(, $( $rest_gen_rename:ident = )* <$rest_gen:ident as $rest_trait:path>::$rest_trait_type:ident )*; - Events { $( $events:tt )* }; - $( $parsed_generic_params:ident ),*; - $( <$parsed_generic:ident as $parsed_trait:path>::$parsed_trait_type:ident ),*; + $($instance:ident $( = $event_default_instance:path)? )?; + { <$generic:ident as $trait:path>::$trait_type:ident { $( $events:tt )* } }; + {$( $parsed:tt)*}; ) => { - __decl_generic_event!( + $crate::__decl_generic_event!(@generate $( #[ $attr ] )*; $event_generic_param; - $( $( $rest_gen_rename = )* <$rest_gen as $rest_trait>::$rest_trait_type ),*; - Events { $( $events )* }; - $( $parsed_generic_params ),*, $trait_type; - $( <$parsed_generic as $parsed_trait>::$parsed_trait_type ),*, <$generic as $trait>::$trait_type; + $($instance $( = $event_default_instance)? )?; + { $($events)* }; + { $($parsed)*, $trait_type = <$generic as $trait>::$trait_type}; ); }; - ( + // Finish formatting on a named one + (@format_generic $(#[$attr:meta])*; $event_generic_param:ident; - ; - Events { $( $events:tt )* }; - $( $generic_param:ident ),*; - $( <$generic:ident as $trait:path>::$trait_type:ident ),*; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_rename:ident = $generic_type:ty { $( $events:tt )* } }; + {$( $parsed:tt)*}; ) => { - pub type Event<$event_generic_param> = RawEvent<$( <$generic as $trait>::$trait_type ),*>; + $crate::__decl_generic_event!(@generate + $(#[$attr])*; + $event_generic_param; + $($instance $( = $event_default_instance)? )?; + { $($events)* }; + { $($parsed)*, $generic_rename = $generic_type}; + ); + }; + // Final unnamed type can't be parsed + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_type:ty { $( $events:tt )* } }; + {$( $parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@cannot_parse $generic_type); + }; + (@generate + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { $( $events:tt )* }; + { ,$( $generic_param:ident = $generic_type:ty ),* }; + ) => { + /// [`RawEvent`] specialized for the configuration [`Trait`] + /// + /// [`RawEvent`]: enum.RawEvent.html + /// [`Trait`]: trait.Trait.html + pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >; // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug))] $(#[$attr])* - pub enum RawEvent<$( $generic_param ),*> { + pub enum RawEvent<$( $generic_param ),* $(, $instance)? > { + #[doc(hidden)] + $(PhantomData($crate::rstd::marker::PhantomData<$instance>),)? $( $events )* } - impl<$( $generic_param ),*> From> for () { - fn from(_: RawEvent<$( $generic_param ),*>) -> () { () } + impl<$( $generic_param ),* $(, $instance)? > From> for () { + fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () } } - impl<$( $generic_param ),*> RawEvent<$( $generic_param ),*> { + impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> { #[allow(dead_code)] pub fn metadata() -> &'static [$crate::event::EventMetadata] { - __events_to_metadata!(; $( $events )* ) + $crate::__events_to_metadata!(; $( $events )* ) } } + }; + (@cannot_parse $ty:ty) => { + compile_error!(concat!("The type `", stringify!($ty), "` can't be parsed as an unnamed one, please name it `Name = ", stringify!($ty), "`")); } } @@ -244,7 +312,7 @@ macro_rules! __events_to_metadata { $event:ident $( ( $( $param:path ),* ) )*, $( $rest:tt )* ) => { - __events_to_metadata!( + $crate::__events_to_metadata!( $( $metadata, )* $crate::event::EventMetadata { name: $crate::event::DecodeDifferent::Encode(stringify!($event)), @@ -265,53 +333,42 @@ macro_rules! __events_to_metadata { } } +/// Constructs an Event type for a runtime. This is usually called automatically by the +/// construct_runtime macro. See also __create_decl_macro. #[macro_export] macro_rules! impl_outer_event { + + // Macro transformations (to convert invocations with incomplete parameters to the canonical + // form) + ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident { - $( $rest:tt $( <$t:ident> )*, )* + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* } ) => { - impl_outer_event!( + $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; system; - Modules { $( $rest $(<$t>)*, )* }; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; ; ); }; ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest:tt $( <$t:ident> )*, )* - } - ) => { - impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest $(<$t>)*, )* }; - $module::Event<$runtime>,; - ); - }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest:tt $( <$t:ident> )*, )* + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* } ) => { - impl_outer_event!( + $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest $(<$t>)*, )* }; - $module::Event,; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; + ; ); }; ( @@ -320,18 +377,18 @@ macro_rules! impl_outer_event { $runtime:ident; $system:ident; Modules { - $module:ident, - $( $rest:tt $( <$t:ident> )*, )* + $module:ident, + $( $rest:tt $( <$t:ident $(, $rest_instance:path)? > )*, )* }; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { - impl_outer_event!( + $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest $(<$t>)*, )* }; - $( $module_name::Event $( <$generic_param> )*, )* $module::Event<$runtime>,; + Modules { $( $rest $(<$t $(, $rest_instance)? >)*, )* }; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event<$runtime $(, $instance)? >,; ); }; ( @@ -341,36 +398,39 @@ macro_rules! impl_outer_event { $system:ident; Modules { $module:ident, - $( $rest:tt, )* + $( $rest:tt )* }; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { - impl_outer_event!( + $crate::impl_outer_event!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest, )* }; - $( $module_name::Event $( <$generic_param> )*, )* $module::Event,; + Modules { $( $rest )* }; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )* $module::Event,; ); }; + + // The main macro expansion that actually renders the Event enum code. + ( $(#[$attr:meta])*; $name:ident; $runtime:ident; $system:ident; Modules {}; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, Encode, Decode)] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] #[cfg_attr(feature = "std", derive(Debug))] $(#[$attr])* #[allow(non_camel_case_types)] pub enum $name { system($system::Event), $( - $module_name( $module_name::Event $( <$generic_param> )* ), + $module_name( $module_name::Event $( <$generic_param $(, $generic_instance)? > )* ), )* } impl From<$system::Event> for $name { @@ -379,17 +439,17 @@ macro_rules! impl_outer_event { } } $( - impl From<$module_name::Event $( <$generic_param> )*> for $name { - fn from(x: $module_name::Event $( <$generic_param> )*) -> Self { + impl From<$module_name::Event $( <$generic_param $(, $generic_instance)? > )*> for $name { + fn from(x: $module_name::Event $( <$generic_param $(, $generic_instance)? > )*) -> Self { $name::$module_name(x) } } )* - __impl_outer_event_json_metadata!( + $crate::__impl_outer_event_json_metadata!( $runtime; $name; $system; - $( $module_name::Event $( <$generic_param> )*, )*; + $( $module_name::Event $( <$generic_param $(, $generic_instance)? > )*, )*; ); } } @@ -401,7 +461,7 @@ macro_rules! __impl_outer_event_json_metadata { $runtime:ident; $event_name:ident; $system:ident; - $( $module_name:ident::Event $( <$generic_param:ident> )*, )*; + $( $module_name:ident::Event $( <$generic_param:ident $(, $generic_instance:path)? > )*, )*; ) => { impl $runtime { #[allow(dead_code)] @@ -414,13 +474,25 @@ macro_rules! __impl_outer_event_json_metadata { , ( stringify!($module_name), $crate::event::FnEncode( - $module_name::Event $( ::<$generic_param> )* ::metadata + $module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata ) ) )* ]) } } + #[allow(dead_code)] + pub fn __module_events_system() -> &'static [$crate::event::EventMetadata] { + system::Event::metadata() + } + $( + #[allow(dead_code)] + $crate::paste::item!{ + pub fn [< __module_events_ $module_name >] () -> &'static [$crate::event::EventMetadata] { + $module_name::Event $( ::<$generic_param $(, $generic_instance)? > )* ::metadata() + } + } + )* } } } @@ -429,6 +501,8 @@ macro_rules! __impl_outer_event_json_metadata { #[allow(dead_code)] mod tests { use super::*; + use serde_derive::Serialize; + use parity_codec::{Encode, Decode}; mod system { pub trait Trait { diff --git a/srml/support/src/hashable.rs b/srml/support/src/hashable.rs index 23d0ee976a39680236961c6fa00685fa247e9cd7..9bb383b2a6b4ab68185729ea66bfbd558696cf2f 100644 --- a/srml/support/src/hashable.rs +++ b/srml/support/src/hashable.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ //! Hashable trait. -use codec::Codec; +use crate::codec::Codec; use runtime_io::{blake2_256, twox_128, twox_256}; pub trait Hashable: Sized { diff --git a/srml/support/src/inherent.rs b/srml/support/src/inherent.rs index 925ba91cec5322dfc90f89bff962ea97ba07fd0f..8a4fb669d15daafacb4cfaf6643374c70d2206cb 100644 --- a/srml/support/src/inherent.rs +++ b/srml/support/src/inherent.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,11 +15,11 @@ // along with Substrate. If not, see . #[doc(hidden)] -pub use rstd::{cmp, result::Result, vec::Vec}; +pub use crate::rstd::vec::Vec; #[doc(hidden)] -pub use runtime_primitives::{ - traits::{ProvideInherent, Block as BlockT}, CheckInherentError -}; +pub use crate::runtime_primitives::traits::{Block as BlockT, Extrinsic}; +#[doc(hidden)] +pub use inherents::{InherentData, ProvideInherent, CheckInherentsResult, IsFatalError}; /// Implement the outer inherent. @@ -30,54 +30,72 @@ pub use runtime_primitives::{ /// ```nocompile /// impl_outer_inherent! { /// pub struct InherentData where Block = Block, UncheckedExtrinsic = UncheckedExtrinsic { -/// timestamp: Timestamp export Error as TimestampInherentError, +/// timestamp: Timestamp, /// consensus: Consensus, +/// /// Aura module using the `Timestamp` call. +/// aura: Timestamp, /// } /// } /// ``` -/// -/// Additional parameters after `UncheckedExtrinsic` are `Error` and `Call`. #[macro_export] macro_rules! impl_outer_inherent { ( - for $runtime:ident, - Block = $block:ident, - InherentData = $inherent:ty + impl Inherents where Block = $block:ident, UncheckedExtrinsic = $uncheckedextrinsic:ident { - $( $module:ident: $module_ty:ident,)* + $( $module:ident: $call:ident, )* } ) => { - impl $runtime { - fn check_inherents( - block: $block, - data: $inherent - ) -> $crate::inherent::Result<(), $crate::inherent::CheckInherentError> { - use $crate::inherent::CheckInherentError; + trait InherentDataExt { + fn create_extrinsics(&self) -> + $crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic>; + fn check_extrinsics(&self, block: &$block) -> $crate::inherent::CheckInherentsResult; + } - let mut max_valid_after = None; - $( - let res = <$module_ty as $crate::inherent::ProvideInherent>::check_inherent( - &block, - data.$module, - &|xt| match xt.function { - Call::$module_ty(ref data) => Some(data), - _ => None, - }, - ); + impl InherentDataExt for $crate::inherent::InherentData { + fn create_extrinsics(&self) -> + $crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic> { + use $crate::inherent::ProvideInherent; + + let mut inherents = Vec::new(); - match res { - Err(CheckInherentError::ValidAtTimestamp(t)) => - max_valid_after = $crate::inherent::cmp::max(max_valid_after, Some(t)), - res => res? + $( + if let Some(inherent) = $module::create_inherent(self) { + inherents.push($uncheckedextrinsic::new_unsigned( + Call::$call(inherent)) + ); } )* - // once everything else has checked out, take the maximum of - // all things which are timestamp-restricted. - match max_valid_after { - Some(t) => Err(CheckInherentError::ValidAtTimestamp(t)), - None => Ok(()) + inherents + } + + fn check_extrinsics(&self, block: &$block) -> $crate::inherent::CheckInherentsResult { + use $crate::inherent::{ProvideInherent, IsFatalError}; + + let mut result = $crate::inherent::CheckInherentsResult::new(); + for xt in block.extrinsics() { + if $crate::inherent::Extrinsic::is_signed(xt).unwrap_or(false) { + break; + } + + $( + match xt.function { + Call::$call(ref call) => { + if let Err(e) = $module::check_inherent(call, self) { + result.put_error( + $module::INHERENT_IDENTIFIER, &e + ).expect("There is only one fatal error; qed"); + if e.is_fatal_error() { + return result; + } + } + } + _ => {}, + } + )* } + + result } } }; diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 2f4b9b3ecb020383efb14a74ac13fe43a8933449..89b14fe2fc355f1b6570017718d1a8207e8c783f 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,32 +19,22 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[cfg(feature = "std")] -extern crate serde; +#[macro_use] +extern crate bitmask; +#[cfg(feature = "std")] +pub use serde; #[doc(hidden)] -pub extern crate sr_std as rstd; -extern crate sr_io as runtime_io; +pub use sr_std as rstd; #[doc(hidden)] -pub extern crate sr_primitives as runtime_primitives; -extern crate srml_metadata; - -extern crate mashup; -#[macro_use] -extern crate srml_support_procedural; - -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; +pub use parity_codec as codec; #[cfg(feature = "std")] -#[macro_use] -extern crate serde_derive; -#[cfg(test)] -#[macro_use] -extern crate parity_codec_derive; - #[doc(hidden)] -pub extern crate parity_codec as codec; +pub use once_cell; +#[doc(hidden)] +pub use paste; +pub use sr_primitives as runtime_primitives; + pub use self::storage::generator::Storage as GenericStorage; #[macro_use] @@ -62,16 +52,33 @@ pub mod metadata; mod runtime; #[macro_use] pub mod inherent; +mod double_map; +pub mod traits; -pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap}; +pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap, EnumerableStorageMap}; pub use self::hashable::Hashable; pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; -pub use self::metadata::RuntimeMetadata; +pub use self::double_map::StorageDoubleMap; pub use runtime_io::print; #[doc(inline)] pub use srml_support_procedural::decl_storage; +pub mod lazy { + use spin::Once; + + pub struct Lazy(Once); + + impl Lazy { + pub const INIT: Self = Lazy(Once::INIT); + + #[inline(always)] + pub fn get(&'static self, builder: F) -> &T where F: FnOnce() -> T { + self.0.call_once(builder) + } + } +} + #[macro_export] macro_rules! fail { ( $y:expr ) => {{ @@ -83,7 +90,7 @@ macro_rules! fail { macro_rules! ensure { ( $x:expr, $y:expr ) => {{ if !$x { - fail!($y); + $crate::fail!($y); } }} } @@ -93,7 +100,7 @@ macro_rules! ensure { macro_rules! assert_noop { ( $x:expr , $y:expr ) => { let h = runtime_io::storage_root(); - assert_err!($x, $y); + $crate::assert_err!($x, $y); assert_eq!(h, runtime_io::storage_root()); } } @@ -123,9 +130,146 @@ macro_rules! assert_ok { #[cfg_attr(feature = "std", derive(Debug))] pub enum Void {} -#[doc(hidden)] -pub use mashup::*; - #[cfg(feature = "std")] #[doc(hidden)] pub use serde_derive::*; + +/// Programatically create derivations for tuples of up to 19 elements. You provide a second macro +/// which is called once per tuple size, along with a number of identifiers, one for each element +/// of the tuple. +#[macro_export] +macro_rules! for_each_tuple { + ($m:ident) => { + for_each_tuple! { @IMPL $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, } + }; + (@IMPL $m:ident !!) => { $m! { } }; + (@IMPL $m:ident !! $h:ident, $($t:ident,)*) => { + $m! { $h $($t)* } + for_each_tuple! { @IMPL $m !! $($t,)* } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use parity_codec::Codec; + use runtime_io::{with_externalities, Blake2Hasher}; + use runtime_primitives::BuildStorage; + + pub trait Trait { + type BlockNumber: Codec + Default; + type Origin; + } + + mod module { + #![allow(dead_code)] + + use super::Trait; + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { + + } + } + } + use self::module::Module; + + decl_storage! { + trait Store for Module as Example { + pub Data get(data) build(|_| vec![(15u32, 42u64)]): linked_map u32 => u64; + pub GenericData get(generic_data): linked_map T::BlockNumber => T::BlockNumber; + pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option; + } + } + + struct Test; + impl Trait for Test { + type BlockNumber = u32; + type Origin = u32; + } + + fn new_test_ext() -> runtime_io::TestExternalities { + GenesisConfig::::default().build_storage().unwrap().0.into() + } + + type Map = Data; + + #[test] + fn basic_insert_remove_should_work() { + with_externalities(&mut new_test_ext(), || { + // initialised during genesis + assert_eq!(Map::get(&15u32), 42u64); + + // get / insert / take + let key = 17u32; + assert_eq!(Map::get(&key), 0u64); + Map::insert(key, 4u64); + assert_eq!(Map::get(&key), 4u64); + assert_eq!(Map::take(&key), 4u64); + assert_eq!(Map::get(&key), 0u64); + + // mutate + Map::mutate(&key, |val| { + *val = 15; + }); + assert_eq!(Map::get(&key), 15u64); + + // remove + Map::remove(&key); + assert_eq!(Map::get(&key), 0u64); + }); + } + + #[test] + fn enumeration_and_head_should_work() { + with_externalities(&mut new_test_ext(), || { + assert_eq!(Map::head(), Some(15)); + assert_eq!(Map::enumerate().collect::>(), vec![(15, 42)]); + // insert / remove + let key = 17u32; + Map::insert(key, 4u64); + assert_eq!(Map::head(), Some(key)); + assert_eq!(Map::enumerate().collect::>(), vec![(key, 4), (15, 42)]); + assert_eq!(Map::take(&15), 42u64); + assert_eq!(Map::take(&key), 4u64); + assert_eq!(Map::head(), None); + assert_eq!(Map::enumerate().collect::>(), vec![]); + + // Add couple of more elements + Map::insert(key, 42u64); + assert_eq!(Map::head(), Some(key)); + assert_eq!(Map::enumerate().collect::>(), vec![(key, 42)]); + Map::insert(key + 1, 43u64); + assert_eq!(Map::head(), Some(key + 1)); + assert_eq!(Map::enumerate().collect::>(), vec![(key + 1, 43), (key, 42)]); + + // mutate + let key = key + 2; + Map::mutate(&key, |val| { + *val = 15; + }); + assert_eq!(Map::enumerate().collect::>(), vec![(key, 15), (key - 1, 43), (key - 2, 42)]); + assert_eq!(Map::head(), Some(key)); + Map::mutate(&key, |val| { + *val = 17; + }); + assert_eq!(Map::enumerate().collect::>(), vec![(key, 17), (key - 1, 43), (key - 2, 42)]); + + // remove first + Map::remove(&key); + assert_eq!(Map::head(), Some(key - 1)); + assert_eq!(Map::enumerate().collect::>(), vec![(key - 1, 43), (key - 2, 42)]); + + // remove last from the list + Map::remove(&(key - 2)); + assert_eq!(Map::head(), Some(key - 1)); + assert_eq!(Map::enumerate().collect::>(), vec![(key - 1, 43)]); + + // remove the last element + Map::remove(&(key - 1)); + assert_eq!(Map::head(), None); + assert_eq!(Map::enumerate().collect::>(), vec![]); + }); + } + +} diff --git a/srml/support/src/metadata.rs b/srml/support/src/metadata.rs index 0bd9bce2d94a774006f77201ba25d382d55cd35a..d61dbe43520ea84ee406f6e1ebb0dbf1eb61db7f 100644 --- a/srml/support/src/metadata.rs +++ b/srml/support/src/metadata.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,7 +15,9 @@ // along with Substrate. If not, see . pub use srml_metadata::{ - DecodeDifferent, FnEncode, RuntimeMetadata, RuntimeModuleMetadata + DecodeDifferent, FnEncode, RuntimeMetadata, + ModuleMetadata, RuntimeMetadataV1, + DefaultByteGetter, RuntimeMetadataPrefixed, }; /// Implements the metadata support for the given runtime and all its modules. @@ -30,15 +32,15 @@ pub use srml_metadata::{ macro_rules! impl_runtime_metadata { ( for $runtime:ident with modules - $( $rest:tt )* + $( $rest:tt )* ) => { impl $runtime { - pub fn metadata() -> $crate::metadata::RuntimeMetadata { - $crate::metadata::RuntimeMetadata { - outer_event: Self::outer_event_metadata(), - modules: __runtime_modules_to_metadata!($runtime;; $( $rest )*), - outer_dispatch: Self::outer_dispatch_metadata(), - } + pub fn metadata() -> $crate::metadata::RuntimeMetadataPrefixed { + $crate::metadata::RuntimeMetadata::V1 ( + $crate::metadata::RuntimeMetadataV1 { + modules: $crate::__runtime_modules_to_metadata!($runtime;; $( $rest )*), + } + ).into() } } } @@ -50,60 +52,193 @@ macro_rules! __runtime_modules_to_metadata { ( $runtime: ident; $( $metadata:expr ),*; - $mod:ident::$module:ident, + $mod:ident::$module:ident $( < $instance:ident > )? $(with)+ $($kw:ident)*, $( $rest:tt )* ) => { - __runtime_modules_to_metadata!( + $crate::__runtime_modules_to_metadata!( $runtime; - $( $metadata, )* $crate::metadata::RuntimeModuleMetadata { - prefix: $crate::metadata::DecodeDifferent::Encode(stringify!($mod)), - module: $crate::metadata::DecodeDifferent::Encode( - $crate::metadata::FnEncode($mod::$module::<$runtime>::metadata) - ), - storage: None, + $( $metadata, )* $crate::metadata::ModuleMetadata { + name: $crate::metadata::DecodeDifferent::Encode(stringify!($mod)), + prefix: $crate::__runtime_modules_to_metadata_calls_storagename!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + storage: $crate::__runtime_modules_to_metadata_calls_storage!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + calls: $crate::__runtime_modules_to_metadata_calls_call!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), + event: $crate::__runtime_modules_to_metadata_calls_event!($mod, $module $( <$instance> )?, $runtime, $(with $kw)*), }; $( $rest )* ) }; ( - $runtime: ident; + $runtime:ident; $( $metadata:expr ),*; - $mod:ident::$module:ident with Storage, - $( $rest:tt )* ) => { - __runtime_modules_to_metadata!( - $runtime; - $( $metadata, )* $crate::metadata::RuntimeModuleMetadata { - prefix: $crate::metadata::DecodeDifferent::Encode(stringify!($mod)), - module: $crate::metadata::DecodeDifferent::Encode( - $crate::metadata::FnEncode($mod::$module::<$runtime>::metadata) - ), - storage: Some($crate::metadata::DecodeDifferent::Encode( - $crate::metadata::FnEncode($mod::$module::<$runtime>::store_metadata) - )), - }; - $( $rest )* + $crate::metadata::DecodeDifferent::Encode(&[ $( $metadata ),* ]) + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata_calls_call { + // skip system + ( + system, + $skip_module: ident $( <$instance:ident> )?, + $skip_runtime: ident, + with Call + $(with $kws:ident)* + ) => { + None + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with Call + $(with $kws:ident)* + ) => { + Some($crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + $mod::$module::<$runtime $(, $mod::$instance )?>::call_functions + ) + )) + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with $_:ident + $(with $kws:ident)* + ) => { + $crate::__runtime_modules_to_metadata_calls_call!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + ) => { + None + }; +} + + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata_calls_event { + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with Event + $(with $kws:ident)* + ) => { + Some($crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + $crate::paste::expr!{ + $runtime:: [< __module_events_ $mod $(_ $instance)?>] + } + ) + )) + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with $_:ident + $(with $kws:ident)* + ) => { + $crate::__runtime_modules_to_metadata_calls_event!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + ) => { + None + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata_calls_storagename { + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with Storage + $(with $kws:ident)* + ) => { + $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + $mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_name + ) ) }; ( - $runtime:ident; - $( $metadata:expr ),*; + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with $_:ident + $(with $kws:ident)* ) => { - $crate::metadata::DecodeDifferent::Encode(&[ $( $metadata ),* ]) + $crate::__runtime_modules_to_metadata_calls_storagename!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + ) => { + $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode(|| "") + ) + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata_calls_storage { + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with Storage + $(with $kws:ident)* + ) => { + Some($crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + $mod::$module::<$runtime $(, $mod::$instance )?>::store_metadata_functions + ) + )) + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + with $_:ident + $(with $kws:ident)* + ) => { + $crate::__runtime_modules_to_metadata_calls_storage!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* ); + }; + ( + $mod: ident, + $module: ident $( <$instance:ident> )?, + $runtime: ident, + ) => { + None }; } + #[cfg(test)] // Do not complain about unused `dispatch` and `dispatch_aux`. #[allow(dead_code)] mod tests { use super::*; use srml_metadata::{ - EventMetadata, OuterEventMetadata, RuntimeModuleMetadata, CallMetadata, ModuleMetadata, + EventMetadata, StorageFunctionModifier, StorageFunctionType, FunctionMetadata, - StorageMetadata, StorageFunctionMetadata, OuterDispatchMetadata, OuterDispatchCall + StorageFunctionMetadata, + ModuleMetadata, RuntimeMetadataPrefixed }; - use codec::{Decode, Encode}; + use crate::codec::{Encode, Decode}; mod system { pub trait Trait { @@ -142,7 +277,7 @@ mod tests { } mod event_module { - use dispatch::Result; + use crate::dispatch::Result; pub trait Trait { type Origin; @@ -183,12 +318,12 @@ mod tests { pub struct Module for enum Call where origin: T::Origin {} } - decl_storage! { + crate::decl_storage! { trait Store for Module as TestStorage { StorageMethod : Option; } add_extra_genesis { - build(|_, _, _| {}); + build(|_, _, _| {}); } } } @@ -237,115 +372,89 @@ mod tests { impl_runtime_metadata!( for TestRuntime with modules - event_module::Module, - event_module2::Module with Storage, + system::Module with Event, + event_module::Module with Event Call, + event_module2::Module with Event Storage Call, ); - const EXPECTED_METADATA: RuntimeMetadata = RuntimeMetadata { - outer_event: OuterEventMetadata { - name: DecodeDifferent::Encode("TestEvent"), - events: DecodeDifferent::Encode(&[ - ( - "system", - FnEncode(|| &[ + const EXPECTED_METADATA: RuntimeMetadata = RuntimeMetadata::V1( + RuntimeMetadataV1 { + modules: DecodeDifferent::Encode(&[ + ModuleMetadata { + name: DecodeDifferent::Encode("system"), + prefix: DecodeDifferent::Encode(FnEncode(||"")), + storage: None, + calls: None, + event: Some(DecodeDifferent::Encode( + FnEncode(||&[ EventMetadata { name: DecodeDifferent::Encode("SystemEvent"), arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]) + } + ]) + )), + }, + ModuleMetadata { + name: DecodeDifferent::Encode("event_module"), + prefix: DecodeDifferent::Encode(FnEncode(||"")), + storage: None, + calls: Some( + DecodeDifferent::Encode(FnEncode(||&[ + FunctionMetadata { + name: DecodeDifferent::Encode("aux_0"), + arguments: DecodeDifferent::Encode(&[]), documentation: DecodeDifferent::Encode(&[]), } - ]) - ), - ( - "event_module", - FnEncode(|| &[ + ]))), + event: Some(DecodeDifferent::Encode( + FnEncode(||&[ EventMetadata { name: DecodeDifferent::Encode("TestEvent"), arguments: DecodeDifferent::Encode(&["Balance"]), documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."]) } - ]) - ), - ( - "event_module2", - FnEncode(|| &[ + ]) + )), + }, + ModuleMetadata { + name: DecodeDifferent::Encode("event_module2"), + prefix: DecodeDifferent::Encode(FnEncode(||"TestStorage")), + storage: Some(DecodeDifferent::Encode( + FnEncode(||&[ + StorageFunctionMetadata { + name: DecodeDifferent::Encode("StorageMethod"), + modifier: StorageFunctionModifier::Optional, + ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter( + &event_module2::__GetByteStructStorageMethod(::std::marker::PhantomData::) + ) + ), + documentation: DecodeDifferent::Encode(&[]), + } + ]) + )), + calls: Some(DecodeDifferent::Encode(FnEncode(||&[ ]))), + event: Some(DecodeDifferent::Encode( + FnEncode(||&[ EventMetadata { name: DecodeDifferent::Encode("TestEvent"), arguments: DecodeDifferent::Encode(&["Balance"]), documentation: DecodeDifferent::Encode(&[]) } - ]) - ) - ]), - }, - modules: DecodeDifferent::Encode(&[ - RuntimeModuleMetadata { - prefix: DecodeDifferent::Encode("event_module"), - module: DecodeDifferent::Encode(FnEncode(|| - ModuleMetadata { - name: DecodeDifferent::Encode("Module"), - call: CallMetadata { - name: DecodeDifferent::Encode("Call"), - functions: DecodeDifferent::Encode(&[ - FunctionMetadata { - id: 0, - name: DecodeDifferent::Encode("aux_0"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]), - } - ]) - } - } + ]) )), - storage: None, }, - RuntimeModuleMetadata { - prefix: DecodeDifferent::Encode("event_module2"), - module: DecodeDifferent::Encode(FnEncode(|| - ModuleMetadata { - name: DecodeDifferent::Encode("Module"), - call: CallMetadata { - name: DecodeDifferent::Encode("Call"), - functions: DecodeDifferent::Encode(&[]) - } - } - )), - storage: Some(DecodeDifferent::Encode(FnEncode(|| - StorageMetadata { - prefix: DecodeDifferent::Encode("TestStorage"), - functions: DecodeDifferent::Encode(&[ - StorageFunctionMetadata { - name: DecodeDifferent::Encode("StorageMethod"), - modifier: StorageFunctionModifier::Optional, - ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), - documentation: DecodeDifferent::Encode(&[]), - } - ]) - } - ))), - } - ]), - outer_dispatch: OuterDispatchMetadata { - name: DecodeDifferent::Encode("Call"), - calls: DecodeDifferent::Encode(&[ - OuterDispatchCall { - name: DecodeDifferent::Encode("EventModule"), - prefix: DecodeDifferent::Encode("event_module"), - index: 0, - }, - OuterDispatchCall { - name: DecodeDifferent::Encode("EventModule2"), - prefix: DecodeDifferent::Encode("event_module2"), - index: 1, - } - ]) - } - }; + ])} + ); #[test] fn runtime_metadata() { let metadata_encoded = TestRuntime::metadata().encode(); - let metadata_decoded = RuntimeMetadata::decode(&mut &metadata_encoded[..]); + let metadata_decoded = RuntimeMetadataPrefixed::decode(&mut &metadata_encoded[..]); + let expected_metadata: RuntimeMetadataPrefixed = EXPECTED_METADATA.into(); - assert_eq!(EXPECTED_METADATA, metadata_decoded.unwrap()); + assert_eq!(expected_metadata, metadata_decoded.unwrap()); } } diff --git a/srml/support/src/origin.rs b/srml/support/src/origin.rs index 5cc54794dbf1f63682602f0e612d330f9d6780de..2d97f218e095819fb41f8868a7b17929d7a4bcd2 100644 --- a/srml/support/src/origin.rs +++ b/srml/support/src/origin.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,113 +14,77 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +//! Macros that define an Origin type. Every function call to your runtime has an origin which +//! specifies where the extrinsic was generated from. + +/// Constructs an Origin type for a runtime. This is usually called automatically by the +/// construct_runtime macro. See also __create_decl_macro. #[macro_export] macro_rules! impl_outer_origin { + + // Macro transformations (to convert invocations with incomplete parameters to the canonical + // form) + ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident { - $( $module:ident $( <$generic:ident> )* ),* $(,)* + $( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)? } ) => { - impl_outer_origin! { + $crate::impl_outer_origin! { $(#[$attr])* pub enum $name for $runtime where system = system { - $( $module $( <$generic> )*, )* + $( $module $( <$generic $(, $instance )? > )?, )* } } }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident {} - ) => { - impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { }; - ; - ); - }; ( $(#[$attr:meta])* pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* + $( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)? } ) => { - impl_outer_origin!( + $crate::impl_outer_origin!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $module; - ); - }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )* ),* $(,)* - } - ) => { - impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $module<$runtime>; - ); - }; - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )*, )* - }; - $( $parsed_module:ident $( <$generic_param:ident> )* ),*; - ) => { - impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $( $parsed_module $( <$generic_param> )* ),*, $module; + Modules { $( $module $( <$generic $(, $instance )? > )*, )* }; ); }; + + // Replace generic param with runtime + ( $(#[$attr:meta])*; $name:ident; $runtime:ident; $system:ident; Modules { - $module:ident, - $( $rest_module:ident $( <$rest_generic:ident> )*, )* + $module:ident $( )?, + $( $rest_module:tt )* }; - $( $parsed_module:ident $( <$generic_param:ident> )* ),*; + $( $parsed:tt )* ) => { - impl_outer_origin!( + $crate::impl_outer_origin!( $( #[$attr] )*; $name; $runtime; $system; - Modules { $( $rest_module $( <$rest_generic> )*, )* }; - $( $parsed_module $( <$generic_param> )* ),*, $module<$runtime>; + Modules { $( $rest_module )* }; + $( $parsed )* $module $( <$runtime $(, $instance )? > )?, ); }; + + // The main macro expansion that actually renders the Origin enum code. + ( $(#[$attr:meta])*; $name:ident; $runtime:ident; $system:ident; - Modules {}; - $( $module:ident $( <$generic_param:ident> )* ),*; + Modules { }; + $( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)* ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq)] @@ -130,7 +94,7 @@ macro_rules! impl_outer_origin { pub enum $name { system($system::Origin<$runtime>), $( - $module($module::Origin $( <$generic_param> )* ), + $module($module::Origin $( <$generic_param $(, $generic_instance )? > )* ), )* #[allow(dead_code)] Void($crate::Void) @@ -163,13 +127,13 @@ macro_rules! impl_outer_origin { } } $( - impl From<$module::Origin $( <$generic_param> )*> for $name { - fn from(x: $module::Origin $( <$generic_param> )*) -> Self { + impl From<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> for $name { + fn from(x: $module::Origin $( <$generic_param $(, $generic_instance )? > )*) -> Self { $name::$module(x) } } - impl Into )*>> for $name { - fn into(self) -> Option<$module::Origin $( <$generic_param> )*> { + impl Into )*>> for $name { + fn into(self) -> Option<$module::Origin $( <$generic_param $(, $generic_instance )? > )*> { if let $name::$module(l) = self { Some(l) } else { diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index 5fcd8c565b261fd1931c248e364370272c880140..c575383b264e328839e00bdf68b58d6de9f9fcdd 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,28 +14,44 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +//! Macros to define a runtime. A runtime is basically all your logic running in Substrate, +//! consisting of selected SRML modules and maybe some of your own modules. +//! A lot of supporting logic is automatically generated for a runtime, +//! mostly for to combine data types and metadata of the included modules. + /// Construct a runtime, with the given name and the given modules. /// +/// The parameters here are specific types for Block, NodeBlock and InherentData +/// (TODO: describe the difference between Block and NodeBlock) +/// and the modules that are used by the runtime. +/// /// # Example: /// /// ```nocompile /// construct_runtime!( /// pub enum Runtime with Log(interalIdent: DigestItem) where /// Block = Block, -/// NodeBlock = runtime::Block +/// NodeBlock = runtime::Block, +/// UncheckedExtrinsic = UncheckedExtrinsic /// { /// System: system, /// Test: test::{default, Log(Test)}, /// Test2: test_with_long_module::{Module}, +/// +/// // Module with instances +/// Test3_Instance1: test3::::{Module, Call, Storage, Event, Config, Origin}, +/// Test3_DefaultInstance: test3::{Module, Call, Storage, Event, Config, Origin}, /// } /// ) /// ``` /// -/// The module `System: system` will expand to `System: system::{Module, Call, Storage, Event, Config}`. +/// The module `System: system` will expand to `System: system::{Module, Call, Storage, Event, Config}`. /// The identifier `System` is the name of the module and the lower case identifier `system` is the -/// name of the rust module for this module. +/// name of the Rust module/crate for this Substrate module. +/// /// The module `Test: test::{default, Log(Test)}` will expand to -/// `Test: test::{Module, Call, Storage, Event, Config, Log(Test)}`. +/// `Test: test::{Module, Call, Storage, Event, Config, Log(Test)}`. +/// /// The module `Test2: test_with_long_module::{Module}` will expand to /// `Test2: test_with_long_module::{Module}`. /// @@ -43,172 +59,89 @@ /// - `Module` /// - `Call` /// - `Storage` -/// - `Event` or `Event` (if the event is generic) -/// - `Origin` or `Origin` (if the origin is generic) -/// - `Config` or `Config` (if the config is generic) +/// - `Event` or `Event` (if the event is generic) or `Event` (if also over instance) +/// - `Origin` or `Origin` (if the origin is generic) or `Origin` (if also over instance) +/// - `Config` or `Config` (if the config is generic) or `Config` (if also over instance) /// - `Log( $(IDENT),* )` +/// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter +/// is for modules that use a `Call` from a different module as +/// inherent. +/// +/// # Note +/// +/// The population of the genesis storage depends on the order of modules. So, if one of your +/// modules depends on another module. The dependent module need to come before the module depending on it. #[macro_export] macro_rules! construct_runtime { + + // Macro transformations (to convert invocations with incomplete parameters to the canonical + // form) + ( pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>) where Block = $block:ident, NodeBlock = $node_block:ty, - InherentData = $inherent:ty + UncheckedExtrinsic = $uncheckedextrinsic:ident { $( $rest:tt )* } ) => { construct_runtime!( - $runtime; - $block; - $node_block; - $inherent; - $log_internal < $( $log_genarg ),* >; - ; + { + $runtime; + $block; + $node_block; + $uncheckedextrinsic; + $log_internal < $( $log_genarg ),* >; + }; + {}; $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $inherent:ty; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident, - $( - $rest_name:ident: $rest_module:ident $( - ::{ - $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* - ),* - } - )*, - )* + $( $rest:tt )* ) => { construct_runtime!( - $runtime; - $block; - $node_block; - $inherent; - $log_internal < $( $log_genarg ),* >; - $( - $expanded_name: $expanded_module::{ - $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* - ),* - }, - )* $name: $module::{Module, Call, Storage, Event, Config}; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + { $( $preset )* }; + { $( $expanded )* $name: $module::{Module, Call, Storage, Event, Config}, }; + $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $inherent:ty; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident::{ default, $( $modules:ident - $( <$modules_generic:ident> )* + $( <$modules_generic:ident $(, $modules_instance:ident)?> )* $( ( $( $modules_args:ident ),* ) )* ),* }, - $( - $rest_name:ident: $rest_module:ident $( - ::{ - $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* - ),* - } - )*, - )* + $( $rest:tt )* ) => { construct_runtime!( - $runtime; - $block; - $node_block; - $inherent; - $log_internal < $( $log_genarg ),* >; - $( - $expanded_name: $expanded_module::{ + { $( $preset )* }; + { + $( $expanded )* + $name: $module::{ + Module, Call, Storage, Event, Config, $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* + $modules $( <$modules_generic $(, $modules_instance)?> )* + $( ( $( $modules_args ),* ) )* ),* }, - )* - $name: $module::{ - Module, Call, Storage, Event, Config, - $( - $modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )* - ),* }; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + $( $rest )* ); }; ( - $runtime:ident; - $block:ident; - $node_block:ty; - $inherent:ty; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $expanded_name:ident: $expanded_module:ident::{ - $( - $expanded_modules:ident - $( <$expanded_modules_generic:ident> )* - $( ( $( $expanded_modules_args:ident ),* ) )* - ),* - } - ),*; + { $( $preset:tt )* }; + { $( $expanded:tt )* }; $name:ident: $module:ident::{ $( $modules:ident @@ -216,73 +149,71 @@ macro_rules! construct_runtime { $( ( $( $modules_args:ident ),* ) )* ),* }, - $( - $rest_name:ident: $rest_module:ident $( - ::{ + $( $rest:tt )* + ) => { + construct_runtime!( + { $( $preset )* }; + { + $( $expanded )* + $name: $module::{ $( - $rest_modules:ident - $( <$rest_modules_generic:ident> )* - $( ( $( $rest_modules_args:ident ),* ) )* + $modules $( <$modules_generic> )* + $( ( $( $modules_args ),* ) )* ),* - } - )*, - )* + }, + }; + $( $rest )* + ); + }; + ( // Instance module: we indicate the generic instance `I` with the full instance path + { $( $preset:tt )* }; + { $( $expanded:tt )* }; + $name:ident: $module:ident ::< $module_instance:ident >::{ + $( + $modules:ident + $( <$modules_generic:ident $(, $modules_instance:ident )?> )* + $( ( $( $modules_args:ident ),* ) )* + ),* + }, + $( $rest:tt )* ) => { construct_runtime!( - $runtime; - $block; - $node_block; - $inherent; - $log_internal < $( $log_genarg ),* >; - $( - $expanded_name: $expanded_module::{ + { $( $preset )* }; + { + $( $expanded )* + $name: $module::<$module_instance>::{ $( - $expanded_modules - $( <$expanded_modules_generic> )* - $( ( $( $expanded_modules_args ),* ) )* + $modules $( <$modules_generic $(, $modules_instance=$module::$module_instance)?> )* + $( ( $( $modules_args ),* ) )* ),* }, - )* - $name: $module::{ - $( - $modules $( <$modules_generic> )* $( ( $( $modules_args ),* ) )* - ),* }; - $( - $rest_name: $rest_module $( - ::{ - $( - $rest_modules - $( <$rest_modules_generic> )* - $( ( $( $rest_modules_args ),* ) )* - ),* - } - )*, - )* + $( $rest )* ); }; + + // The main macro expansion that actually renders the Runtime code. + ( - $runtime:ident; - $block:ident; - $node_block:ty; - $inherent:ty; - $log_internal:ident <$( $log_genarg:ty ),+>; - $( - $name:ident: $module:ident::{ - $( - $modules:ident - $( <$modules_generic:ident> )* - $( ( $( $modules_args:ident ),* ) )* - ),* - } - ),*; - ) => { - mashup! { + { + $runtime:ident; + $block:ident; + $node_block:ty; + $uncheckedextrinsic:ident; + $log_internal:ident <$( $log_genarg:ty ),+>; + }; + { $( - substrate_generate_ident_name["config-ident" $name] = $name Config; + $name:ident: $module:ident :: $( < $module_instance:ident >:: )? { + $( + $modules:ident + $( <$modules_generic:ident $(, I=$modules_instance:path)?> )* + $( ( $( $modules_args:ident ),* ) )* + ),* + }, )* - } - + }; + ) => { #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] pub struct $runtime; @@ -292,68 +223,77 @@ macro_rules! construct_runtime { impl $crate::runtime_primitives::traits::GetRuntimeBlockType for $runtime { type RuntimeBlock = $block; } - __decl_outer_event!( + $crate::__decl_instance_import!( + $( $( $module < $module_instance > )? )* + ); + $crate::__decl_outer_event!( $runtime; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } ),* ); - __decl_outer_origin!( + $crate::__decl_outer_origin!( $runtime; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } ),* ); - __decl_all_modules!( + $crate::__decl_all_modules!( $runtime; ; - ; + {}; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { $( $modules ),* }, + )* ); - __decl_outer_dispatch!( + $crate::__decl_outer_dispatch!( $runtime; ; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module::{ $( $modules ),* } ),*; ); - __decl_runtime_metadata!( + $crate::__decl_runtime_metadata!( $runtime; - ; - ; + {}; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { $( $modules )* } + )* ); - __decl_outer_log!( + $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - ; + {}; $( - $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { $( $modules $( ( $( $modules_args )* ) )* )* } + )* ); - __decl_outer_config!( + $crate::__decl_outer_config!( $runtime; - ; + {}; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - ),*; + $name: $module:: $( < $module_instance >:: )? { + $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* + }, + )* ); - __decl_outer_inherent!( + $crate::__decl_outer_inherent!( $runtime; $block; - $inherent; + $uncheckedextrinsic; ; $( - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } ),*; ); } } +/// A macro that generates a "__decl" private macro that transforms parts of the runtime definition +/// to feed them into a public "impl" macro which accepts the format +/// "pub enum $name for $runtime where system = $system". +/// +/// Used to define Event and Origin associated types. #[macro_export] #[doc(hidden)] macro_rules! __create_decl_macro { @@ -367,145 +307,135 @@ macro_rules! __create_decl_macro { macro_rules! $macro_name { ( $runtime:ident; - System: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })* + $d( $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { + $d( $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> ),* ),* + }),* ) => { - $macro_name!( + $d crate::$macro_name!(@inner $runtime; - $module; ; + {}; $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + $name: $module:: $d( < $module_instance >:: )? { + $d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),* + }, + )* ); }; - ( + (@inner $runtime:ident; ; // there can not be multiple `System`s - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; + { $d( $parsed:tt )* }; System: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $modules:ident $d( <$modules_generic:ident> )* ),* + }, + $d( $rest:tt )* ) => { - $macro_name!( + $d crate::$macro_name!(@inner $runtime; $module; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - )*; + { $d( $parsed )* }; + $d( $rest )* ); }; - ( + (@inner $runtime:ident; - $name:ident: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })* + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: < $module_instance:ident >:: { + $macro_enum_name <$event_generic:ident, $event_instance:path> $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { - $macro_name!( + $d crate::$macro_name!(@inner $runtime; - ; - ; - $name: $module::{ $d( $modules $d( <$modules_generic> )* ),* } - $d( - , $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - )*; + $d( $system )?; + { + $d( $parsed )* + $module $module_instance <$event_generic, $event_instance>, + }; + $d( $rest )* ); }; - ( + (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{ - $macro_enum_name $d( <$event_gen:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: < $module_instance:ident >:: { + $macro_enum_name $d( <$event_generic:ident> )* $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { - $macro_name!( + compile_error!{concat!{ + "Module `", stringify!{$name}, "` must have `", stringify!{$macro_enum_name}, "`", + " but has `", stringify!{$macro_enum_name} $d(, "<", stringify!{$event_generic}, ">")*, "`", + ": Instantiated modules must have ", stringify!{$macro_enum_name}, + " generic over instance to be able to convert to outer ", stringify!{$macro_enum_name} + }} + }; + (@inner + $runtime:ident; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: { + $macro_enum_name $d( <$event_generic:ident $d(, $event_instance:path)?> )* $d(, $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* )* + }, + $d( $rest:tt )* + ) => { + $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( - $parsed_modules $d( <$parsed_generic> )* , )* - $module $d( <$event_gen> )*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + $d( $system )?; + { + $d( $parsed )* + $module $d( <$event_generic $d(, $event_instance)?> )*, + }; + $d( $rest )* ); }; - ( + (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{ - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - } - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { + $ingore:ident $d( <$ignor:ident $d(, $ignore_instance:path)?> )* $d(, $modules:ident $d( <$modules_generic:ident $d(, $modules_instance:path)?> )* )* + }, + $d( $rest:tt )* ) => { - $macro_name!( + $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $name: $module::{ $d( $modules $d( <$modules_generic> )* ),* } - $d( - , $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - )*; + $d( $system )?; + { $d( $parsed )* }; + $name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic $d(, $modules_instance)?> )* ),* }, + $d( $rest )* ); }; - ( + (@inner $runtime:ident; - $d( $system:ident )*; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - $name:ident: $module:ident::{} - $d(, $rest_name:ident : $rest_module:ident::{ - $d( $rest_modules:ident $d( <$rest_modules_generic:ident> )* ),* - })*; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident: $module:ident:: $d( < $module_instance:ident >:: )? {}, + $d( $rest:tt )* ) => { - $macro_name!( + $d crate::$macro_name!(@inner $runtime; - $d( $system )*; - $d( $parsed_modules $d( <$parsed_generic> )* ),*; - $d( - $rest_name: $rest_module::{ - $d( $rest_modules $d( <$rest_modules_generic> )* ),* - } - ),*; + $d( $system )?; + { $d( $parsed )* }; + $d( $rest )* ); }; - ( + (@inner $runtime:ident; - $d( $system:ident )+; - $d( $parsed_modules:ident $d( <$parsed_generic:ident> )* ),*; - ; + $system:ident; + { $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident $d(, $parsed_instance_full_path:path)?> )* ,)* }; ) => { - $macro_outer_name! { - pub enum $macro_enum_name for $runtime where system = $d( $system )* { - $d( - $parsed_modules $d( <$parsed_generic> )*, - )* + $d crate::paste::item! { + $d crate::$macro_outer_name! { + + pub enum $macro_enum_name for $runtime where system = $system { + $d( + [< $parsed_modules $d(_ $instance )? >] $d( <$parsed_generic $d(, $parsed_instance_full_path)?> )*, + )* + } } } } @@ -516,110 +446,85 @@ macro_rules! __create_decl_macro { __create_decl_macro!(__decl_outer_event, impl_outer_event, Event, $); __create_decl_macro!(__decl_outer_origin, impl_outer_origin, Origin, $); +/// A macro that defines all modules as an associated types of the Runtime type. #[macro_export] #[doc(hidden)] macro_rules! __decl_all_modules { ( $runtime:ident; ; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - System: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + System: $module:ident::{ Module $(, $modules:ident )* }, + $( $rest:tt )* ) => { - __decl_all_modules!( + $crate::__decl_all_modules!( $runtime; $module; - $( $parsed_modules :: $parsed_name ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, + $( $rest:tt )* ) => { - __decl_all_modules!( + $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + $( $system )?; + { + $( $parsed )* + $module::$name $(<$module_instance>)?, + }; + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $ingore:ident $(, $modules:ident )* }, + $( $rest:tt )* ) => { - __decl_all_modules!( + $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; + $( $system )?; + { $( $parsed )* }; + $name: $module::{ $( $modules ),* }, + $( $rest )* ); }; ( $runtime:ident; - $( $system:ident )*; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $system:ident )?; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, + $( $rest:tt )* ) => { - __decl_all_modules!( + $crate::__decl_all_modules!( $runtime; - $( $system )*; - $( $parsed_modules :: $parsed_name ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + $( $system )?; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; $system:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - ; + { $( $parsed_module:ident :: $parsed_name:ident $(<$instance:ident>)? ,)*}; ) => { pub type System = system::Module<$runtime>; $( - pub type $parsed_name = $parsed_modules::Module<$runtime>; + pub type $parsed_name = $parsed_module::Module<$runtime $(, $parsed_module::$instance )?>; )* type AllModules = ( $( $parsed_name, )* ); } } +/// A macro that defines the Call enum to represent calls to functions in the modules included +/// in the runtime (by wrapping the values of all FooModule::Call enums). #[macro_export] #[doc(hidden)] macro_rules! __decl_outer_dispatch { @@ -633,7 +538,7 @@ macro_rules! __decl_outer_dispatch { $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* })*; ) => { - __decl_outer_dispatch!( + $crate::__decl_outer_dispatch!( $runtime; $( $parsed_modules :: $parsed_name ),*; $( @@ -653,7 +558,7 @@ macro_rules! __decl_outer_dispatch { $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* })*; ) => { - __decl_outer_dispatch!( + $crate::__decl_outer_dispatch!( $runtime; $( $parsed_modules :: $parsed_name, )* $module::$name; $( @@ -673,7 +578,7 @@ macro_rules! __decl_outer_dispatch { $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* })*; ) => { - __decl_outer_dispatch!( + $crate::__decl_outer_dispatch!( $runtime; $( $parsed_modules :: $parsed_name ),*; $name: $module::{ $( $modules $( <$modules_generic> )* ),* } @@ -692,7 +597,7 @@ macro_rules! __decl_outer_dispatch { $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* })*; ) => { - __decl_outer_dispatch!( + $crate::__decl_outer_dispatch!( $runtime; $( $parsed_modules :: $parsed_name ),*; $( @@ -707,7 +612,7 @@ macro_rules! __decl_outer_dispatch { $( $parsed_modules:ident :: $parsed_name:ident ),*; ; ) => { - impl_outer_dispatch!( + $crate::impl_outer_dispatch!( pub enum Call for $runtime where origin: Origin { $( $parsed_modules::$parsed_name, )* } @@ -715,349 +620,201 @@ macro_rules! __decl_outer_dispatch { }; } +/// A private macro that generates metadata() method for the runtime. See impl_runtime_metadata macro. #[macro_export] #[doc(hidden)] macro_rules! __decl_runtime_metadata { + // leading is Module : parse ( $runtime:ident; - ; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* + { $( $parsed:tt )* }; + $( { leading_module: $( $leading_module:ident )* } )? + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + Module $( $modules:ident )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $rest:tt )* ) => { - __decl_runtime_metadata!( + $crate::__decl_runtime_metadata!( $runtime; - $module { Module, }; - $( $parsed_modules { Module $( with $parsed_storage )* } ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; - ); - }; - ( - $runtime:ident; - $current_module:ident { , Storage }; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{ - Module $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - __decl_runtime_metadata!( - $runtime; - ; - $( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module with Storage }; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - ; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{ - Storage $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - __decl_runtime_metadata!( - $runtime; - $module { , Storage }; - $( $parsed_modules { Module $( with $parsed_storage )* } ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; - ); - }; - ( - $runtime:ident; - $current_module:ident { Module, }; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{ - Storage $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - __decl_runtime_metadata!( - $runtime; - ; - $( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module with Storage }; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { + $( $parsed )* + $module $( < $module_instance > )? { $( $( $leading_module )* )? $( $modules )* } + }; + $( $rest )* ); }; + // leading isn't Module : put it in leadings ( $runtime:ident; - $( $current_module:ident { $( $current_module_storage:tt )* } )*; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* + { $( $parsed:tt )* }; + $( { leading_module: $( $leading_module:ident )* } )? + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + $other_module:ident $( $modules:ident )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - __decl_runtime_metadata!( - $runtime; - $( $current_module { $( $current_module_storage )* } )*; - $( $parsed_modules { Module $( with $parsed_storage )* } ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; - ); - }; - ( - $runtime:ident; - $current_module:ident { Module, }; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + $( $rest:tt )* ) => { - __decl_runtime_metadata!( + $crate::__decl_runtime_metadata!( $runtime; - ; - $( $parsed_modules { Module $( with $parsed_storage )* }, )* $module { Module }; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + { leading_module: $( $( $leading_module )* )? $other_module } + $name: $module:: $( < $module_instance >:: )? { + $( $modules )* + } + $( $rest )* ); }; + // does not contain Module : skip ( $runtime:ident; - $( $current_module:ident { $( $ignore:tt )* } )*; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $( { leading_module: $( $leading_module:ident )* } )? + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {} + $( $rest:tt )* ) => { - __decl_runtime_metadata!( + $crate::__decl_runtime_metadata!( $runtime; - ; - $( $parsed_modules { Module $( with $parsed_storage )* } ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; + // end of decl ( $runtime:ident; - ; - $( $parsed_modules:ident { Module $( with $parsed_storage:ident )* } ),*; - ; + { $( $parsed_modules:ident $( < $module_instance:ident > )? { $( $withs:ident )* } )* }; ) => { - impl_runtime_metadata!( + $crate::impl_runtime_metadata!( for $runtime with modules - $( $parsed_modules::Module $(with $parsed_storage)*, )* + $( $parsed_modules::Module $( < $module_instance > )? with $( $withs )* , )* ); } + } +/// A private macro that generates Log enum for the runtime. See impl_outer_log macro. #[macro_export] #[doc(hidden)] macro_rules! __decl_outer_log { ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{ - Log ( $( $args:ident ),* ) $(, $modules:ident $( ( $( $modules_args:ident )* ) )* )* + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + Log ( $( $args:ident )* ) $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + $( $rest:tt )* ) => { - __decl_outer_log!( + $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ), )* $module ( $( $args ),* ); - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - ),*; + { $( $parsed )* $module $(<$module_instance>)? ( $( $args )* )}; + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{ - $ignore:ident $( ( $( $args_ignore:ident ),* ) )* - $(, $modules:ident $( ( $( $modules_args:ident ),* ) )* )* + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + $ignore:ident $( ( $( $args_ignore:ident )* ) )* + $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + $( $rest:tt )* ) => { - __decl_outer_log!( + $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ) ),*; - $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - )*; + { $( $parsed )* }; + $name: $module:: $(<$module_instance>::)? { $( $modules $( ( $( $modules_args )* ) )* )* } + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_modules_args:ident )* ) )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? {} + $( $rest:tt )* ) => { - __decl_outer_log!( + $crate::__decl_outer_log!( $runtime; $log_internal < $( $log_genarg ),* >; - $( $parsed_modules ( $( $parsed_args ),* ) ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_modules_args ),* ) )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; $log_internal:ident <$( $log_genarg:ty ),+>; - $( $parsed_modules:ident( $( $parsed_args:ident ),* ) ),*; - ; + { $( + $parsed_modules:ident $(< $parsed_instance:ident >)? ( $( $parsed_args:ident )* ) + )* }; ) => { - impl_outer_log!( - pub enum Log($log_internal: DigestItem<$( $log_genarg ),*>) for $runtime { - $( $parsed_modules ( $( $parsed_args ),* ) ),* - } - ); + $crate::paste::item! { + $crate::runtime_primitives::impl_outer_log!( + pub enum Log($log_internal: DigestItem<$( $log_genarg ),*>) for $runtime { + $( [< $parsed_modules $(_ $parsed_instance)? >] $(< $parsed_modules::$parsed_instance >)? ( $( $parsed_args ),* ) ),* + } + ); + } }; } +/// A private macro that generates GenesisConfig for the runtime. See impl_outer_config macro. #[macro_export] #[doc(hidden)] macro_rules! __decl_outer_config { ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - Config $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - __decl_outer_config!( - $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - Config $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + Config $(< $config_generic:ident $(, $config_instance:path)?>)? $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )* + }, + $( $rest:tt )* ) => { - __decl_outer_config!( + $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { + $( $parsed )* + $module::$name $( $module_instance )? $(<$config_generic $(, $config_instance)?>)?, + }; + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { + $ingore:ident $( <$ignor:ident $(, $ignore_instance:path)?> )* $(, $modules:ident $( <$modules_generic:ident $(, $modules_instance:path)?> )* )* + }, + $( $rest:tt )* ) => { - __decl_outer_config!( + $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; + { $( $parsed )* }; + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* }, + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, + $( $rest:tt )* ) => { - __decl_outer_config!( + $crate::__decl_outer_config!( $runtime; - $( $parsed_modules :: $parsed_name $( < $parsed_generic > )*),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; + { $( $parsed )* }; + $( $rest )* ); }; ( $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident $( < $parsed_generic:ident > )* ),*; - ; + {$( $parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )? $( < $parsed_generic:ident $(, $parsed_instance_full_path:path)? > )* ,)* }; ) => { - substrate_generate_ident_name! { - impl_outer_config!( + $crate::paste::item! { + $crate::runtime_primitives::impl_outer_config!( pub struct GenesisConfig for $runtime { $( - "config-ident" $parsed_name => $parsed_modules $( < $parsed_generic > )*, + [< $parsed_name Config >] => [< $parsed_modules $( _ $parsed_instance)? >] $( < $parsed_generic $(, $parsed_instance_full_path)? > )*, )* } ); @@ -1065,29 +822,30 @@ macro_rules! __decl_outer_config { }; } +/// A private macro that generates check_inherents() implementation for the runtime. #[macro_export] #[doc(hidden)] macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $inherent:ty; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $uncheckedextrinsic:ident; + $( $parsed_name:ident :: $parsed_call:ident ),*; $name:ident: $module:ident::{ - Inherent $(, $modules:ident $( <$modules_generic:ident> )* )* + Inherent $(, $modules:ident $( ( $( $modules_call:ident )* ) )* )* } $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + $( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),* })*; ) => { - __decl_outer_inherent!( + $crate::__decl_outer_inherent!( $runtime; $block; - $inherent; - $( $parsed_modules :: $parsed_name, )* $module::$name; + $uncheckedextrinsic; + $( $parsed_name :: $parsed_call, )* $name::$name; $( $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* + $( $rest_modules $( ( $( $rest_call )* ) )* ),* } ),*; ); @@ -1095,24 +853,49 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $inherent:ty; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $uncheckedextrinsic:ident; + $( $parsed_name:ident :: $parsed_call:ident ),*; $name:ident: $module:ident::{ - $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* + Inherent ( $call:ident ) $(, $modules:ident $( ( $( $modules_call:ident )* ) )* )* } $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + $( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),* })*; ) => { - __decl_outer_inherent!( + $crate::__decl_outer_inherent!( $runtime; $block; - $inherent; - $( $parsed_modules :: $parsed_name ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $uncheckedextrinsic; + $( $parsed_name :: $parsed_call, )* $name::$call; + $( + $rest_name: $rest_module::{ + $( $rest_modules $( ( $( $rest_call )* ) )* ),* + } + ),*; + ); + }; + ( + $runtime:ident; + $block:ident; + $uncheckedextrinsic:ident; + $( $parsed_name:ident :: $parsed_call:ident ),*; + $name:ident: $module:ident::{ + $ingore:ident $( ( $( $ignor:ident )* ) )* + $(, $modules:ident $( ( $( $modules_call:ident )* ) )* )* + } + $(, $rest_name:ident : $rest_module:ident::{ + $( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),* + })*; + ) => { + $crate::__decl_outer_inherent!( + $runtime; + $block; + $uncheckedextrinsic; + $( $parsed_name :: $parsed_call ),*; + $name: $module::{ $( $modules $( ( $( $modules_call )* ) )* ),* } $( , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* + $( $rest_modules $( ( $( $rest_call )* ) )* ),* } )*; ); @@ -1120,21 +903,21 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $inherent:ty; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $uncheckedextrinsic:ident; + $( $parsed_name:ident :: $parsed_call:ident ),*; $name:ident: $module:ident::{} $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + $( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),* })*; ) => { - __decl_outer_inherent!( + $crate::__decl_outer_inherent!( $runtime; $block; - $inherent; - $( $parsed_modules :: $parsed_name ),*; + $uncheckedextrinsic; + $( $parsed_name :: $parsed_call ),*; $( $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* + $( $rest_modules $( ( $( $rest_call )* ) )* ),* } ),*; ); @@ -1142,16 +925,25 @@ macro_rules! __decl_outer_inherent { ( $runtime:ident; $block:ident; - $inherent:ty; - $( $parsed_modules:ident :: $parsed_name:ident ),*; + $uncheckedextrinsic:ident; + $( $parsed_name:ident :: $parsed_call:ident ),*; ; ) => { - impl_outer_inherent!( - for $runtime, - Block = $block, - InherentData = $inherent { - $($parsed_modules : $parsed_name,)* + $crate::impl_outer_inherent!( + impl Inherents where Block = $block, UncheckedExtrinsic = $uncheckedextrinsic { + $( $parsed_name : $parsed_call, )* } ); }; } + +#[macro_export] +#[doc(hidden)] +// Those imports are used by event, config, origin and log macros to get access to its inner type +macro_rules! __decl_instance_import { + ( $( $module:ident <$instance:ident> )* ) => { + $crate::paste::item! { + $(use $module as [< $module _ $instance >];)* + } + }; +} diff --git a/srml/support/src/storage/generator.rs b/srml/support/src/storage/generator.rs index a3a9395b06fca545306330628a84128d10a2149b..d76e5f62dfb4f6b6c6eb120b60e8e375621351b5 100644 --- a/srml/support/src/storage/generator.rs +++ b/srml/support/src/storage/generator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -46,16 +46,19 @@ //!# fn main() { } //! ``` -use codec; -use rstd::vec::Vec; +use crate::codec; +use crate::rstd::vec::Vec; #[doc(hidden)] -pub use rstd::borrow::Borrow; +pub use crate::rstd::borrow::Borrow; #[doc(hidden)] -pub use rstd::marker::PhantomData; +pub use crate::rstd::marker::PhantomData; +#[doc(hidden)] +pub use crate::rstd::boxed::Box; pub use srml_metadata::{ DecodeDifferent, StorageMetadata, StorageFunctionMetadata, - StorageFunctionType, StorageFunctionModifier + StorageFunctionType, StorageFunctionModifier, + DefaultByte, DefaultByteGetter, }; /// Abstraction around storage. @@ -64,34 +67,55 @@ pub trait Storage { fn exists(&self, key: &[u8]) -> bool; /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option; + fn get(&self, key: &[u8]) -> Option; /// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if /// it's not there. - fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") } + fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") } /// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's /// default is returned if it's not there. - fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() } + fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() } /// Put a value in under a key. - fn put(&self, key: &[u8], val: &T); + fn put(&self, key: &[u8], val: &T); /// Remove the bytes of a key from storage. fn kill(&self, key: &[u8]); /// Take a value from storage, deleting it after reading. - fn take(&self, key: &[u8]) -> Option { + fn take(&self, key: &[u8]) -> Option { let value = self.get(key); self.kill(key); value } /// Take a value from storage, deleting it after reading. - fn take_or_panic(&self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") } + fn take_or_panic(&self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") } /// Take a value from storage, deleting it after reading. - fn take_or_default(&self, key: &[u8]) -> T { self.take(key).unwrap_or_default() } + fn take_or_default(&self, key: &[u8]) -> T { self.take(key).unwrap_or_default() } +} + +// We use a construct like this during when genesis storage is being built. +#[cfg(feature = "std")] +impl Storage for (crate::rstd::cell::RefCell<&mut sr_primitives::StorageOverlay>, PhantomData) { + fn exists(&self, key: &[u8]) -> bool { + self.0.borrow().contains_key(S::hash(key).as_ref()) + } + + fn get(&self, key: &[u8]) -> Option { + self.0.borrow().get(S::hash(key).as_ref()) + .map(|x| codec::Decode::decode(&mut x.as_slice()).expect("Unable to decode expected type.")) + } + + fn put(&self, key: &[u8], val: &T) { + self.0.borrow_mut().insert(S::hash(key).to_vec(), codec::Encode::encode(val)); + } + + fn kill(&self, key: &[u8]) { + self.0.borrow_mut().remove(S::hash(key).as_ref()); + } } /// A strongly-typed value kept in storage. @@ -193,120 +217,129 @@ pub trait StorageMap { fn mutate R, S: Storage>(key: &K, f: F, storage: &S) -> R; } -// TODO: Remove this in favour of `decl_storage` macro. +/// A `StorageMap` with enumerable entries. +pub trait EnumerableStorageMap: StorageMap { + /// Return current head element. + fn head(storage: &S) -> Option; + + /// Enumerate all elements in the map. + fn enumerate<'a, S: Storage>(storage: &'a S) -> Box + 'a> where K: 'a, V: 'a; +} + +// FIXME #1466 Remove this in favour of `decl_storage` macro. /// Declares strongly-typed wrappers around codec-compatible types in storage. #[macro_export] macro_rules! storage_items { // simple values ($name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); + $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); + $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); storage_items!($($t)*); }; ($name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); + $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); + $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); storage_items!($($t)*); }; ($name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); + $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); + $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); + $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); + $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); + $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); + $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); + $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); + $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); storage_items!($($t)*); }; // maps ($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; ($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; ($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); + $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); storage_items!($($t)*); }; // lists ($name:ident : $prefix:expr => list [$ty:ty]; $($t:tt)*) => { - __storage_items_internal!(() $name: $prefix => list [$ty]); + $crate::__storage_items_internal!(() $name: $prefix => list [$ty]); storage_items!($($t)*); }; (pub $name:ident : $prefix:expr => list [$ty:ty]; $($t:tt)*) => { - __storage_items_internal!((pub) $name: $prefix => list [$ty]); + $crate::__storage_items_internal!((pub) $name: $prefix => list [$ty]); storage_items!($($t)*); }; () => () @@ -317,7 +350,7 @@ macro_rules! storage_items { macro_rules! __storage_items_internal { // generator for values. (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { - __storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $key => $ty } + $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $key => $ty } pub fn $get_fn() -> $gettype { <$name as $crate::storage::generator::StorageValue<$ty>> :: get(&$crate::storage::RuntimeStorage) } }; (($($vis:tt)*) () ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { @@ -347,7 +380,7 @@ macro_rules! __storage_items_internal { let ret = f(&mut val); - __handle_wrap_internal!($wraptype { + $crate::__handle_wrap_internal!($wraptype { // raw type case >::put(&val, storage) } { @@ -364,7 +397,7 @@ macro_rules! __storage_items_internal { }; // generator for maps. (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { - __storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $prefix => map [$kty => $ty] } + $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $prefix => map [$kty => $ty] } pub fn $get_fn>(key: K) -> $gettype { <$name as $crate::storage::generator::StorageMap<$kty, $ty>> :: get(key.borrow(), &$crate::storage::RuntimeStorage) } @@ -405,7 +438,7 @@ macro_rules! __storage_items_internal { let ret = f(&mut val); - __handle_wrap_internal!($wraptype { + $crate::__handle_wrap_internal!($wraptype { // raw type case >::insert(key, &val, storage) } { @@ -444,7 +477,6 @@ macro_rules! __storage_items_internal { } /// Get the key used to put the length field. - // TODO: concat macro should accept byte literals. fn len_key() -> $crate::rstd::vec::Vec { let mut key = $prefix.to_vec(); key.extend(b"len"); @@ -512,7 +544,7 @@ macro_rules! __handle_wrap_internal { }; } -// TODO: revisit this idiom once we get `type`s in `impl`s. +// FIXME: revisit this idiom once we get `type`s in `impl`s. /*impl Module { type Now = super::Now; }*/ @@ -523,19 +555,20 @@ macro_rules! __handle_wrap_internal { mod tests { use std::collections::HashMap; use std::cell::RefCell; - use codec::Codec; + use codec::{Decode, Encode}; use super::*; + use crate::rstd::marker::PhantomData; impl Storage for RefCell, Vec>> { fn exists(&self, key: &[u8]) -> bool { self.borrow_mut().get(key).is_some() } - fn get(&self, key: &[u8]) -> Option { + fn get(&self, key: &[u8]) -> Option { self.borrow_mut().get(key).map(|v| T::decode(&mut &v[..]).unwrap()) } - fn put(&self, key: &[u8], val: &T) { + fn put(&self, key: &[u8], val: &T) { self.borrow_mut().insert(key.to_owned(), val.encode()); } @@ -599,7 +632,7 @@ mod tests { pub struct Module for enum Call where origin: T::Origin {} } - decl_storage! { + crate::decl_storage! { trait Store for Module as TestStorage { // non-getters: pub / $default @@ -633,6 +666,10 @@ mod tests { GETMAPU32MYDEF get(map_u32_getter_mydef): map u32 => String = "map".into(); pub PUBGETMAPU32MYDEF get(pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); + + COMPLEXTYPE1: ::std::vec::Vec<::Origin>; + COMPLEXTYPE2: (Vec)>>, u32); + COMPLEXTYPE3: ([u32;25]); } add_extra_genesis { build(|_, _, _| {}); @@ -647,86 +684,122 @@ mod tests { } const EXPECTED_METADATA: StorageMetadata = StorageMetadata { - prefix: DecodeDifferent::Encode("TestStorage"), functions: DecodeDifferent::Encode(&[ StorageFunctionMetadata { name: DecodeDifferent::Encode("U32"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[ " Hello, this is doc!" ]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBU32"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("U32MYDEF"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBU32MYDEF"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, - StorageFunctionMetadata { name: DecodeDifferent::Encode("GETU32"), modifier: StorageFunctionModifier::Default, - ty: StorageFunctionType::Plain(DecodeDifferent::Encode("T :: Origin")), + ty: StorageFunctionType::Plain(DecodeDifferent::Encode("T::Origin")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETU32"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("GETU32WITHCONFIG"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32WITHCONFIG(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIG"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIG(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, - StorageFunctionMetadata { name: DecodeDifferent::Encode("GETU32MYDEF"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETU32MYDEF"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("GETU32WITHCONFIGMYDEF"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32WITHCONFIGMYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEF"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEFOPT"), modifier: StorageFunctionModifier::Optional, ty: StorageFunctionType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEFOPT(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, @@ -736,6 +809,9 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructMAPU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { @@ -744,6 +820,9 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBMAPU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { @@ -752,6 +831,9 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { @@ -760,15 +842,20 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, - StorageFunctionMetadata { name: DecodeDifferent::Encode("GETMAPU32"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { @@ -777,15 +864,20 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, - StorageFunctionMetadata { name: DecodeDifferent::Encode("GETMAPU32MYDEF"), modifier: StorageFunctionModifier::Default, ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, StorageFunctionMetadata { @@ -794,6 +886,36 @@ mod tests { ty: StorageFunctionType::Map{ key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String") }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE1"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Plain(DecodeDifferent::Encode("::std::vec::Vec<::Origin>")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE2"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Plain(DecodeDifferent::Encode("(Vec)>>, u32)")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageFunctionMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE3"), + modifier: StorageFunctionModifier::Default, + ty: StorageFunctionType::Plain(DecodeDifferent::Encode("([u32; 25])")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE3(PhantomData::)) + ), documentation: DecodeDifferent::Encode(&[]), }, ]) @@ -816,6 +938,7 @@ mod tests { assert_eq!(config.pub_u32_getter_with_config_mydef, 1u32); assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 100u32); } + } #[cfg(test)] @@ -832,7 +955,7 @@ mod test2 { type PairOf = (T, T); - decl_storage! { + crate::decl_storage! { trait Store for Module as TestStorage { SingleDef : u32; PairDef : PairOf; @@ -853,3 +976,29 @@ mod test2 { type BlockNumber = u32; } } + +#[cfg(test)] +#[allow(dead_code)] +mod test3 { + pub trait Trait { + type Origin; + type BlockNumber; + } + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + crate::decl_storage! { + trait Store for Module as Test { + Foo get(foo) config(initial_foo): u32; + } + } + + type PairOf = (T, T); + + struct TraitImpl {} + + impl Trait for TraitImpl { + type Origin = u32; + type BlockNumber = u32; + } +} diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index 6e1302718abd1bf574f107c4f8b755f159a33186..fde07628778748f0d25b5c733b56fe08e9e092ea 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,16 +16,14 @@ //! Stuff to do with the runtime's storage. -use rstd::prelude::*; -use rstd::borrow::Borrow; +use crate::rstd::prelude::*; +use crate::rstd::borrow::Borrow; use runtime_io::{self, twox_128}; -use codec::{Codec, Decode, KeyedVec, Input}; +use crate::codec::{Codec, Encode, Decode, KeyedVec, Input}; #[macro_use] pub mod generator; -// TODO: consider using blake256 to avoid possible preimage attack. - struct IncrementalInput<'a> { key: &'a [u8], pos: usize, @@ -34,14 +32,14 @@ struct IncrementalInput<'a> { impl<'a> Input for IncrementalInput<'a> { fn read(&mut self, into: &mut [u8]) -> usize { let len = runtime_io::read_storage(self.key, into, self.pos).unwrap_or(0); - let read = ::rstd::cmp::min(len, into.len()); + let read = crate::rstd::cmp::min(len, into.len()); self.pos += read; read } } - /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. -pub fn get(key: &[u8]) -> Option { +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +pub fn get(key: &[u8]) -> Option { let key = twox_128(key); runtime_io::read_storage(&key[..], &mut [0; 0][..], 0).map(|_| { let mut input = IncrementalInput { @@ -54,29 +52,29 @@ pub fn get(key: &[u8]) -> Option { /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. -pub fn get_or_default(key: &[u8]) -> T { +pub fn get_or_default(key: &[u8]) -> T { get(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. -pub fn get_or(key: &[u8], default_value: T) -> T { +pub fn get_or(key: &[u8], default_value: T) -> T { get(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. -pub fn get_or_else T>(key: &[u8], default_value: F) -> T { +pub fn get_or_else T>(key: &[u8], default_value: F) -> T { get(key).unwrap_or_else(default_value) } /// Put `value` in storage under `key`. -pub fn put(key: &[u8], value: &T) { +pub fn put(key: &[u8], value: &T) { value.using_encoded(|slice| runtime_io::set_storage(&twox_128(key)[..], slice)); } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. -pub fn take(key: &[u8]) -> Option { +pub fn take(key: &[u8]) -> Option { let r = get(key); if r.is_some() { kill(key); @@ -86,19 +84,19 @@ pub fn take(key: &[u8]) -> Option { /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. -pub fn take_or_default(key: &[u8]) -> T { +pub fn take_or_default(key: &[u8]) -> T { take(key).unwrap_or_else(Default::default) } /// Return the value of the item in storage under `key`, or `default_value` if there is no /// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or(key: &[u8], default_value: T) -> T { +pub fn take_or(key: &[u8], default_value: T) -> T { take(key).unwrap_or(default_value) } /// Return the value of the item in storage under `key`, or `default_value()` if there is no /// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or_else T>(key: &[u8], default_value: F) -> T { +pub fn take_or_else T>(key: &[u8], default_value: F) -> T { take(key).unwrap_or_else(default_value) } @@ -125,18 +123,18 @@ pub fn put_raw(key: &[u8], value: &[u8]) { /// The underlying runtime storage. pub struct RuntimeStorage; -impl ::GenericStorage for RuntimeStorage { +impl crate::GenericStorage for RuntimeStorage { fn exists(&self, key: &[u8]) -> bool { super::storage::exists(key) } /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option { + fn get(&self, key: &[u8]) -> Option { super::storage::get(key) } /// Put a value in under a key. - fn put(&self, key: &[u8], val: &T) { + fn put(&self, key: &[u8], val: &T) { super::storage::put(key, val) } @@ -146,7 +144,7 @@ impl ::GenericStorage for RuntimeStorage { } /// Take a value from storage, deleting it after reading. - fn take(&self, key: &[u8]) -> Option { + fn take(&self, key: &[u8]) -> Option { super::storage::take(key) } } @@ -338,6 +336,28 @@ impl StorageMap for U where U: generator::StorageMa } } +/// A storage map that can be enumerated. +/// +/// Note that type is primarily useful for off-chain computations. +/// Runtime implementors should avoid enumerating storage entries. +pub trait EnumerableStorageMap: StorageMap { + /// Return current head element. + fn head() -> Option; + + /// Enumerate all elements in the map. + fn enumerate() -> Box> where K: 'static, V: 'static; +} + +impl EnumerableStorageMap for U where U: generator::EnumerableStorageMap { + fn head() -> Option { + >::head(&RuntimeStorage) + } + + fn enumerate() -> Box> where K: 'static, V: 'static { + >::enumerate(&RuntimeStorage) + } +} + /// A trait to conveniently store a vector of storable data. pub trait StorageVec { type Item: Default + Sized + Codec; @@ -398,7 +418,7 @@ pub trait StorageVec { } pub mod unhashed { - use rstd::borrow::Borrow; + use crate::rstd::borrow::Borrow; use super::{runtime_io, Codec, Decode, KeyedVec, Vec, IncrementalInput}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs new file mode 100644 index 0000000000000000000000000000000000000000..fbce46eac0aef58883898e47004df06871dc0075 --- /dev/null +++ b/srml/support/src/traits.rs @@ -0,0 +1,278 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits for SRML + +use crate::rstd::result; +use crate::codec::{Codec, Encode, Decode}; +use crate::runtime_primitives::traits::{ + MaybeSerializeDebug, SimpleArithmetic, As +}; + +/// The account with the given id was killed. +pub trait OnFreeBalanceZero { + /// The account was the given id was killed. + fn on_free_balance_zero(who: &AccountId); +} + +impl OnFreeBalanceZero for () { + fn on_free_balance_zero(_who: &AccountId) {} +} +impl< + AccountId, + X: OnFreeBalanceZero, + Y: OnFreeBalanceZero, +> OnFreeBalanceZero for (X, Y) { + fn on_free_balance_zero(who: &AccountId) { + X::on_free_balance_zero(who); + Y::on_free_balance_zero(who); + } +} + +/// Trait for a hook to get called when some balance has been minted, causing dilution. +pub trait OnDilution { + /// Some `portion` of the total balance just "grew" by `minted`. `portion` is the pre-growth + /// amount (it doesn't take account of the recent growth). + fn on_dilution(minted: Balance, portion: Balance); +} + +impl OnDilution for () { + fn on_dilution(_minted: Balance, _portion: Balance) {} +} + +/// Outcome of a balance update. +pub enum UpdateBalanceOutcome { + /// Account balance was simply updated. + Updated, + /// The update has led to killing of the account. + AccountKilled, +} + +pub trait ArithmeticType { + type Type: SimpleArithmetic + As + As + Codec + Copy + MaybeSerializeDebug + Default; +} + +/// Abstraction over a fungible assets system. +pub trait Currency { + /// The balance of an account. + type Balance; + + // PUBLIC IMMUTABLES + + /// The combined balance of `who`. + fn total_balance(who: &AccountId) -> Self::Balance; + + /// Some result as `slash(who, value)` (but without the side-effects) assuming there are no + /// balance changes in the meantime and only the reserved balance is not taken into account. + fn can_slash(who: &AccountId, value: Self::Balance) -> bool; + + /// Same result as `reserve(who, value)` (but without the side-effects) assuming there + /// are no balance changes in the meantime. + fn can_reserve(who: &AccountId, value: Self::Balance) -> bool; + + /// The total amount of stake on the system. + fn total_issuance() -> Self::Balance; + + /// The minimum balance any single account may have. This is equivalent to Balances module's + /// Existential Deposit. + fn minimum_balance() -> Self::Balance; + + /// The 'free' balance of a given account. + /// + /// This is the only balance that matters in terms of most operations on tokens. It is + /// alone used to determine the balance when in the contract execution environment. When this + /// balance falls below the value of `ExistentialDeposit`, then the 'current account' is + /// deleted: specifically `FreeBalance`. Furthermore, `OnFreeBalanceZero` callback + /// is invoked, giving a chance to external modules to cleanup data associated with + /// the deleted account. + /// + /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets + /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. + fn free_balance(who: &AccountId) -> Self::Balance; + + /// The amount of the balance of a given account that is externally reserved; this can still get + /// slashed, but gets slashed last of all. + /// + /// This balance is a 'reserve' balance that other subsystems use in order to set aside tokens + /// that are still 'owned' by the account holder, but which are suspendable. (This is different + /// and wholly unrelated to the `Bondage` system used in the staking module.) + /// + /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' + /// is deleted: specifically, `ReservedBalance`. + /// + /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets + /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. + fn reserved_balance(who: &AccountId) -> Self::Balance; + + // PUBLIC MUTABLES (DANGEROUS) + + /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the + /// free balance. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + fn slash(who: &AccountId, value: Self::Balance) -> Option; + + /// Adds up to `value` to the free balance of `who`. + /// + /// If `who` doesn't exist, nothing is done and an Err returned. + fn reward(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; + + /// Adds up to `value` to the free balance of `who`. + /// + /// If `who` doesn't exist, it is created + /// + /// Returns if the account was successfully updated or update has led to killing of the account. + /// + /// NOTE: This assumes that the total stake remains unchanged after this operation. + fn increase_free_balance_creating(who: &AccountId, value: Self::Balance) -> UpdateBalanceOutcome; + + /// Moves `value` from balance to reserved balance. + /// + /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will + /// be returned to notify of this. This is different behaviour to `unreserve`. + fn reserve(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; + + /// Moves up to `value` from reserved balance to balance. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + /// NOTE: This is different to `reserve`. + fn unreserve(who: &AccountId, value: Self::Balance) -> Option; + + /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + fn slash_reserved(who: &AccountId, value: Self::Balance) -> Option; + + /// Moves up to `value` from reserved balance of account `slashed` to free balance of account + /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be + /// returned. + /// + /// As much funds up to `value` will be moved as possible. If this is less than `value`, then + /// `Ok(Some(remaining))` will be returned. Full completion is given by `Ok(None)`. + fn repatriate_reserved( + slashed: &AccountId, + beneficiary: &AccountId, + value: Self::Balance + ) -> result::Result, &'static str>; +} + +/// An identifier for a lock. Used for disambiguating different locks so that +/// they can be individually replaced or removed. +pub type LockIdentifier = [u8; 8]; + +/// A currency whose accounts can have liquidity restrictions. +pub trait LockableCurrency: Currency { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// Introduce a new lock or change an existing one. + fn set_lock( + id: LockIdentifier, + who: &AccountId, + amount: Self::Balance, + until: Self::Moment, + reasons: WithdrawReasons, + ); + + /// Change any existing lock so that it becomes strictly less liquid in all + /// respects to the given parameters. + fn extend_lock( + id: LockIdentifier, + who: &AccountId, + amount: Self::Balance, + until: Self::Moment, + reasons: WithdrawReasons, + ); + + /// Remove an existing lock. + fn remove_lock( + id: LockIdentifier, + who: &AccountId, + ); +} + +/// Charge bytes fee trait +pub trait ChargeBytesFee { + /// Charge fees from `transactor` for an extrinsic (transaction) of encoded length + /// `encoded_len` bytes. Return Ok if the payment was successful. + fn charge_base_bytes_fee(transactor: &AccountId, encoded_len: usize) -> Result<(), &'static str>; +} + +/// Charge fee trait +pub trait ChargeFee: ChargeBytesFee { + /// The type of fee amount. + type Amount; + + /// Charge `amount` of fees from `transactor`. Return Ok iff the payment was successful. + fn charge_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; + + /// Refund `amount` of previous charged fees from `transactor`. Return Ok if the refund was successful. + fn refund_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; +} + +bitmask! { + /// Reasons for moving funds out of an account. + #[derive(Encode, Decode)] + pub mask WithdrawReasons: i8 where + + /// Reason for moving funds out of an account. + #[derive(Encode, Decode)] + flags WithdrawReason { + /// In order to pay for (system) transaction costs. + TransactionPayment = 0b00000001, + /// In order to transfer ownership. + Transfer = 0b00000010, + /// In order to reserve some funds for a later return or repatriation + Reserve = 0b00000100, + } +} + +/// Transfer fungible asset trait +pub trait TransferAsset { + /// The type of asset amount. + type Amount; + + /// Transfer asset from `from` account to `to` account with `amount` of asset. + fn transfer(from: &AccountId, to: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; + + /// Remove asset from `who` account by deducting `amount` in the account balances. + fn withdraw(who: &AccountId, amount: Self::Amount, reason: WithdrawReason) -> Result<(), &'static str>; + + /// Add asset to `who` account by increasing `amount` in the account balances. + fn deposit(who: &AccountId, amount: Self::Amount) -> Result<(), &'static str>; +} + +impl ChargeBytesFee for () { + fn charge_base_bytes_fee(_: &T, _: usize) -> Result<(), &'static str> { Ok(()) } +} + +impl ChargeFee for () { + type Amount = (); + + fn charge_fee(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } + fn refund_fee(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } +} + +impl TransferAsset for () { + type Amount = (); + + fn transfer(_: &T, _: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } + fn withdraw(_: &T, _: Self::Amount, _: WithdrawReason) -> Result<(), &'static str> { Ok(()) } + fn deposit(_: &T, _: Self::Amount) -> Result<(), &'static str> { Ok(()) } +} diff --git a/srml/support/test/Cargo.toml b/srml/support/test/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e1113eb46851f3a82a5848c42ab3441b934e6fb6 --- /dev/null +++ b/srml/support/test/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "srml-support-test" +version = "0.1.0" +authors = ["thiolliere "] +edition = "2018" + +[dev-dependencies] +serde = { version = "1.0", default-features = false } +serde_derive = { version = "1.0" } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +runtime_io = { package = "sr-io", path = "../../../core/sr-io", default-features = false } +srml-support = { path = "../", default-features = false } +inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false } +primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "serde/std", + "parity-codec/std", + "runtime_io/std", + "srml-support/std", + "inherents/std", + "primitives/std", +] diff --git a/srml/support/test/src/lib.rs b/srml/support/test/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs new file mode 100644 index 0000000000000000000000000000000000000000..373e3e23d090f53c37da53f6389d4e1e95136418 --- /dev/null +++ b/srml/support/test/tests/instance.rs @@ -0,0 +1,457 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![recursion_limit="128"] + +#[cfg(feature = "std")] +use serde_derive::Serialize; +use runtime_io::{with_externalities, Blake2Hasher}; +use srml_support::rstd::prelude::*; +use srml_support::rstd as rstd; +use srml_support::codec::{Encode, Decode}; +use srml_support::runtime_primitives::{generic, BuildStorage}; +use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify, Digest}; +use srml_support::{Parameter, construct_runtime, decl_module, decl_storage, decl_event}; +use inherents::{ + ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError +}; +use srml_support::{StorageValue, StorageMap}; +use primitives::{H256, sr25519}; + +pub trait Currency { +} + +// Mock +mod system { + use super::*; + + pub trait Trait: 'static + Eq + Clone { + type Origin: Into>> + From>; + type BlockNumber; + type Digest: Digest; + type Hash; + type AccountId; + type Event: From; + type Log: From> + Into>; + } + + pub type DigestItemOf = <::Digest as Digest>::Item; + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { + pub fn deposit_event(_event: T::Event) { + } + } + } + impl Module { + pub fn deposit_log(_item: ::Item) { + unimplemented!(); + } + } + + decl_event!( + pub enum Event { + ExtrinsicSuccess, + ExtrinsicFailed, + } + ); + + /// Origin for the system module. + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum RawOrigin { + Root, + Signed(AccountId), + Inherent, + } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::Inherent, + } + } + } + + pub type Origin = RawOrigin<::AccountId>; + + pub type Log = RawLog< + ::Hash, + >; + + #[cfg_attr(feature = "std", derive(Serialize, Debug))] + #[derive(Encode, Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + ChangesTrieRoot(H), + } + + pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> + where OuterOrigin: Into>> + { + match o.into() { + Some(RawOrigin::Root) => Ok(()), + _ => Err("bad origin: expected to be a root origin"), + } + } +} + +// Test for: +// * No default instance +// * Custom InstantiableTrait +// * Origin, Inherent, Log, Event +mod module1 { + use super::*; + + pub trait Trait: system::Trait { + type Event: From> + Into<::Event>; + type Origin: From>; + type Log: From> + Into>; + } + + decl_module! { + pub struct Module, I: InstantiableThing> for enum Call where origin: ::Origin { + fn deposit_event() = default; + + fn one() { + Self::deposit_event(RawEvent::AnotherVariant(3)); + Self::deposit_log(RawLog::AmountChange(3)); + } + } + } + + impl, I: InstantiableThing> Module { + /// Deposit one of this module's logs. + fn deposit_log(log: Log) { + >::deposit_log(>::Log::from(log).into()); + } + } + + decl_storage! { + trait Store for Module, I: InstantiableThing> as Module1 { + pub Value config(value): u64; + pub Map: map u32 => u64; + pub LinkedMap: linked_map u32 => u64; + } + } + + decl_event! { + pub enum Event where Phantom = rstd::marker::PhantomData { + _Phantom(Phantom), + AnotherVariant(u32), + } + } + + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum Origin, I> { + Members(u32), + _Phantom(rstd::marker::PhantomData<(T, I)>), + } + + pub type Log = RawLog< + T, + I, + >; + + /// A logs in this module. + #[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))] + #[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + _Phantom(rstd::marker::PhantomData<(T, I)>), + AmountChange(u32), + } + + pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; + + impl, I: InstantiableThing> ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_data: &InherentData) -> Option { + unimplemented!(); + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> { + unimplemented!(); + } + } +} + +// Test for: +// * default instance +// * use of no_genesis_config_phantom_data +mod module2 { + use super::*; + + pub trait Trait: system::Trait { + type Amount: Parameter + Default; + type Event: From> + Into<::Event>; + type Origin: From>; + type Log: From> + Into>; + } + + impl, I: Instance> Currency for Module {} + + decl_module! { + pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { + fn deposit_event() = default; + } + } + + decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Module2 { + pub Value config(value): T::Amount; + pub Map config(map): map u64 => u64; + pub LinkedMap config(linked_map): linked_map u64 => u64; + } + extra_genesis_skip_phantom_data_field; + } + + decl_event! { + pub enum Event where Amount = >::Amount { + Variant(Amount), + } + } + + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] + pub enum Origin, I=DefaultInstance> { + Members(u32), + _Phantom(rstd::marker::PhantomData<(T, I)>), + } + + pub type Log = RawLog< + T, + I, + >; + + /// A logs in this module. + #[cfg_attr(feature = "std", derive(serde_derive::Serialize, Debug))] + #[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)] + pub enum RawLog { + _Phantom(rstd::marker::PhantomData<(T, I)>), + AmountChange(u32), + } + + pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; + + impl, I: Instance> ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_data: &InherentData) -> Option { + unimplemented!(); + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> rstd::result::Result<(), Self::Error> { + unimplemented!(); + } + } +} + +// Test for: +// * Depends on multiple instances of a module with instances +mod module3 { + use super::*; + + pub trait Trait: module2::Trait + module2::Trait + system::Trait { + type Currency: Currency; + type Currency2: Currency; + } + + decl_module! { + pub struct Module for enum Call where origin: ::Origin { + } + } +} + +impl module1::Trait for Runtime { + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module1::Trait for Runtime { + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u16; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u32; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u32; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module2::Trait for Runtime { + type Amount = u64; + type Event = Event; + type Origin = Origin; + type Log = Log; +} +impl module3::Trait for Runtime { + type Currency = Module2_2; + type Currency2 = Module2_3; +} + +pub type Signature = sr25519::Signature; +pub type AccountId = ::Signer; +pub type BlockNumber = u64; +pub type Index = u64; + +impl system::Trait for Runtime { + type Hash = H256; + type Origin = Origin; + type BlockNumber = BlockNumber; + type Digest = generic::Digest; + type AccountId = AccountId; + type Event = Event; + type Log = Log; +} + +construct_runtime!( + pub enum Runtime with Log(InternalLog: DigestItem) where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event, Log(ChangesTrieRoot)}, + Module1_1: module1::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module1_2: module1::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2: module2::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_1: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_2: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module2_3: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent}, + Module3: module3::{Module, Call}, + } +); + +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; + +fn new_test_ext() -> runtime_io::TestExternalities { + GenesisConfig{ + module1_Instance1: Some(module1::GenesisConfig { + value: 3, + .. Default::default() + }), + module1_Instance2: Some(module1::GenesisConfig { + value: 4, + _genesis_phantom_data: Default::default(), + }), + module2: Some(module2::GenesisConfig { + value: 4, + map: vec![], + linked_map: vec![], + }), + module2_Instance1: None, + module2_Instance2: None, + module2_Instance3: None, + }.build_storage().unwrap().0.into() +} + +#[test] +fn storage_instance_independance() { + with_externalities(&mut new_test_ext(), || { + let mut map = rstd::collections::btree_map::BTreeMap::new(); + for key in &[ + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Value::::key().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::Map::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::LinkedMap::::prefix().to_vec(), + module2::Map::::key_for(0), + module2::Map::::key_for(0).to_vec(), + module2::Map::::key_for(0).to_vec(), + module2::Map::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0), + module2::LinkedMap::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0).to_vec(), + module2::LinkedMap::::key_for(0).to_vec(), + module2::Map::::key_for(1), + module2::Map::::key_for(1).to_vec(), + module2::Map::::key_for(1).to_vec(), + module2::Map::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1), + module2::LinkedMap::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1).to_vec(), + module2::LinkedMap::::key_for(1).to_vec(), + ] { + assert!(map.insert(key, ()).is_none()) + } + }); +} + +#[test] +fn storage_with_instance_basic_operation() { + with_externalities(&mut new_test_ext(), || { + type Value = module2::Value; + type Map = module2::Map; + type LinkedMap = module2::LinkedMap; + + assert_eq!(Value::exists(), false); + Value::put(1); + assert_eq!(Value::get(), 1); + assert_eq!(Value::take(), 1); + assert_eq!(Value::get(), 0); + Value::mutate(|a| *a=2); + assert_eq!(Value::get(), 2); + Value::kill(); + assert_eq!(Value::get(), 0); + + let key = 1; + assert_eq!(Map::exists(1), false); + Map::insert(key, 1); + assert_eq!(Map::get(key), 1); + assert_eq!(Map::take(key), 1); + assert_eq!(Map::get(key), 0); + Map::mutate(key, |a| *a=2); + assert_eq!(Map::get(key), 2); + Map::remove(key); + assert_eq!(Map::get(key), 0); + + assert_eq!(LinkedMap::exists(1), false); + LinkedMap::insert(key, 1); + assert_eq!(LinkedMap::get(key), 1); + assert_eq!(LinkedMap::take(key), 1); + assert_eq!(LinkedMap::get(key), 0); + LinkedMap::mutate(key, |a| *a=2); + assert_eq!(LinkedMap::get(key), 2); + LinkedMap::remove(key); + assert_eq!(LinkedMap::get(key), 0); + }); +} diff --git a/srml/system/Cargo.toml b/srml/system/Cargo.toml index 5bc00b1230a026368367e6300266e27e746c8700..bd199b97f902a300b2a3d387203262a9712a3a62 100644 --- a/srml/system/Cargo.toml +++ b/srml/system/Cargo.toml @@ -2,29 +2,30 @@ name = "srml-system" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default-features = false} -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } [features] default = ["std"] std = [ - "serde/std", + "serde", + "serde_derive", "safe-mix/std", "parity-codec/std", - "parity-codec-derive/std", "substrate-primitives/std", - "sr-std/std", - "sr-io/std", + "rstd/std", + "runtime_io/std", "srml-support/std", - "sr-primitives/std", + "primitives/std", ] diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index fda59529d45f0cab879026a149ed99d649afa06e..c5397345a1e95b25ae22b255c1a834edc12551f4 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,32 +19,18 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate substrate_primitives; - -#[cfg_attr(any(feature = "std", test), macro_use)] -extern crate sr_std as rstd; - -#[macro_use] -extern crate srml_support as runtime_support; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate parity_codec as codec; -extern crate sr_io as runtime_io; -extern crate sr_primitives as primitives; -extern crate safe_mix; - +#[cfg(feature = "std")] +use serde_derive::Serialize; use rstd::prelude::*; +#[cfg(any(feature = "std", test))] +use rstd::map; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, Lookup, Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, As, CurrentHeight, BlockNumberToHash, - MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug}; + MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup}; use substrate_primitives::storage::well_known_keys; -use runtime_support::{storage, StorageValue, StorageMap, Parameter}; +use srml_support::{storage, StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage}; use safe_mix::TripletMix; - -#[cfg(any(feature = "std", test))] -use codec::Encode; +use parity_codec::{Encode, Decode}; #[cfg(any(feature = "std", test))] use runtime_io::{twox_128, TestExternalities, Blake2Hasher}; @@ -52,9 +38,31 @@ use runtime_io::{twox_128, TestExternalities, Blake2Hasher}; #[cfg(any(feature = "std", test))] use substrate_primitives::ChangesTrieConfiguration; +/// Handler for when a new account has been created. +pub trait OnNewAccount { + /// A new account `who` has been registered. + fn on_new_account(who: &AccountId); +} + +impl OnNewAccount for () { + fn on_new_account(_who: &AccountId) {} +} + +/// Determinator to say whether a given account is unused. +pub trait IsDeadAccount { + /// Is the given account dead? + fn is_dead_account(who: &AccountId) -> bool; +} + +impl IsDeadAccount for () { + fn is_dead_account(_who: &AccountId) -> bool { + true + } +} + /// Compute the extrinsics root of a list of extrinsics. -pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { - extrinsics_data_root::(extrinsics.iter().map(codec::Encode::encode).collect()) +pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { + extrinsics_data_root::(extrinsics.iter().map(parity_codec::Encode::encode).collect()) } /// Compute the extrinsics root of a list of extrinsics. @@ -63,7 +71,7 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { H::enumerated_trie_root(&xts) } -pub trait Trait: Eq + Clone { +pub trait Trait: 'static + Eq + Clone { type Origin: Into>> + From>; type Index: Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + MaybeDisplay + SimpleArithmetic + Copy; type BlockNumber: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy + rstd::hash::Hash; @@ -71,6 +79,7 @@ pub trait Trait: Eq + Clone { type Hashing: Hash; type Digest: Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + traits::Digest; type AccountId: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + Ord + Default; + type Lookup: StaticLookup; type Header: Parameter + traits::Header< Number = Self::BlockNumber, Hash = Self::Hash, @@ -176,24 +185,33 @@ impl RawLog { impl From> for primitives::testing::DigestItem { fn from(log: RawLog) -> primitives::testing::DigestItem { match log { - RawLog::ChangesTrieRoot(root) => primitives::generic::DigestItem::ChangesTrieRoot - ::(root), + RawLog::ChangesTrieRoot(root) => primitives::generic::DigestItem::ChangesTrieRoot(root), } } } +// Create a Hash with 69 for each byte, +// only used to build genesis config +#[cfg(feature = "std")] +fn hash69 + Default>() -> T { + let mut h = T::default(); + h.as_mut().iter_mut().for_each(|byte| *byte = 69); + h +} + decl_storage! { trait Store for Module as System { pub AccountNonce get(account_nonce): map T::AccountId => T::Index; ExtrinsicCount: Option; - pub BlockHash get(block_hash) build(|_| vec![(T::BlockNumber::zero(), [69u8; 32])]): map T::BlockNumber => T::Hash; + AllExtrinsicsLen: Option; + pub BlockHash get(block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; ExtrinsicData get(extrinsic_data): map u32 => Vec; - RandomSeed get(random_seed) build(|_| [0u8; 32]): T::Hash; + RandomSeed get(random_seed) build(|_| T::Hash::default()): T::Hash; /// The current block number being processed. Set by `execute_block`. - Number get(block_number) build(|_| 1u64): T::BlockNumber; - ParentHash get(parent_hash) build(|_| [69u8; 32]): T::Hash; + Number get(block_number) build(|_| T::BlockNumber::sa(1u64)): T::BlockNumber; + ParentHash get(parent_hash) build(|_| hash69()): T::Hash; ExtrinsicsRoot get(extrinsics_root): T::Hash; Digest get(digest): T::Digest; @@ -202,8 +220,8 @@ decl_storage! { add_extra_genesis { config(changes_trie_config): Option; - build(|storage: &mut primitives::StorageMap, _: &mut primitives::ChildrenStorageMap, config: &GenesisConfig| { - use codec::Encode; + build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { + use parity_codec::Encode; storage.insert(well_known_keys::EXTRINSIC_INDEX.to_vec(), 0u32.encode()); @@ -261,6 +279,16 @@ impl Module { storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX) } + /// Gets extrinsics count. + pub fn extrinsic_count() -> u32 { + >::get().unwrap_or_default() + } + + /// Gets a total length of all executed extrinsics. + pub fn all_extrinsics_len() -> u32 { + >::get().unwrap_or_default() + } + /// Start the execution of a particular block. pub fn initialise(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) { // populate environment. @@ -277,6 +305,7 @@ impl Module { pub fn finalise() -> T::Header { >::kill(); >::kill(); + >::kill(); let number = >::take(); let parent_hash = >::take(); @@ -295,8 +324,7 @@ impl Module { // > stays to be inspected by the client. - ::new(number, extrinsics_root, storage_root, - parent_hash, digest) + ::new(number, extrinsics_root, storage_root, parent_hash, digest) } /// Deposits a log and ensures it matches the blocks log data. @@ -322,9 +350,9 @@ impl Module { #[cfg(any(feature = "std", test))] pub fn externalities() -> TestExternalities { TestExternalities::new(map![ - twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), // TODO: replace with Hash::default().encode + twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), twox_128(>::key()).to_vec() => T::BlockNumber::one().encode(), - twox_128(>::key()).to_vec() => [69u8; 32].encode(), // TODO: replace with Hash::default().encode + twox_128(>::key()).to_vec() => [69u8; 32].encode(), twox_128(>::key()).to_vec() => T::Hash::default().encode() ]) } @@ -363,19 +391,25 @@ impl Module { /// Note what the extrinsic data of the current extrinsic index is. If this is called, then /// ensure `derive_extrinsics` is also called before block-building is completed. + /// + /// NOTE this function is called only when the block is being constructed locally. + /// `execute_block` doesn't note any extrinsics. pub fn note_extrinsic(encoded_xt: Vec) { >::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt); } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &Result<(), &'static str>) { + pub fn note_applied_extrinsic(r: &Result<(), &'static str>, encoded_len: u32) { Self::deposit_event(match r { Ok(_) => Event::ExtrinsicSuccess, Err(_) => Event::ExtrinsicFailed, }.into()); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; + let total_length = encoded_len.saturating_add(Self::all_extrinsics_len()); + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index); + >::put(&total_length); } /// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block @@ -401,10 +435,10 @@ impl Default for ChainContext { } impl Lookup for ChainContext { - type Source = T::AccountId; - type Target = T::AccountId; + type Source = ::Source; + type Target = ::Target; fn lookup(&self, s: Self::Source) -> rstd::result::Result { - Ok(s) + ::lookup(s) } } @@ -429,8 +463,9 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::H256; use primitives::BuildStorage; - use primitives::traits::BlakeTwo256; + use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, DigestItem, Header}; + use srml_support::impl_outer_origin; impl_outer_origin!{ pub enum Origin for Test where system = super {} @@ -446,6 +481,7 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = u16; type Log = DigestItem; @@ -477,8 +513,8 @@ mod tests { System::initialise(&2, &[0u8; 32].into(), &[0u8; 32].into()); System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(())); - System::note_applied_extrinsic(&Err("")); + System::note_applied_extrinsic(&Ok(()), 0); + System::note_applied_extrinsic(&Err(""), 0); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalise(); diff --git a/srml/timestamp/Cargo.toml b/srml/timestamp/Cargo.toml index b11e74e3eb460800cbe67bb60aff3d8a8596a812..413c487214454aa33b766ca493fe15da523ae8df 100644 --- a/srml/timestamp/Cargo.toml +++ b/srml/timestamp/Cargo.toml @@ -2,32 +2,30 @@ name = "srml-timestamp" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-consensus = { path = "../consensus", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -sr-io = { path = "../../core/sr-io", default-features = true } +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "sr-std/std", - "sr-io/std", + "rstd/std", "srml-support/std", - "sr-primitives/std", - "srml-consensus/std", - "serde/std", + "runtime_primitives/std", + "serde", "parity-codec/std", - "substrate-primitives/std", - "srml-system/std", + "system/std", + "inherents/std", ] diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index d89bb50a648ac6bf482429b733364e68ee880002..f3e0d8153e2a09aaa9e9f33cf5d4604b8ec6c5a8 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,72 +14,192 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Timestamp manager: provides means to find out the current time. +//! # Timestamp Module +//! +//! The timestamp module provides functionality to get and set the on-chain time. +//! To use it in your module, you need to implement the timestamp [`Trait`]. +//! The supported dispatchable functions are documented as part of the [`Call`] enum. +//! +//! ## Overview +//! +//! The timestamp module allows the validators to set and validate a timestamp with each block. //! -//! It is expected that the timestamp is set by the validator in the -//! beginning of each block, typically one of the first extrinsics. The timestamp -//! can be set only once per block and must be set each block. +//! It uses inherents for timestamp data, which is provided by the block author and validated/verified by other validators. +//! The timestamp can be set only once per block and must be set each block. There could be a constraint on how much time must pass before setting the new timestamp. +//! +//! **NOTE:** The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. +//! The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. +//! +//! ## Interface +//! +//! ### Dispatchable functions ([`Call`]) +//! +//! * `set` - Sets the current time. +//! +//! ### Public functions ([`Module`]) +//! +//! * `get` - Gets the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. +//! +//! * `block_period` - Gets the minimum (and advised) period between blocks for the chain. +//! +//! ## Usage +//! +//! The following example shows how to use the timestamp module in your custom module to query the current timestamp. +//! +//! ### Prerequisites +//! +//! Import the `timestamp` module in your custom module and derive the module configuration trait from the `timestamp` trait. +//! +//! ### Get current timestamp +//! +//! ```ignore +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! +//! pub trait Trait: timestamp::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn get_time(origin) -> Result { +//! let _sender = ensure_signed(origin)?; +//! let _now = >::get(); +//! Ok(()) +//! } +//! } +//! } +//! ``` +//! +//! ### Example from SRML +//! +//! The [`Session` module](https://github.com/paritytech/substrate/blob/master/srml/session/src/lib.rs) uses the `timestamp` module for session management. +//! +//! ## Related Modules +//! +//! * [`System`](https://crates.parity.io/srml_system/index.html) +//! * [`Session`](https://crates.parity.io/srml_session/index.html) //! -//! Note, that there might be a constraint on how much time must pass -//! before setting the new timestamp, specified by the `tim:block_period` -//! storage entry. -//! -//! # Interaction with the system -//! -//! ## Finalization -//! -//! This module should be hooked up to the finalization routine. #![cfg_attr(not(feature = "std"), no_std)] -#[cfg_attr(not(feature = "std"), macro_use)] -extern crate sr_std as rstd; +use parity_codec::Encode; +#[cfg(feature = "std")] +use parity_codec::Decode; +#[cfg(feature = "std")] +use inherents::ProvideInherentData; +use srml_support::{StorageValue, Parameter, decl_storage, decl_module}; +use srml_support::for_each_tuple; +use runtime_primitives::traits::{As, SimpleArithmetic, Zero}; +use system::ensure_inherent; +use rstd::{result, ops::{Mul, Div}, cmp}; +use inherents::{RuntimeString, InherentIdentifier, ProvideInherent, IsFatalError, InherentData}; + +/// The identifier for the `timestamp` inherent. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0"; +/// The type of the inherent. +pub type InherentType = u64; + +/// Errors that can occur while checking the timestamp inherent. +#[derive(Encode)] +#[cfg_attr(feature = "std", derive(Debug, Decode))] +pub enum InherentError { + /// The timestamp is valid in the future. + /// This is a non-fatal-error and will not stop checking the inherents. + ValidAtTimestamp(InherentType), + /// Some other error. + Other(RuntimeString), +} -#[macro_use] -extern crate srml_support as runtime_support; +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match self { + InherentError::ValidAtTimestamp(_) => false, + InherentError::Other(_) => true, + } + } +} -#[cfg(test)] -extern crate substrate_primitives; -#[cfg(test)] -extern crate sr_io as runtime_io; -extern crate sr_primitives as runtime_primitives; -extern crate srml_system as system; -extern crate srml_consensus as consensus; -extern crate parity_codec as codec; - -use codec::HasCompact; -use runtime_support::{StorageValue, Parameter}; -use runtime_primitives::CheckInherentError; -use runtime_primitives::traits::{ - As, SimpleArithmetic, Zero, ProvideInherent, Block as BlockT, Extrinsic -}; -use system::ensure_inherent; -use rstd::{result, ops::{Mul, Div}, vec::Vec}; +impl InherentError { + /// Try to create an instance ouf of the given identifier and data. + #[cfg(feature = "std")] + pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option { + if id == &INHERENT_IDENTIFIER { + ::decode(&mut &data[..]) + } else { + None + } + } +} + +/// Auxiliary trait to extract timestamp inherent data. +pub trait TimestampInherentData { + /// Get timestamp inherent data. + fn timestamp_inherent_data(&self) -> Result; +} + +impl TimestampInherentData for InherentData { + fn timestamp_inherent_data(&self) -> Result { + self.get_data(&INHERENT_IDENTIFIER) + .and_then(|r| r.ok_or_else(|| "Timestamp inherent data not found".into())) + } +} + +#[cfg(feature = "std")] +pub struct InherentDataProvider; + +#[cfg(feature = "std")] +impl ProvideInherentData for InherentDataProvider { + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { + use std::time::SystemTime; + + let now = SystemTime::now(); + now.duration_since(SystemTime::UNIX_EPOCH) + .map_err(|_| { + "Current time is before unix epoch".into() + }).and_then(|d| { + let duration: InherentType = d.as_secs(); + inherent_data.put_data(INHERENT_IDENTIFIER, &duration) + }) + } + + fn error_to_string(&self, error: &[u8]) -> Option { + InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e)) + } +} /// A trait which is called when the timestamp is set. pub trait OnTimestampSet { fn on_timestamp_set(moment: Moment); } -impl OnTimestampSet for () { - fn on_timestamp_set(_moment: Moment) { } -} +macro_rules! impl_timestamp_set { + () => ( + impl OnTimestampSet for () { + fn on_timestamp_set(_: Moment) {} + } + ); -impl OnTimestampSet for (A, B) - where A: OnTimestampSet, B: OnTimestampSet -{ - fn on_timestamp_set(moment: Moment) { - A::on_timestamp_set(moment.clone()); - B::on_timestamp_set(moment); + ( $($t:ident)* ) => { + impl),*> OnTimestampSet for ($($t,)*) { + fn on_timestamp_set(moment: Moment) { + $($t::on_timestamp_set(moment.clone());)* + } + } } } -pub trait Trait: consensus::Trait + system::Trait { - /// The position of the required timestamp-set extrinsic. - const TIMESTAMP_SET_POSITION: u32; +for_each_tuple!(impl_timestamp_set); +/// The module configuration trait +pub trait Trait: system::Trait { /// Type used for expressing timestamp. - type Moment: Parameter + Default + SimpleArithmetic + Mul + Div; + type Moment: Parameter + Default + SimpleArithmetic + + Mul + + Div; + /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. type OnTimestampSet: OnTimestampSet; } @@ -88,22 +208,15 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Set the current time. /// - /// Extrinsic with this call should be placed at the specific position in the each block - /// (specified by the Trait::TIMESTAMP_SET_POSITION) typically at the start of the each block. /// This call should be invoked exactly once per block. It will panic at the finalization phase, /// if this call hasn't been invoked by that time. /// /// The timestamp should be greater than the previous one by the amount specified by `block_period`. - fn set(origin, now: ::Type) { + /// + /// The dispatch origin for this call must be `Inherent`. + fn set(origin, #[compact] now: T::Moment) { ensure_inherent(origin)?; - let now = now.into(); - assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); - assert!( - >::extrinsic_index() == Some(T::TIMESTAMP_SET_POSITION), - "Timestamp extrinsic must be at position {} in the block", - T::TIMESTAMP_SET_POSITION - ); assert!( Self::now().is_zero() || now >= Self::now() + Self::block_period(), "Timestamp must increment by at least between sequential blocks" @@ -124,6 +237,7 @@ decl_storage! { trait Store for Module as Timestamp { /// Current time for the current block. pub Now get(now) build(|_| T::Moment::sa(0)): T::Moment; + /// The minimum (and advised) period between blocks. pub BlockPeriod get(block_period) config(period): T::Moment = T::Moment::sa(5); @@ -133,10 +247,9 @@ decl_storage! { } impl Module { - /// Get the current time for the current block. /// - /// NOTE: if this function is called prior the setting the timestamp, + /// NOTE: if this function is called prior to setting the timestamp, /// it will return the timestamp of the previous block. pub fn get() -> T::Moment { Self::now() @@ -149,33 +262,39 @@ impl Module { } } +fn extract_inherent_data(data: &InherentData) -> Result { + data.get_data::(&INHERENT_IDENTIFIER) + .map_err(|_| RuntimeString::from("Invalid timestamp inherent data encoding."))? + .ok_or_else(|| "Timestamp inherent data is not provided.".into()) +} + impl ProvideInherent for Module { - type Inherent = T::Moment; type Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + let data = extract_inherent_data(data).expect("Gets and decodes timestamp inherent data"); - fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { - let next_time = ::rstd::cmp::max(data, Self::now() + Self::block_period()); - vec![(T::TIMESTAMP_SET_POSITION, Call::set(next_time.into()))] + let next_time = cmp::max(As::sa(data), Self::now() + Self::block_period()); + Some(Call::set(next_time.into())) } - fn check_inherent Option<&Self::Call>>( - block: &Block, data: Self::Inherent, extract_function: &F - ) -> result::Result<(), CheckInherentError> { + fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { const MAX_TIMESTAMP_DRIFT: u64 = 60; - let xt = block.extrinsics().get(T::TIMESTAMP_SET_POSITION as usize) - .ok_or_else(|| CheckInherentError::Other("No valid timestamp inherent in block".into()))?; + let t = match call { + Call::set(ref t) => t.clone(), + _ => return Ok(()), + }.as_(); - let t = match (xt.is_signed(), extract_function(&xt)) { - (Some(false), Some(Call::set(ref t))) => t.clone(), - _ => return Err(CheckInherentError::Other("No valid timestamp inherent in block".into())), - }.into().as_(); + let data = extract_inherent_data(data).map_err(|e| InherentError::Other(e))?; let minimum = (Self::now() + Self::block_period()).as_(); - if t > data.as_() + MAX_TIMESTAMP_DRIFT { - Err(CheckInherentError::Other("Timestamp too far in future to accept".into())) + if t > data + MAX_TIMESTAMP_DRIFT { + Err(InherentError::Other("Timestamp too far in future to accept".into())) } else if t < minimum { - Err(CheckInherentError::ValidAtTimestamp(minimum)) + Err(InherentError::ValidAtTimestamp(minimum)) } else { Ok(()) } @@ -186,10 +305,11 @@ impl ProvideInherent for Module { mod tests { use super::*; + use srml_support::{impl_outer_origin, assert_ok}; use runtime_io::{with_externalities, TestExternalities}; use substrate_primitives::H256; use runtime_primitives::BuildStorage; - use runtime_primitives::traits::BlakeTwo256; + use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; use runtime_primitives::testing::{Digest, DigestItem, Header}; impl_outer_origin! { @@ -206,18 +326,12 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } - impl consensus::Trait for Test { - const NOTE_OFFLINE_POSITION: u32 = 1; - type Log = DigestItem; - type SessionKey = u64; - type InherentOfflineReport = (); - } impl Trait for Test { - const TIMESTAMP_SET_POSITION: u32 = 0; type Moment = u64; type OnTimestampSet = (); } @@ -232,7 +346,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69.into()), Origin::INHERENT)); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); assert_eq!(Timestamp::now(), 69); }); } @@ -247,8 +361,8 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69.into()), Origin::INHERENT)); - let _ = Timestamp::dispatch(Call::set(70.into()), Origin::INHERENT); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); + let _ = Timestamp::dispatch(Call::set(70), Origin::INHERENT); }); } @@ -262,7 +376,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - let _ = Timestamp::dispatch(Call::set(46.into()), Origin::INHERENT); + let _ = Timestamp::dispatch(Call::set(46), Origin::INHERENT); }); } } diff --git a/srml/treasury/Cargo.toml b/srml/treasury/Cargo.toml index 9090ac4d9b025a93c54e81d21eeb357fbf4aca09..825fc73532cbc35fdbf519c8b67bac94bb05f070 100644 --- a/srml/treasury/Cargo.toml +++ b/srml/treasury/Cargo.toml @@ -2,31 +2,32 @@ name = "srml-treasury" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } +serde = { version = "1.0", optional = true } +serde_derive = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -srml-balances = { path = "../balances", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +balances = { package = "srml-balances", path = "../balances", default-features = false } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +substrate-primitives = { path = "../../core/primitives" } [features] default = ["std"] std = [ - "serde/std", + "serde", + "serde_derive", "parity-codec/std", - "parity-codec-derive/std", - "substrate-primitives/std", - "sr-std/std", - "sr-io/std", - "sr-primitives/std", + "rstd/std", + "runtime_primitives/std", "srml-support/std", - "srml-system/std", - "srml-balances/std", + "system/std", + "balances/std", ] diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index abbe0e78995e54e2e1f9c2b5d5d935e83efe803e..f57142059323912c05ebc0e72f2b0fb1dbb54d0d 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,39 +18,26 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate sr_std as rstd; - -#[macro_use] -extern crate srml_support as runtime_support; - -#[cfg(test)] -extern crate sr_io as runtime_io; #[cfg(feature = "std")] -extern crate serde; - -#[macro_use] -extern crate parity_codec_derive; - -extern crate parity_codec as codec; -#[cfg(test)] -extern crate substrate_primitives; -extern crate sr_primitives as runtime_primitives; -extern crate srml_system as system; -extern crate srml_balances as balances; - +use serde_derive::{Serialize, Deserialize}; use rstd::prelude::*; -use runtime_support::{StorageValue, StorageMap}; -use runtime_primitives::{Permill, traits::{Zero, EnsureOrigin}}; -use codec::{HasCompact, Compact}; -use balances::{OnDilution, address::Address}; +use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure}; +use srml_support::traits::{Currency, OnDilution, ArithmeticType}; +use runtime_primitives::{Permill, traits::{Zero, EnsureOrigin, StaticLookup}}; +use parity_codec::{Encode, Decode}; use system::ensure_signed; +type BalanceOf = <::Currency as ArithmeticType>::Type; + /// Our module's configuration trait. All our types and consts go in here. If the /// module is dependent on specific other modules, then their configuration traits /// should be added to our implied traits list. /// /// `system::Trait` should always be included in our implied traits. -pub trait Trait: balances::Trait { +pub trait Trait: system::Trait { + /// The staking balance. + type Currency: ArithmeticType + Currency::Currency as ArithmeticType>::Type>; + /// Origin from which approvals must come. type ApproveOrigin: EnsureOrigin; @@ -68,21 +55,20 @@ type ProposalIndex = u32; decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Put forward a suggestion for spending. A deposit proportional to the value /// is reserved and slashed if the proposal is rejected. It is returned once the /// proposal is awarded. fn propose_spend( origin, - value: ::Type, - beneficiary: Address + #[compact] value: BalanceOf, + beneficiary: ::Source ) { let proposer = ensure_signed(origin)?; - let beneficiary = >::lookup(beneficiary)?; - let value = value.into(); + let beneficiary = T::Lookup::lookup(beneficiary)?; let bond = Self::calculate_bond(value); - >::reserve(&proposer, bond) + T::Currency::reserve(&proposer, bond) .map_err(|_| "Proposer's balance too low")?; let c = Self::proposal_count(); @@ -93,40 +79,37 @@ decl_module! { } /// Set the balance of funds available to spend. - fn set_pot(new_pot: ::Type) { + fn set_pot(#[compact] new_pot: BalanceOf) { // Put the new value into storage. - >::put(new_pot.into()); + >::put(new_pot); } /// (Re-)configure this module. fn configure( - proposal_bond: Permill, - proposal_bond_minimum: ::Type, - spend_period: ::Type, - burn: Permill + #[compact] proposal_bond: Permill, + #[compact] proposal_bond_minimum: BalanceOf, + #[compact] spend_period: T::BlockNumber, + #[compact] burn: Permill ) { >::put(proposal_bond); - >::put(proposal_bond_minimum.into()); - >::put(spend_period.into()); + >::put(proposal_bond_minimum); + >::put(spend_period); >::put(burn); } /// Reject a proposed spend. The original deposit will be slashed. - fn reject_proposal(origin, proposal_id: Compact) { + fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) { T::RejectOrigin::ensure_origin(origin)?; - let proposal_id: ProposalIndex = proposal_id.into(); - let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; let value = proposal.bond; - let _ = >::slash_reserved(&proposal.proposer, value); + let _ = T::Currency::slash_reserved(&proposal.proposer, value); } /// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary /// and the original deposit will be returned. - fn approve_proposal(origin, proposal_id: Compact) { + fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) { T::ApproveOrigin::ensure_origin(origin)?; - let proposal_id = proposal_id.into(); ensure!(>::exists(proposal_id), "No proposal at that index"); @@ -161,7 +144,7 @@ decl_storage! { ProposalBond get(proposal_bond) config(): Permill; /// Minimum amount of funds that should be placed in a deposit for making a proposal. - ProposalBondMinimum get(proposal_bond_minimum) config(): T::Balance; + ProposalBondMinimum get(proposal_bond_minimum) config(): BalanceOf; /// Period between successive spends. SpendPeriod get(spend_period) config(): T::BlockNumber = runtime_primitives::traits::One::one(); @@ -172,13 +155,13 @@ decl_storage! { // State... /// Total funds available to this module for spending. - Pot get(pot): T::Balance; + Pot get(pot): BalanceOf; /// Number of proposals that have been made. ProposalCount get(proposal_count): ProposalIndex; /// Proposals that have been made. - Proposals get(proposals): map ProposalIndex => Option>; + Proposals get(proposals): map ProposalIndex => Option>>; /// Proposal indices that have been approved but not yet awarded. Approvals get(approvals): Vec; @@ -187,7 +170,11 @@ decl_storage! { /// An event in this module. decl_event!( - pub enum Event where ::Balance, ::AccountId { + pub enum Event + where + Balance = BalanceOf, + ::AccountId + { /// New proposal. Proposed(ProposalIndex), /// We have ended a spend period and will now allocate funds. @@ -205,8 +192,8 @@ impl Module { // Add public immutables and private mutables. /// The needed bond for a proposal whose spend is `value`. - fn calculate_bond(value: T::Balance) -> T::Balance { - Self::proposal_bond_minimum().max(Self::proposal_bond().times(value)) + fn calculate_bond(value: BalanceOf) -> BalanceOf { + Self::proposal_bond_minimum().max(Self::proposal_bond() * value) } // Spend some money! @@ -224,10 +211,10 @@ impl Module { >::remove(index); // return their deposit. - let _ = >::unreserve(&p.proposer, p.bond); + let _ = T::Currency::unreserve(&p.proposer, p.bond); // provide the allocation. - >::increase_free_balance_creating(&p.beneficiary, p.value); + T::Currency::increase_free_balance_creating(&p.beneficiary, p.value); Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary)); false @@ -243,7 +230,7 @@ impl Module { if !missed_any { // burn some proportion of the remaining budget if we run a surplus. - let burn = Self::burn().times(budget_remaining).min(budget_remaining); + let burn = (Self::burn() * budget_remaining).min(budget_remaining); budget_remaining -= burn; Self::deposit_event(RawEvent::Burnt(burn)) } @@ -254,12 +241,12 @@ impl Module { } } -impl OnDilution for Module { - fn on_dilution(minted: T::Balance, portion: T::Balance) { +impl OnDilution> for Module { + fn on_dilution(minted: BalanceOf, portion: BalanceOf) { // Mint extra funds for the treasury to keep the ratio of portion to total_issuance equal // pre dilution and post-dilution. if !minted.is_zero() && !portion.is_zero() { - let total_issuance = >::total_issuance(); + let total_issuance = T::Currency::total_issuance(); let funding = (total_issuance - portion) / portion * minted; >::mutate(|x| *x += funding); } @@ -271,9 +258,10 @@ mod tests { use super::*; use runtime_io::with_externalities; + use srml_support::{impl_outer_origin, assert_ok, assert_noop}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_primitives::BuildStorage; - use runtime_primitives::traits::{BlakeTwo256, OnFinalise}; + use runtime_primitives::traits::{BlakeTwo256, OnFinalise, IdentityLookup}; use runtime_primitives::testing::{Digest, DigestItem, Header}; impl_outer_origin! { @@ -290,18 +278,19 @@ mod tests { type Hashing = BlakeTwo256; type Digest = Digest; type AccountId = u64; + type Lookup = IdentityLookup; type Header = Header; type Event = (); type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; - type AccountIndex = u64; + type OnNewAccount = (); type OnFreeBalanceZero = (); - type EnsureAccountLiquid = (); type Event = (); } impl Trait for Test { + type Currency = balances::Module; type ApproveOrigin = system::EnsureRoot; type RejectOrigin = system::EnsureRoot; type Event = (); @@ -313,12 +302,10 @@ mod tests { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; t.extend(balances::GenesisConfig::{ balances: vec![(0, 100), (1, 99), (2, 1)], - transaction_base_fee: 0, - transaction_byte_fee: 0, transfer_fee: 0, creation_fee: 0, existential_deposit: 0, - reclaim_rebate: 0, + vesting: vec![], }.build_storage().unwrap().0); t.extend(GenesisConfig::{ proposal_bond: Permill::from_percent(5), @@ -353,7 +340,7 @@ mod tests { #[test] fn spend_proposal_takes_min_deposit() { with_externalities(&mut new_test_ext(), || { - assert_ok!(Treasury::propose_spend(Origin::signed(0), 1.into(), Address::Id(3))); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); assert_eq!(Balances::free_balance(&0), 99); assert_eq!(Balances::reserved_balance(&0), 1); }); @@ -362,7 +349,7 @@ mod tests { #[test] fn spend_proposal_takes_proportional_deposit() { with_externalities(&mut new_test_ext(), || { - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_eq!(Balances::free_balance(&0), 95); assert_eq!(Balances::reserved_balance(&0), 5); }); @@ -371,7 +358,7 @@ mod tests { #[test] fn spend_proposal_fails_when_proposer_poor() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::propose_spend(Origin::signed(2), 100.into(), Address::Id(3)), "Proposer's balance too low"); + assert_noop!(Treasury::propose_spend(Origin::signed(2), 100, 3), "Proposer's balance too low"); }); } @@ -380,8 +367,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0.into())); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(1); assert_eq!(Balances::free_balance(&3), 0); @@ -404,8 +391,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0.into())); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Balances::free_balance(&3), 0); @@ -418,23 +405,23 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0.into())); - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0.into()), "No proposal at that index"); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn reject_non_existant_spend_proposal_fails() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0.into()), "No proposal at that index"); + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn accept_non_existant_spend_proposal_fails() { with_externalities(&mut new_test_ext(), || { - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0.into()), "No proposal at that index"); + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } @@ -443,9 +430,9 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0.into())); - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0.into()), "No proposal at that index"); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } @@ -454,8 +441,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100.into(), Address::Id(3))); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0.into())); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Balances::free_balance(&3), 100); @@ -468,8 +455,8 @@ mod tests { with_externalities(&mut new_test_ext(), || { Treasury::on_dilution(100, 100); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 150.into(), Address::Id(3))); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0.into())); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalise(2); assert_eq!(Treasury::pot(), 100); diff --git a/srml/upgrade-key/Cargo.toml b/srml/upgrade-key/Cargo.toml index 762aaf50113ee906dd8f7d0c6ee82f6305696950..4bdbd6404c289ca4cd305f86aa06b19d51faa1d3 100644 --- a/srml/upgrade-key/Cargo.toml +++ b/srml/upgrade-key/Cargo.toml @@ -2,32 +2,25 @@ name = "srml-upgrade-key" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] -hex-literal = "0.1.0" -serde = { version = "1.0", default-features = false } -parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } -substrate-primitives = { path = "../../core/primitives", default-features = false } +serde = { version = "1.0", optional = true } +parity-codec = { version = "3.2", default-features = false } sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } srml-support = { path = "../support", default-features = false } -srml-support-procedural = { path = "../support/procedural" } -srml-system = { path = "../system", default-features = false } -srml-consensus = { path = "../consensus", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } [features] default = ["std"] std = [ - "serde/std", + "serde", "parity-codec/std", - "parity-codec-derive/std", "sr-std/std", - "sr-io/std", "sr-primitives/std", - "substrate-primitives/std", "srml-support/std", - "srml-system/std", - "srml-consensus/std", + "system/std", + "consensus/std", ] diff --git a/srml/upgrade-key/src/lib.rs b/srml/upgrade-key/src/lib.rs index 3957b080d382a513792d6a30ba0e7f432c5cdeec..46e757bcc957f35418184630cac63b345a58c7d2 100644 --- a/srml/upgrade-key/src/lib.rs +++ b/srml/upgrade-key/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,23 +19,9 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate sr_std; -#[cfg(test)] -extern crate sr_io; -#[cfg(test)] -extern crate substrate_primitives; -extern crate sr_primitives; -#[macro_use] -extern crate parity_codec_derive; -extern crate parity_codec as codec; -#[macro_use] -extern crate srml_support as support; - -extern crate srml_system as system; -extern crate srml_consensus as consensus; - use sr_std::prelude::*; -use support::StorageValue; +use sr_primitives::traits::StaticLookup; +use srml_support::{StorageValue, decl_module, decl_event, decl_storage, ensure}; use system::ensure_signed; pub trait Trait: consensus::Trait + system::Trait { @@ -46,7 +32,7 @@ pub trait Trait: consensus::Trait + system::Trait { decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; fn upgrade(origin, new: Vec) { // This is a public call, so we ensure that the origin is some signed account. let _sender = ensure_signed(origin)?; @@ -56,10 +42,11 @@ decl_module! { Self::deposit_event(RawEvent::Upgraded); } - fn set_key(origin, new: T::AccountId) { + fn set_key(origin, new: ::Source) { // This is a public call, so we ensure that the origin is some signed account. let _sender = ensure_signed(origin)?; ensure!(_sender == Self::key(), "only the current upgrade key can use the upgrade_key module"); + let new = T::Lookup::lookup(new)?; Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index 9e4249d54d077adfaac4829331c73880bbb8e27e..3a581e504a8d951eaad41bb515191a28622b0ada 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -1,12 +1,18 @@ [package] name = "subkey" -version = "0.1.0" +version = "0.2.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] substrate-primitives = { version = "*", path = "../core/primitives" } -rand = "0.4" +rand = "0.6" clap = { version = "~2.32", features = ["yaml"] } +tiny-bip39 = "0.6.0" +rustc-hex = "2.0" +substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39" } +schnorrkel = { git = "https://github.com/w3f/schnorrkel", commit = "d3289df76b8ae6dfb68e733204c5c009df5343a9" } +hex = "0.3" [features] bench = [] diff --git a/subkey/src/cli.yml b/subkey/src/cli.yml index 57cf98bdf2e5024c1364ce1f3e9d3f52a90bcbae..cc131703eb8df23b4d7599b258c5f0971cb71f7a 100644 --- a/subkey/src/cli.yml +++ b/subkey/src/cli.yml @@ -1,20 +1,63 @@ name: subkey author: "Parity Team " -about: A substrate key utility +about: Utility for generating and restoring with Substrate keys +args: + - ed25519: + short: e + long: ed25519 + help: Use Ed25519/BIP39 cryptography + takes_value: false + - sr25519: + short: s + long: sr25519 + help: Use Schnorr/Ristretto x25519/BIP39 cryptography + takes_value: false + - password: + short: p + long: password + takes_value: true + required: false + help: The password for the key subcommands: - generate: about: Generate a random account - - restore: - about: Gets a public key and a SS58 address from the provided seed phrase + - inspect: + about: Gets a public key and a SS58 address from the provided Secret URI args: - - seed: + - uri: index: 1 required: true - help: 32 bytes long seed phrase used to restore the public key. If the provided seed is shorter than that, then - it will be right-padded with 0x20 bytes (ASCII space). If the provided seed is longer than - 32 bytes then seed will be truncated. + help: A Key URI to be inspected. May be a secret seed, secret URI (with derivation paths and password), SS58 or public URI. + - sign: + about: Sign a message, provided on STDIN, with a given (secret) key + args: + - suri: + index: 1 + required: true + help: The secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false + - verify: + about: Verify a signature for a message, provided on STDIN, with a given (public or secret) key + args: + - sig: + index: 1 + required: true + help: Signature, hex-encoded. + - uri: + index: 2 + required: true + help: The public or secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false - vanity: - about: Generate vanity address + about: Generate a seed that provides a vanity address args: - pattern: index: 1 diff --git a/subkey/src/main.rs b/subkey/src/main.rs index 48b9a67654e9af966b9e997224c42dd3a5c5c761..5caf58d45ba14cda8e06f133ce4bd3744e46755c 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,66 +17,204 @@ #![cfg_attr(feature = "bench", feature(test))] #[cfg(feature = "bench")] extern crate test; -extern crate substrate_primitives; -extern crate rand; -#[macro_use] -extern crate clap; +extern crate substrate_bip39; +extern crate rustc_hex; -use rand::{OsRng, Rng}; -use substrate_primitives::{ed25519::Pair, hexdisplay::HexDisplay}; +use std::io::{stdin, Read}; +use clap::load_yaml; +use rand::{RngCore, rngs::OsRng}; +use substrate_bip39::mini_secret_from_entropy; +use bip39::{Mnemonic, Language, MnemonicType}; +use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay, Pair, crypto::Ss58Codec}; +use schnorrkel::keys::MiniSecretKey; mod vanity; -fn print_account(seed: &[u8; 32]) { - let pair = Pair::from_seed(seed); - println!("Seed 0x{} is account:\n Public key (hex): 0x{}\n Address (SS58): {}", - HexDisplay::from(seed), - HexDisplay::from(&pair.public().0), - pair.public().to_ss58check() - ); +trait Crypto { + type Seed: AsRef<[u8]> + AsMut<[u8]> + Sized + Default; + type Pair: Pair; + fn generate_phrase() -> String { + Mnemonic::new(MnemonicType::Words12, Language::English).phrase().to_owned() + } + fn generate_seed() -> Self::Seed { + let mut seed: Self::Seed = Default::default(); + OsRng::new().unwrap().fill_bytes(seed.as_mut()); + seed + } + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed; + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair; + fn pair_from_suri(phrase: &str, password: Option<&str>) -> Self::Pair { + Self::pair_from_seed(&Self::seed_from_phrase(phrase, password)) + } + fn ss58_from_pair(pair: &Self::Pair) -> String; + fn public_from_pair(pair: &Self::Pair) -> Vec; + fn seed_from_pair(_pair: &Self::Pair) -> Option<&Self::Seed> { None } + fn print_from_seed(seed: &Self::Seed) { + let pair = Self::pair_from_seed(seed); + println!("Seed 0x{} is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + HexDisplay::from(&seed.as_ref()), + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + fn print_from_phrase(phrase: &str, password: Option<&str>) { + let seed = Self::seed_from_phrase(phrase, password); + let pair = Self::pair_from_seed(&seed); + println!("Phrase `{}` is account:\n Seed: 0x{}\n Public key (hex): 0x{}\n Address (SS58): {}", + phrase, + HexDisplay::from(&seed.as_ref()), + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + fn print_from_uri(uri: &str, password: Option<&str>) where ::Public: Sized + Ss58Codec + AsRef<[u8]> { + if let Ok(pair) = Self::Pair::from_string(uri, password) { + let seed_text = Self::seed_from_pair(&pair) + .map_or_else(Default::default, |s| format!("\n Seed: 0x{}", HexDisplay::from(&s.as_ref()))); + println!("Secret Key URI `{}` is account:{}\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + seed_text, + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + if let Ok(public) = ::Public::from_string(uri) { + println!("Public Key URI `{}` is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + HexDisplay::from(&public.as_ref()), + public.to_ss58check() + ); + } + } } -fn main() { - let yaml = load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml).get_matches(); +struct Ed25519; + +impl Crypto for Ed25519 { + type Seed = [u8; 32]; + type Pair = ed25519::Pair; + + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { + Sr25519::seed_from_phrase(phrase, password) + } + fn pair_from_suri(suri: &str, password_override: Option<&str>) -> Self::Pair { + ed25519::Pair::from_legacy_string(suri, password_override) + } + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { ed25519::Pair::from_seed(seed.clone()) } + fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } + fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } + fn seed_from_pair(pair: &Self::Pair) -> Option<&Self::Seed> { Some(pair.seed()) } +} + +struct Sr25519; + +impl Crypto for Sr25519 { + type Seed = [u8; 32]; + type Pair = sr25519::Pair; + + fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { + mini_secret_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .unwrap_or_else(|_| + panic!("Phrase is not a valid BIP-39 phrase: \n {}", phrase) + ) + .entropy(), + password.unwrap_or("") + ) + .expect("32 bytes can always build a key; qed") + .to_bytes() + } + + fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { + sr25519::Pair::from_string(suri, password).expect("Invalid phrase") + } + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { + MiniSecretKey::from_bytes(seed) + .expect("32 bytes can always build a key; qed") + .into() + } + fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } + fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } +} + +fn execute>(matches: clap::ArgMatches) where + <::Pair as Pair>::Signature: AsRef<[u8]> + AsMut<[u8]> + Default, + <::Pair as Pair>::Public: Sized + AsRef<[u8]> + Ss58Codec + AsRef<<::Pair as Pair>::Public>, +{ + let password = matches.value_of("password"); match matches.subcommand() { ("generate", Some(_matches)) => { - let mut seed = [0u8; 32]; - OsRng::new().unwrap().fill_bytes(&mut seed[..]); - print_account(&seed); - } + // create a new randomly generated mnemonic phrase + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + C::print_from_phrase(mnemonic.phrase(), password); + }, ("vanity", Some(matches)) => { let desired: String = matches.value_of("pattern").map(str::to_string).unwrap_or_default(); - let key = vanity::generate_key(&desired).expect("Key generation failed"); - println!("Found account with score {}%", key.score); - print_account(&key.seed); + let key = vanity::generate_key::(&desired).expect("Key generation failed"); + C::print_from_seed(&key.seed); } - ("restore", Some(matches)) => { - // This subcommand is probably obsolete, see - // https://github.com/paritytech/substrate/issues/1063 - - let mut raw_seed = matches.value_of("seed") - .map(str::as_bytes) - .expect("seed parameter is required; thus it can't be None; qed"); - - if raw_seed.len() > 32 { - raw_seed = &raw_seed[..32]; - println!("seed is too long and will be truncated to: {}", HexDisplay::from(&raw_seed)); - } - - // Copy the raw_seed into a buffer that already contains ' ' 0x20. - // This will effectively get us padding for seeds shorter than 32. - let mut seed = [' ' as u8; 32]; - let len = raw_seed.len().min(32); - seed[..len].copy_from_slice(&raw_seed[..len]); - print_account(&seed); + ("inspect", Some(matches)) => { + // TODO: Accept public key with derivation path. + let uri = matches.value_of("uri") + .expect("URI parameter is required; thus it can't be None; qed"); + C::print_from_uri(uri, password); }, + ("sign", Some(matches)) => { + let suri = matches.value_of("suri") + .expect("secret URI parameter is required; thus it can't be None; qed"); + let pair = C::pair_from_suri(suri, password); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + let sig = pair.sign(&message); + println!("{}", hex::encode(&sig)); + } + ("verify", Some(matches)) => { + let sig_data = matches.value_of("sig") + .expect("signature parameter is required; thus it can't be None; qed"); + let mut sig = <::Pair as Pair>::Signature::default(); + let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); + if sig_data.len() != sig.as_ref().len() { + panic!("signature is an invalid length. {} bytes is not the expected value of {} bytes", sig_data.len(), sig.as_ref().len()); + } + sig.as_mut().copy_from_slice(&sig_data); + let uri = matches.value_of("uri") + .expect("public uri parameter is required; thus it can't be None; qed"); + let pubkey = <::Pair as Pair>::Public::from_string(uri).ok().or_else(|| + ::Pair::from_string(uri, password).ok().map(|p| p.public()) + ).expect("Invalid URI; expecting either a secret URI or a public URI."); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + if <::Pair as Pair>::verify(&sig, &message, &pubkey) { + println!("Signature verifies correctly.") + } else { + println!("Signature invalid.") + } + } _ => print_usage(&matches), } } +fn main() { + let yaml = load_yaml!("cli.yml"); + let matches = clap::App::from_yaml(yaml) + .version(env!("CARGO_PKG_VERSION")) + .get_matches(); + + if matches.is_present("ed25519") { + execute::(matches) + } else { + execute::(matches) + } +} + fn print_usage(matches: &clap::ArgMatches) { println!("{}", matches.usage()); } diff --git a/subkey/src/vanity.rs b/subkey/src/vanity.rs index 9eb621cc55116b1cb6e3a69a158dd2db0f4b10e7..785eb95aa5b203ac5c53e62abea30b6c090259ae 100644 --- a/subkey/src/vanity.rs +++ b/subkey/src/vanity.rs @@ -1,4 +1,4 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. +// Copyright 2018-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use rand::{OsRng, Rng}; -use substrate_primitives::ed25519::Pair; +use rand::{rngs::OsRng, RngCore}; +use super::Crypto; fn good_waypoint(done: u64) -> u64 { match done { @@ -38,9 +38,9 @@ fn next_seed(mut seed: [u8; 32]) -> [u8; 32] { /// A structure used to carry both Pair and seed. /// This should usually NOT been used. If unsure, use Pair. -pub struct KeyPair { - pub pair: Pair, - pub seed: [u8; 32], +pub(super) struct KeyPair { + pub pair: C::Pair, + pub seed: C::Seed, pub score: usize, } @@ -57,7 +57,7 @@ fn calculate_score(_desired: &str, key: &str) -> usize { 0 } -pub fn generate_key(desired: &str) -> Result { +pub(super) fn generate_key>(desired: &str) -> Result, &str> { if desired.is_empty() { return Err("Pattern must not be empty"); } @@ -77,8 +77,8 @@ pub fn generate_key(desired: &str) -> Result { OsRng::new().unwrap().fill_bytes(&mut seed[..]); } - let p = Pair::from_seed(&seed); - let ss58 = p.public().to_ss58check(); + let p = C::pair_from_seed(&seed); + let ss58 = C::ss58_from_pair(&p); let score = calculate_score(&desired, &ss58); if score > best || desired.len() < 2 { best = score; @@ -104,12 +104,14 @@ pub fn generate_key(desired: &str) -> Result { #[cfg(test)] mod tests { use super::*; + use super::super::Ed25519; + use substrate_primitives::Pair; #[cfg(feature = "bench")] use test::Bencher; #[test] fn test_generation_with_single_char() { - assert!(generate_key("j").unwrap().pair.public().to_ss58check().contains("j")); + assert!(generate_key::("j").unwrap().pair.public().to_ss58check().contains("j")); } #[test] diff --git a/test-utils/chain-spec-builder/Cargo.lock b/test-utils/chain-spec-builder/Cargo.lock index bcad2f12d2678a1b472deddd77233a154304a3af..feccfa14ef41cbdf554d413701c37bbe1349cfb1 100644 --- a/test-utils/chain-spec-builder/Cargo.lock +++ b/test-utils/chain-spec-builder/Cargo.lock @@ -40,12 +40,11 @@ dependencies = [ [[package]] name = "aio-limited" version = "0.1.0" -source = "git+https://github.com/paritytech/aio-limited.git#a7c0bd6944902b1c9fb2bcf4f8fe1412c824b5b9" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -118,7 +117,7 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -132,15 +131,6 @@ name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "base64" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "base64" version = "0.9.3" @@ -161,15 +151,16 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.37.4" +version = "0.43.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -190,12 +181,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -207,6 +199,15 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-buffer" version = "0.3.3" @@ -216,6 +217,17 @@ dependencies = [ "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-cipher-trait" version = "0.5.3" @@ -224,6 +236,14 @@ dependencies = [ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-padding" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bs58" version = "0.2.2" @@ -234,11 +254,21 @@ name = "byte-tools" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.7" @@ -255,7 +285,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -263,10 +293,10 @@ dependencies = [ [[package]] name = "cexpr" -version = "0.2.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -284,15 +314,6 @@ dependencies = [ "substrate-service 0.3.0", ] -[[package]] -name = "chashmap" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "chrono" version = "0.4.6" @@ -305,7 +326,7 @@ dependencies = [ [[package]] name = "clang-sys" -version = "0.23.0" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -333,7 +354,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -371,6 +392,15 @@ name = "crossbeam" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.2.0" @@ -397,7 +427,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -411,7 +441,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -429,6 +459,15 @@ name = "crossbeam-utils" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crunchy" version = "0.1.6" @@ -441,11 +480,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crypto-mac" -version = "0.5.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,6 +496,15 @@ dependencies = [ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ctr" version = "0.1.1" @@ -466,6 +514,15 @@ dependencies = [ "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cuckoofilter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "curve25519-dalek" version = "0.20.0" @@ -485,16 +542,11 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "datastore" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "digest" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -505,11 +557,28 @@ dependencies = [ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ed25519-dalek" version = "0.8.1" @@ -538,16 +607,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.5.13" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -570,17 +630,6 @@ dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "eth-secp256k1" -version = "0.5.7" -source = "git+https://github.com/paritytech/rust-secp256k1#ccc06e7480148b723eb44ac56cf4d20eec380b6f" -dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "etrace" version = "1.1.1" @@ -615,15 +664,15 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -662,7 +711,7 @@ name = "fs-swap" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -701,6 +750,15 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "generic-array" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "generic-array" version = "0.9.0" @@ -709,6 +767,14 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.2.11" @@ -745,15 +811,15 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -794,6 +860,16 @@ dependencies = [ "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hmac" version = "0.6.3" @@ -803,6 +879,16 @@ dependencies = [ "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hmac-drbg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http" version = "0.1.13" @@ -880,6 +966,23 @@ dependencies = [ "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "impl-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.0.2" @@ -911,8 +1014,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -921,48 +1024,49 @@ dependencies = [ "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-derive" +version = "10.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-http-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "jsonrpc-macros" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" -dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-pubsub" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -972,16 +1076,16 @@ dependencies = [ [[package]] name = "jsonrpc-ws-server" -version = "9.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git#2ed142d55662155b0dc76b9b5d2732300f265dd6" +version = "10.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)", ] [[package]] @@ -996,26 +1100,26 @@ dependencies = [ [[package]] name = "kvdb" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", ] [[package]] name = "kvdb-rocksdb" version = "0.1.4" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rocksdb 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1030,11 +1134,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "lazycell" @@ -1051,36 +1152,36 @@ name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-dns 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-floodsub 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-kad 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-mplex 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ratelimit 0.1.1 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-relay 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-secio 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-tcp-transport 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-transport-timeout 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-uds 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-websocket 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-yamux 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ratelimit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1088,21 +1189,21 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1110,34 +1211,41 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libp2p-core-derive" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libp2p-dns" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-floodsub" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1146,18 +1254,18 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1167,77 +1275,81 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-mplex" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-mdns" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-peerstore" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-mplex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ping" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,139 +1357,138 @@ dependencies = [ ] [[package]] -name = "libp2p-ratelimit" -version = "0.1.1" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-plaintext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-relay" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-ratelimit" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-secio" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes-ctr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "asn1_der 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519-dalek 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libp2p-tcp-transport" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +name = "libp2p-tcp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tk-listen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "libp2p-transport-timeout" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "libp2p-uds" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-websocket" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-yamux" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.1.0 (git+https://github.com/paritytech/yamux)", + "yamux 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "librocksdb-sys" -version = "5.14.2" +version = "5.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libsecp256k1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "linked-hash-map" version = "0.5.1" @@ -1408,6 +1519,14 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lru-cache" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "make-cmd" version = "0.1.0" @@ -1428,7 +1547,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1436,14 +1555,6 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.1.1" @@ -1461,10 +1572,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memory-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1531,36 +1642,10 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multiaddr" -version = "0.3.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "multihash" -version = "0.8.1-pre" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" -dependencies = [ - "blake2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "multistream-select" -version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1584,7 +1669,7 @@ name = "native-tls" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1610,7 +1695,6 @@ dependencies = [ name = "node-cli" version = "0.1.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1618,17 +1702,17 @@ dependencies = [ "node-executor 0.1.0", "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-basic-authorship 0.1.0", "substrate-cli 0.3.0", "substrate-client 0.1.0", "substrate-consensus-aura 0.1.0", - "substrate-consensus-common 0.1.0", "substrate-finality-grandpa 0.1.0", + "substrate-inherents 0.1.0", "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", @@ -1644,21 +1728,21 @@ dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", "node-runtime 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "substrate-executor 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", @@ -1671,15 +1755,17 @@ name = "node-runtime" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 0.1.0", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", + "srml-aura 0.1.0", "srml-balances 0.1.0", "srml-consensus 0.1.0", "srml-contract 0.1.0", @@ -1687,15 +1773,17 @@ dependencies = [ "srml-democracy 0.1.0", "srml-executive 0.1.0", "srml-grandpa 0.1.0", + "srml-indices 0.1.0", "srml-session 0.1.0", "srml-staking 0.1.0", + "srml-sudo 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "srml-timestamp 0.1.0", "srml-treasury 0.1.0", "srml-upgrade-key 0.1.0", "substrate-client 0.1.0", - "substrate-finality-grandpa-primitives 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", ] @@ -1712,10 +1800,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nom" -version = "3.2.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1748,11 +1837,21 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "once_cell" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "opaque-debug" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "opaque-debug" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" version = "0.10.15" @@ -1761,7 +1860,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1776,17 +1875,12 @@ name = "openssl-sys" version = "0.9.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.3.3" @@ -1798,11 +1892,11 @@ dependencies = [ [[package]] name = "parity-bytes" version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6#616b40150ded71f57f650067fcbc5c99d7c343e6" +source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" [[package]] name = "parity-codec" -version = "2.1.5" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1811,25 +1905,52 @@ dependencies = [ [[package]] name = "parity-codec-derive" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-crypto" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-multiaddr" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parity-wasm" version = "0.31.3" @@ -1839,13 +1960,20 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.3.8" +name = "parity-ws" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1875,6 +2003,15 @@ dependencies = [ "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.2.14" @@ -1898,6 +2035,38 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -1913,6 +2082,17 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "primitive-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack" version = "0.4.1" @@ -1921,6 +2101,16 @@ dependencies = [ "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack-impl" version = "0.4.1" @@ -1936,7 +2126,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.20" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1949,7 +2139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pwasm-utils" -version = "0.3.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1977,10 +2167,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2088,14 +2278,6 @@ dependencies = [ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rayon" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rayon" version = "1.0.2" @@ -2112,7 +2294,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2130,18 +2312,6 @@ dependencies = [ "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "1.0.5" @@ -2154,14 +2324,6 @@ dependencies = [ "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex-syntax" version = "0.6.2" @@ -2180,23 +2342,22 @@ dependencies = [ [[package]] name = "ring" -version = "0.12.1" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocksdb" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "librocksdb-sys 5.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2216,11 +2377,6 @@ name = "rustc-demangle" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-hex" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc-hex" version = "2.0.1" @@ -2242,7 +2398,7 @@ dependencies = [ [[package]] name = "rw-stream-sink" version = "0.1.0" -source = "git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5#d961e656a74d1bab5366d371a06f9e10d5f4a6c5" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2262,11 +2418,6 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "safemem" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "safemem" version = "0.3.0" @@ -2277,7 +2428,7 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2291,6 +2442,15 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "secp256k1" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "security-framework" version = "0.2.1" @@ -2334,8 +2494,8 @@ name = "serde_derive" version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2351,28 +2511,41 @@ dependencies = [ [[package]] name = "sha1" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "sha1" -version = "0.5.0" +name = "sha2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "sha1" -version = "0.6.0" +name = "sha2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "sha2" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2384,11 +2557,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "slab" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "slab" version = "0.4.1" @@ -2442,8 +2610,9 @@ dependencies = [ name = "sr-api-macros" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2452,13 +2621,15 @@ name = "sr-io" version = "0.1.0" dependencies = [ "environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2468,8 +2639,8 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2481,11 +2652,11 @@ dependencies = [ name = "sr-sandbox" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "substrate-primitives 0.1.0", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2499,30 +2670,45 @@ dependencies = [ name = "sr-version" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", ] +[[package]] +name = "srml-aura" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-staking 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "srml-timestamp 0.1.0", + "substrate-inherents 0.1.0", +] + [[package]] name = "srml-balances" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", "substrate-keyring 0.1.0", - "substrate-primitives 0.1.0", ] [[package]] @@ -2530,14 +2716,14 @@ name = "srml-consensus" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -2545,10 +2731,10 @@ dependencies = [ name = "srml-contract" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -2565,8 +2751,8 @@ name = "srml-council" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2584,8 +2770,8 @@ name = "srml-democracy" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2602,8 +2788,8 @@ name = "srml-executive" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -2617,8 +2803,8 @@ name = "srml-grandpa" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2631,12 +2817,30 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "srml-indices" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-system 0.1.0", + "substrate-keyring 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-metadata" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", @@ -2648,8 +2852,8 @@ name = "srml-session" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2667,8 +2871,8 @@ name = "srml-staking" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2684,19 +2888,71 @@ dependencies = [ "substrate-primitives 0.1.0", ] +[[package]] +name = "srml-sudo" +version = "0.1.0" +dependencies = [ + "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-std 0.1.0", + "srml-support 0.1.0", + "srml-support-procedural 0.1.0", + "srml-system 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "srml-support" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-metadata 0.1.0", + "srml-support-procedural 0.1.0", + "substrate-inherents 0.1.0", +] + +[[package]] +name = "srml-support-procedural" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-api-macros 0.1.0", + "srml-support-procedural-tools 0.1.0", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-support-procedural-tools" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "srml-support-procedural-tools-derive 0.1.0", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-support-procedural-tools-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2704,8 +2960,8 @@ name = "srml-system" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", @@ -2720,7 +2976,8 @@ name = "srml-timestamp" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -2728,6 +2985,7 @@ dependencies = [ "srml-consensus 0.1.0", "srml-support 0.1.0", "srml-system 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", ] @@ -2736,8 +2994,8 @@ name = "srml-treasury" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", @@ -2753,14 +3011,15 @@ name = "srml-upgrade-key" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", + "srml-support-procedural 0.1.0", "srml-system 0.1.0", "substrate-primitives 0.1.0", ] @@ -2775,11 +3034,6 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "stdweb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "stdweb" version = "0.4.10" @@ -2797,8 +3051,8 @@ name = "stdweb-derive" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2810,8 +3064,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base-x 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2857,11 +3111,26 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-basic-authorship" +version = "0.1.0" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", + "substrate-transaction-pool 0.1.0", +] + [[package]] name = "substrate-cli" version = "0.3.0" @@ -2869,14 +3138,13 @@ dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2885,10 +3153,11 @@ dependencies = [ "structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 0.1.0", "substrate-network 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-service 0.3.0", "substrate-telemetry 0.3.0", - "sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2900,13 +3169,14 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "sr-primitives 0.1.0", @@ -2914,6 +3184,7 @@ dependencies = [ "sr-version 0.1.0", "substrate-consensus-common 0.1.0", "substrate-executor 0.1.0", + "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", @@ -2925,13 +3196,14 @@ dependencies = [ name = "substrate-client-db" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", - "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-executor 0.1.0", @@ -2947,17 +3219,51 @@ version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", + "srml-aura 0.1.0", "srml-consensus 0.1.0", "srml-support 0.1.0", "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-aura-slots 0.1.0", "substrate-consensus-common 0.1.0", - "substrate-network 0.1.0", + "substrate-inherents 0.1.0", + "substrate-primitives 0.1.0", + "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-consensus-aura-primitives" +version = "0.1.0" +dependencies = [ + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", + "sr-primitives 0.1.0", + "sr-version 0.1.0", + "srml-support 0.1.0", + "substrate-client 0.1.0", + "substrate-primitives 0.1.0", +] + +[[package]] +name = "substrate-consensus-aura-slots" +version = "0.1.0" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "substrate-client 0.1.0", + "substrate-consensus-aura-primitives 0.1.0", + "substrate-consensus-common 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2968,10 +3274,13 @@ version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", + "substrate-inherents 0.1.0", "substrate-primitives 0.1.0", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2982,31 +3291,34 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-version 0.1.0", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", "substrate-trie 0.4.0", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-finality-grandpa" version = "0.1.0" dependencies = [ - "finality-grandpa 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "finality-grandpa 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", @@ -3022,20 +3334,31 @@ dependencies = [ name = "substrate-finality-grandpa-primitives" version = "0.1.0" dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "substrate-client 0.1.0", "substrate-primitives 0.1.0", ] +[[package]] +name = "substrate-inherents" +version = "0.1.0" +dependencies = [ + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", + "sr-std 0.1.0", +] + [[package]] name = "substrate-keyring" version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3045,13 +3368,13 @@ version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", - "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3059,23 +3382,22 @@ name = "substrate-network" version = "0.1.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-consensus-common 0.1.0", - "substrate-keyring 0.1.0", "substrate-network-libp2p 0.1.0", "substrate-primitives 0.1.0", - "substrate-test-client 0.1.0", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3087,18 +3409,28 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-panic-handler" +version = "0.1.0" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3108,22 +3440,21 @@ dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", "twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3131,17 +3462,20 @@ name = "substrate-rpc" version = "0.1.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", "substrate-executor 0.1.0", + "substrate-network 0.1.0", "substrate-primitives 0.1.0", "substrate-transaction-pool 0.1.0", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3151,9 +3485,9 @@ dependencies = [ name = "substrate-rpc-servers" version = "0.1.0" dependencies = [ - "jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", - "jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)", + "jsonrpc-http-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", @@ -3175,10 +3509,10 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3192,7 +3526,6 @@ dependencies = [ "substrate-keystore 0.1.0", "substrate-network 0.1.0", "substrate-primitives 0.1.0", - "substrate-rpc 0.1.0", "substrate-rpc-servers 0.1.0", "substrate-telemetry 0.3.0", "substrate-transaction-pool 0.1.0", @@ -3205,9 +3538,9 @@ name = "substrate-state-db" version = "0.1.0" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", ] @@ -3215,25 +3548,26 @@ dependencies = [ name = "substrate-state-machine" version = "0.1.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-panic-handler 0.1.0", "substrate-primitives 0.1.0", "substrate-trie 0.4.0", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-telemetry" version = "0.3.0" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3241,41 +3575,6 @@ dependencies = [ "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "substrate-test-client" -version = "0.1.0" -dependencies = [ - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 0.1.0", - "substrate-client 0.1.0", - "substrate-consensus-common 0.1.0", - "substrate-executor 0.1.0", - "substrate-keyring 0.1.0", - "substrate-primitives 0.1.0", - "substrate-state-machine 0.1.0", - "substrate-test-runtime 0.1.0", -] - -[[package]] -name = "substrate-test-runtime" -version = "0.1.0" -dependencies = [ - "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 0.1.0", - "sr-primitives 0.1.0", - "sr-std 0.1.0", - "sr-version 0.1.0", - "srml-support 0.1.0", - "substrate-client 0.1.0", - "substrate-keyring 0.1.0", - "substrate-primitives 0.1.0", -] - [[package]] name = "substrate-transaction-graph" version = "0.1.0" @@ -3283,7 +3582,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", @@ -3296,8 +3595,8 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "substrate-client 0.1.0", "substrate-primitives 0.1.0", @@ -3308,46 +3607,36 @@ dependencies = [ name = "substrate-trie" version = "0.4.0" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "memory-db 0.9.0 (git+https://github.com/paritytech/trie)", - "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.9.0 (git+https://github.com/paritytech/trie)", - "trie-root 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "subtle" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "subtle" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "syn" -version = "0.14.9" +name = "subtle" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "syn" version = "0.15.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sysinfo" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3405,22 +3694,12 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3512,12 +3791,12 @@ dependencies = [ [[package]] name = "tokio-dns-unofficial" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3556,7 +3835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3651,21 +3930,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "trie-db" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.9.0" -source = "git+https://github.com/paritytech/trie#2616db2a2529098949e5d39aa06dd4e502a9e5f7" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.9.0 (git+https://github.com/paritytech/trie)", + "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3708,11 +3987,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3768,14 +4048,6 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unsigned-varint" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unsigned-varint" version = "0.2.1" @@ -3787,7 +4059,7 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3837,7 +4109,7 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3920,22 +4192,6 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ws" -version = "0.7.5" -source = "git+https://github.com/tomusdrw/ws-rs#f12d19c4c19422fc79af28a3181f598bc07ecd1e" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ws" version = "0.7.9" @@ -3975,8 +4231,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "yamux" -version = "0.1.0" -source = "git+https://github.com/paritytech/yamux#966f2730f7a32150f282eef29fd2aecb14d7b9fa" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3984,6 +4240,7 @@ dependencies = [ "nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3993,7 +4250,7 @@ dependencies = [ "checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" "checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" -"checksum aio-limited 0.1.0 (git+https://github.com/paritytech/aio-limited.git)" = "" +"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" @@ -4004,27 +4261,30 @@ dependencies = [ "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum base-x 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5cda5d0f5584d129112ad8bf4775b9fd2b9f1e30738c7b1a25314ba2244d6a51" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" -"checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221" +"checksum bindgen 0.43.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d52d263eacd15d26cbcf215d254b410bd58212aaa2d3c453a04b2d3b3adcf41" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73b77e29dbd0115e43938be2d5128ecf81c0353e00acaa65339a1242586951d9" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +"checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da" "checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" +"checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0ce55bd354b095246fc34caf4e9e242f5297a7fd938b090cadfea6eee614aa62" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" +"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" +"checksum cexpr 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "644d693ecfa91955ed32dcc7eda4914e1be97a641fb6f0645a37348e20b230da" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47e651a8c1eb0cbbaa730f705e2531e75276c6f2bbe2eb12662cfd305213dff8" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2" +"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -4032,36 +4292,40 @@ dependencies = [ "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3486aefc4c0487b9cb52372c97df0a48b8c249514af1ee99703bf70d2f2ceda1" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2" -"checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958" +"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" "checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum ctr 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b669fcb8e20124db86dbd9b01e74ec0e9e420e65381311ce5249864fc7ff0c0" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" "checksum curve25519-dalek 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eacf6ff1b911e3170a8c400b402e10c86dc3cb166bd69034ebbc2b785fea4c2" "checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e" -"checksum datastore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" +"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum ed25519-dalek 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cd66d8a16ef71c23cf5eeb2140d8d3cd293457c6c7fd6804b593397a933fcf1e" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum environmental 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db746025e3ea695bfa0ae744dbacd5fcfc8db51b9760cf8bd0ab69708bb93c49" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum etrace 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f17311e68ea07046ee809b8513f6c259518bc10173681d98c21f8c3926f56f40" "checksum exit-future 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9aa7b56cef68c4182db7212dece19cc9f6e2916cf9412e57e6cea53ec02f316d" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" -"checksum finality-grandpa 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a1dffe3c9d4c59d964f25cea31880e56c20414cdae7efe2269411238f850ad39" +"checksum finality-grandpa 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d415e902db2b87bd5a7df7a2b2de97a4566727a23b95ff39e1bfec25a66d4d1c" "checksum fixed-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a557e80084b05c32b455963ff565a9de6f2866da023d6671705c6aff6f65e01c" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -4072,123 +4336,138 @@ dependencies = [ "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd33bafe2e6370e6c8eb0cf1b8c5f93390b90acde7e9b03723f166b28b648ed" -"checksum hash-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum hash256-std-hasher 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +"checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" +"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" +"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "24f58e8c2d8e886055c3ead7b28793e1455270b5fb39650984c224bc538ba581" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c" "checksum hyper 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)" = "95ffee0d1d30de4313fdaaa485891ce924991d45bbc18adfc8ac5b1639e62fbb" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum jsonrpc-core 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-http-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-macros 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-pubsub 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-server-utils 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" -"checksum jsonrpc-ws-server 9.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "" +"checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" +"checksum jsonrpc-derive 10.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c14be84e86c75935be83a34c6765bf31f97ed6c9163bb0b83007190e9703940a" +"checksum jsonrpc-http-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99e1ce36c7cc9dcab398024d76849ab2cb917ee812653bce6f74fc9eb7c82d16" +"checksum jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56608ed54b1b2a69f4357cb8bdfbcbd99fe1179383c03a09bb428931bd35f592" +"checksum jsonrpc-server-utils 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5521613b31ea22d36d9f95ad642058dccec846a94ed8690957652d479f620707" +"checksum jsonrpc-ws-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20b8333a5a6e6ccbcf5c90f90919de557cba4929efa164e9bd0e8e497eb20e46" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" +"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum libp2p 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-core 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-dns 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-floodsub 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-identify 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-kad 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-mplex 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-peerstore 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-ping 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-ratelimit 0.1.1 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-relay 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-secio 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-tcp-transport 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-transport-timeout 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-uds 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-websocket 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum libp2p-yamux 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum librocksdb-sys 5.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "474d805d72e23a06310fa5201dfe182dc4b80ab1f18bb2823c1ac17ff9dcbaa2" +"checksum libp2p 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2cce57e82d0decdf5464e4e179a319ee14c218c330bb017f62453f4ab74842" +"checksum libp2p-core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "26977e332e88c070353864d5ed72b6e1175fc1c63af5709b5174877836a229b6" +"checksum libp2p-core-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a88f076f3f60f3f407ce4fc0f620e3592125461bec5aa4895316e1f0414b3ea" +"checksum libp2p-dns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f7ad92f9711efece48bb7ce30e3f1e662cd3524dc5d9f96b8f68b6e4e7cde96" +"checksum libp2p-floodsub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4feda0ff3afcf84dfee9ea088835293829d199a34491d7f0990a4ccfd627816c" +"checksum libp2p-identify 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "548f9180101bd5846f4f60e060a00032ba3671a77fc735c48a85b7d1016d28ef" +"checksum libp2p-kad 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91c28bf179a22fd1bfa3bad28ed86b8657ed2d193b76caa6f632ea83356d3a40" +"checksum libp2p-mdns 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1bbcb82063545605abf697967d919d418b1725f7d3688973fa26c98f81e8cda8" +"checksum libp2p-mplex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9406ea58ce4fef47820f7d2d6aa62b7e42b4972c30cc87de577d4da40852d4b1" +"checksum libp2p-ping 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1ca7b60c2edb0cae7f9db56fbe6c21ca6960e96ec92cd1ed265ac06db24a1fe" +"checksum libp2p-plaintext 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bdbdd4700d5edea10214e4733ab5ac5be87862bac8a9b259c987bc9c15004" +"checksum libp2p-ratelimit 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3001ea6afed5ccd1e5934715aa388b60b23e7587117db36b89d697e8ea43ff3" +"checksum libp2p-secio 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc2bee2dce0d0d054d81447b06f7e923f1a98e6b240e42674e0fdf2e4a4924f" +"checksum libp2p-tcp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcb2bcb9402f5fe42441dd4558306ff83a28624f67c6066bdbaa98928c180e3" +"checksum libp2p-uds 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3e88ac8f419f8d9487aaee9ef8785f592b37d78067c6764fe0adc1874a72c6c" +"checksum libp2p-websocket 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b60b65b8d7053220a0c78a09eda0a162db410067639d2b24432a9f1dc06230" +"checksum libp2p-yamux 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71b4fd69a1c038152d017366d759177e2580fb4fbb56ce65429a642e011a07b1" +"checksum librocksdb-sys 5.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9024327233e7fac7982440f73301c00046d438c5b1011e8f4e394226ce19007" +"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3" "checksum mashup 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d82b34c7fb11bb41719465c060589e291d505ca4735ea30016a91f6fc79c3b" "checksum mashup-impl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "aa607bfb674b4efb310512527d64266b065de3f894fc52f84efcbf7eaa5965fb" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multiaddr 0.3.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum multihash 0.8.1-pre (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" -"checksum multistream-select 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" +"checksum multistream-select 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "886fe7ba983a194afdd9074323171c8e313b2c145561da69464d5443f1a3d121" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum nohash-hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27593c72432b8cec9ae79e92792a73c38341064d525b6b612a9fccf8b7d17407" -"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" +"checksum nom 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b30adc557058ce00c9d0d7cb3c6e0b5bc6f36e2e2eabe74b0ba726d194abd588" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" +"checksum once_cell 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "53075ac5dbd2798cfbcf9f710f2737de031d8076c192d8fe66fb23f639ccbdf4" "checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" +"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" "checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106" -"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=616b40150ded71f57f650067fcbc5c99d7c343e6)" = "" -"checksum parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dca389ea5e1632c89b2ce54f7e2b4a8a8c9d278042222a91e0bf95451218cb4c" -"checksum parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa42c2cb493b60b12c75b26e8c94cb734af4df4d7f2cc229dc04c1953dac189" -"checksum parity-crypto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1117f6574377d21309bfa1f7d69ff734120685d92b02c3f362b122585758840" +"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88f69984317b736dceac3baa86600fc089856f69b44b07231f39b5648b02bcd4" +"checksum parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a58ba33211595f92cc2163ac583961d3dc767e656934146636b05256cc9acd7f" +"checksum parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8adf489acb31f1922db0ce43803b6f48a425241a8473611be3cc625a8e4a4c47" +"checksum parity-multiaddr 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a8e5d637787fe097ec1bfca2aa3eb687396518003df991c6c7216d86682d5ff" +"checksum parity-multihash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8eab0287ccde7821e337a124dc5a4f1d6e4c25d10cc91e3f9361615dd95076" "checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9" +"checksum parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fec5048fba72a2e01baeb0d08089db79aead4b57e2443df172fb1840075a233" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edb92f1ebfc177432c03287b15d48c202e6e2c95993a7af3ba039abb43b1492e" "checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" -"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum protobuf 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "671a9cce836bd3635b40b2b0a72783481755ee988c493891f4e974b45264cc9d" -"checksum pwasm-utils 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd695333cfae6e9dbe2703a6d040e252b57a6fc3b9a65c712615ac042b2e0c5" +"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" "checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5829244f52738cfee93b3a165c1911388675be000c888d2fae620dee8fa5b" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" @@ -4200,32 +4479,28 @@ dependencies = [ "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" "checksum rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df7a791f788cb4c516f0e091301a29c2b71ef680db5e644a7d68835c8ae6dbfa" "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" "checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" -"checksum rocksdb 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39be726e556e6f21d54d21cdf1be9f6df30c0411a5856c1abf3f4bb12498f2ed" +"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" +"checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" -"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rw-stream-sink 0.1.0 (git+https://github.com/libp2p/rust-libp2p?rev=d961e656a74d1bab5366d371a06f9e10d5f4a6c5)" = "" +"checksum rw-stream-sink 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "108ad7c3d65ba866ec50a224b7b3b0cb6c682c3d805015cea859d491232346a5" "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" "checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" "checksum security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab01dfbe5756785b5b4d46e0289e5a18071dfa9a7c2b24213ea00b9ef9b665bf" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" @@ -4233,12 +4508,11 @@ dependencies = [ "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" "checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" -"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" -"checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" "checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" @@ -4247,7 +4521,6 @@ dependencies = [ "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum stdweb 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" "checksum stdweb 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "22203527a18dc1c5c83bbd247fb005f5877d040783b6626571d6b7ed7a6f5e75" "checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" "checksum stdweb-internal-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbc9155af9606d44c740197d7d6672b49c4ee93a176c7cecde8b49322677604" @@ -4257,18 +4530,16 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum structopt 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "41c4a2479a078509940d82773d90ff824a8c89533ab3b59cd3ce8b0c0e369c02" "checksum structopt-derive 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5352090cfae7a2c85e1a31146268b53396106c88ca5d6ccee2e3fae83b6e35c2" -"checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" -"checksum sysinfo 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "11c5f6e8a7a7146f26ffed9a5ff8bab2706f1ac8a413a415e1d211b819d5c24d" +"checksum sysinfo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c747a1fbe091faa7bf76c19f40099f9f12495384c811485d81cf3d60c0eae62" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" @@ -4277,7 +4548,7 @@ dependencies = [ "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f90fcd90952f0a496d438a976afba8e5c205fb12123f813d8ab3aa1c8436638c" -"checksum tokio-dns-unofficial 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb9bf62ca2c53bf2f2faec3e48a98b6d8c9577c27011cb0203a4beacdc8ab328" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" "checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" "checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" "checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" @@ -4289,15 +4560,15 @@ dependencies = [ "checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" "checksum tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df195376b43508f01570bacc73e13a1de0854dc59e79d1ec09913e8db6dd2a70" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-db 0.9.0 (git+https://github.com/paritytech/trie)" = "" -"checksum trie-root 0.9.0 (git+https://github.com/paritytech/trie)" = "" +"checksum trie-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" +"checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twofish 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eef327f05b0d0ec1b9d7d119d8f4d9f602ceee37e0540aff8071e8e66c2e22e" "checksum twox-hash 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f85be565a110ed72ed7048cf56570db04ce0a592c98aa59b7dacde3e5718750" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f8bfa9ff0cadcd210129ad9d2c5f145c13e9ced3d3e5d948a6213487d52444" -"checksum uint 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +"checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" @@ -4306,9 +4577,8 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum unsigned-varint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c1441164e5da61f00acd15f5a9e61939693c2c6e8b9fae36a220b82de7e212" "checksum unsigned-varint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8abc4b7d8158bdfbbaaccc35331ed3c30c2673e99000d7ae665a2eb6576f4" -"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" @@ -4316,7 +4586,7 @@ dependencies = [ "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" -"checksum wasmi 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a60b9508cff2b7c27ed41200dd668806280740fadc8c88440e9c88625e84f1a" +"checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" "checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" @@ -4326,9 +4596,8 @@ dependencies = [ "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.1.0 (git+https://github.com/paritytech/yamux)" = "" +"checksum yamux 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e25561b512df3c287cf52404cab0b07ea43d095cb96230e9e2cb635db72d75f0" diff --git a/test-utils/chain-spec-builder/Cargo.toml b/test-utils/chain-spec-builder/Cargo.toml index 7bd99e53aacadad60efe93419fdbdba1f9dcc51d..79290463da09965c67ace75f75cb72b8f5cbe027 100644 --- a/test-utils/chain-spec-builder/Cargo.toml +++ b/test-utils/chain-spec-builder/Cargo.toml @@ -2,6 +2,7 @@ name = "chain-spec-builder" version = "0.1.0" authors = ["haydn dufrene "] +edition = "2018" [dependencies] clap = { version = "~2.32", features = ["yaml"] } diff --git a/test-utils/chain-spec-builder/src/main.rs b/test-utils/chain-spec-builder/src/main.rs index f0e9ef066ffc5c3ae78869e7b58142d22c676e53..b899f9c1fcab73f863eeb4b4df799dbc8db723e9 100644 --- a/test-utils/chain-spec-builder/src/main.rs +++ b/test-utils/chain-spec-builder/src/main.rs @@ -1,11 +1,4 @@ -#[macro_use] -extern crate clap; - -use clap::App; - -extern crate node_cli; -extern crate substrate_service; -extern crate substrate_primitives; +use clap::{App, load_yaml}; use node_cli::chain_spec; use substrate_service::chain_ops::build_spec;